mirror of
https://github.com/YosysHQ/yosys
synced 2026-06-27 02:58:48 +00:00
commit
80d00e2f44
37 changed files with 889 additions and 467 deletions
16
CHANGELOG
16
CHANGELOG
|
|
@ -2,9 +2,23 @@
|
|||
List of major changes and improvements between releases
|
||||
=======================================================
|
||||
|
||||
Yosys 0.39 .. Yosys 0.40-dev
|
||||
Yosys 0.40 .. Yosys 0.41-dev
|
||||
--------------------------
|
||||
|
||||
Yosys 0.39 .. Yosys 0.40
|
||||
--------------------------
|
||||
* New commands and options
|
||||
- Added option "-vhdl2019" to "read" and "verific" pass.
|
||||
|
||||
* Various
|
||||
- Major documentation overhaul.
|
||||
- Added port statistics to "stat" command.
|
||||
- Added new formatting features to cxxrtl backend.
|
||||
|
||||
* Verific support
|
||||
- Added better support for VHDL constants import.
|
||||
- Added support for VHDL 2009.
|
||||
|
||||
Yosys 0.38 .. Yosys 0.39
|
||||
--------------------------
|
||||
* New commands and options
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
# PATH (can use glob) USERNAME(S)
|
||||
|
||||
CODEOWNERS @nakengelhardt
|
||||
passes/cmds/scratchpad.cc @nakengelhardt
|
||||
frontends/rpc/ @whitequark
|
||||
backends/cxxrtl/ @whitequark
|
||||
|
|
@ -19,7 +20,7 @@ passes/opt/opt_lut.cc @whitequark
|
|||
passes/techmap/abc9*.cc @eddiehung @Ravenslofty
|
||||
backends/aiger/xaiger.cc @eddiehung
|
||||
docs/ @KrystalDelusion
|
||||
|
||||
.github/workflows/*.yml @mmicko
|
||||
|
||||
## External Contributors
|
||||
# Only users with write permission to the repository get review
|
||||
|
|
|
|||
34
Makefile
34
Makefile
|
|
@ -142,7 +142,7 @@ LIBS += -lrt
|
|||
endif
|
||||
endif
|
||||
|
||||
YOSYS_VER := 0.39+149
|
||||
YOSYS_VER := 0.40+7
|
||||
|
||||
# Note: We arrange for .gitcommit to contain the (short) commit hash in
|
||||
# tarballs generated with git-archive(1) using .gitattributes. The git repo
|
||||
|
|
@ -158,7 +158,7 @@ endif
|
|||
OBJS = kernel/version_$(GIT_REV).o
|
||||
|
||||
bumpversion:
|
||||
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 0033808.. | wc -l`/;" Makefile
|
||||
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline a1bb025.. | wc -l`/;" Makefile
|
||||
|
||||
# set 'ABCREV = default' to use abc/ as it is
|
||||
#
|
||||
|
|
@ -629,6 +629,7 @@ $(eval $(call add_include_file,kernel/sigtools.h))
|
|||
$(eval $(call add_include_file,kernel/timinginfo.h))
|
||||
$(eval $(call add_include_file,kernel/utils.h))
|
||||
$(eval $(call add_include_file,kernel/yosys.h))
|
||||
$(eval $(call add_include_file,kernel/yosys_common.h))
|
||||
$(eval $(call add_include_file,kernel/yw.h))
|
||||
$(eval $(call add_include_file,libs/ezsat/ezsat.h))
|
||||
$(eval $(call add_include_file,libs/ezsat/ezminisat.h))
|
||||
|
|
@ -984,16 +985,27 @@ docs/gen_images:
|
|||
$(Q) $(MAKE) -C docs images
|
||||
|
||||
DOCS_GUIDELINE_FILES := GettingStarted CodingStyle
|
||||
docs/guidelines:
|
||||
$(Q) mkdir -p docs/source/temp
|
||||
$(Q) cp -f $(addprefix guidelines/,$(DOCS_GUIDELINE_FILES)) docs/source/temp
|
||||
docs/guidelines docs/source/generated:
|
||||
$(Q) mkdir -p docs/source/generated
|
||||
$(Q) cp -f $(addprefix guidelines/,$(DOCS_GUIDELINE_FILES)) docs/source/generated
|
||||
|
||||
# many of these will return an error which can be safely ignored, so we prefix
|
||||
# the command with a '-'
|
||||
DOCS_USAGE_PROGS := yosys yosys-config yosys-filterlib yosys-abc yosys-smtbmc yosys-witness
|
||||
docs/usage: $(addprefix docs/source/temp/,$(DOCS_USAGE_PROGS))
|
||||
docs/source/temp/%: docs/guidelines
|
||||
-$(Q) ./$(PROGRAM_PREFIX)$* --help > $@ 2>&1
|
||||
# some commands return an error and print the usage text to stderr
|
||||
define DOC_USAGE_STDERR
|
||||
docs/source/generated/$(1): $(PROGRAM_PREFIX)$(1) docs/source/generated
|
||||
-$(Q) ./$$< --help 2> $$@
|
||||
endef
|
||||
DOCS_USAGE_STDERR := yosys-config yosys-filterlib yosys-abc
|
||||
$(foreach usage,$(DOCS_USAGE_STDERR),$(eval $(call DOC_USAGE_STDERR,$(usage))))
|
||||
|
||||
# others print to stdout
|
||||
define DOC_USAGE_STDOUT
|
||||
docs/source/generated/$(1): $(PROGRAM_PREFIX)$(1) docs/source/generated
|
||||
$(Q) ./$$< --help > $$@
|
||||
endef
|
||||
DOCS_USAGE_STDOUT := yosys yosys-smtbmc yosys-witness
|
||||
$(foreach usage,$(DOCS_USAGE_STDOUT),$(eval $(call DOC_USAGE_STDOUT,$(usage))))
|
||||
|
||||
docs/usage: $(addprefix docs/source/generated/,$(DOCS_USAGE_STDOUT) $(DOCS_USAGE_STDERR))
|
||||
|
||||
docs/reqs:
|
||||
$(Q) $(MAKE) -C docs reqs
|
||||
|
|
|
|||
|
|
@ -2014,22 +2014,29 @@ void dump_sync_effect(std::ostream &f, std::string indent, const RTLIL::SigSpec
|
|||
|
||||
void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
|
||||
{
|
||||
if (simple_lhs) {
|
||||
bool all_chunks_wires = true;
|
||||
for (auto &chunk : left.chunks())
|
||||
if (chunk.is_wire() && reg_wires.count(chunk.wire->name))
|
||||
all_chunks_wires = false;
|
||||
if (!simple_lhs && all_chunks_wires) {
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
dump_sigspec(f, left);
|
||||
f << stringf(" = ");
|
||||
dump_sigspec(f, right);
|
||||
f << stringf(";\n");
|
||||
} else {
|
||||
int offset = 0;
|
||||
for (auto &chunk : left.chunks()) {
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
if (chunk.is_wire() && reg_wires.count(chunk.wire->name))
|
||||
f << stringf("%s" "always%s\n%s ", indent.c_str(), systemverilog ? "_comb" : " @*", indent.c_str());
|
||||
else
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
dump_sigspec(f, chunk);
|
||||
f << stringf(" = ");
|
||||
dump_sigspec(f, right.extract(offset, GetSize(chunk)));
|
||||
f << stringf(";\n");
|
||||
offset += GetSize(chunk);
|
||||
}
|
||||
} else {
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
dump_sigspec(f, left);
|
||||
f << stringf(" = ");
|
||||
dump_sigspec(f, right);
|
||||
f << stringf(";\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
2
docs/.gitignore
vendored
2
docs/.gitignore
vendored
|
|
@ -1,6 +1,6 @@
|
|||
/build/
|
||||
/source/cmd
|
||||
/source/temp
|
||||
/source/generated
|
||||
/source/_images/**/*.log
|
||||
/source/_images/**/*.aux
|
||||
/source/_images/**/*.pdf
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ help:
|
|||
clean: clean-examples
|
||||
rm -rf $(BUILDDIR)/*
|
||||
rm -rf source/cmd util/__pycache__
|
||||
rm -rf source/generated
|
||||
$(MAKE) -C source/_images clean
|
||||
|
||||
.PHONY: html
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ The ``yosys-config`` tool (an auto-generated shell-script) can be used to query
|
|||
compiler options and other information needed for building loadable modules for
|
||||
Yosys. See :doc:`/yosys_internals/extending_yosys/extensions` for details.
|
||||
|
||||
.. literalinclude:: /temp/yosys-config
|
||||
.. literalinclude:: /generated/yosys-config
|
||||
:start-at: Usage
|
||||
|
||||
.. _sec:filterlib:
|
||||
|
|
@ -25,7 +25,7 @@ The ``yosys-filterlib`` tool is a small utility that can be used to strip or
|
|||
extract information from a Liberty file. This can be useful for removing
|
||||
sensitive or proprietary information such as timing or other trade secrets.
|
||||
|
||||
.. literalinclude:: /temp/yosys-filterlib
|
||||
.. literalinclude:: /generated/yosys-filterlib
|
||||
:start-at: Usage
|
||||
|
||||
yosys-abc
|
||||
|
|
@ -36,9 +36,8 @@ been accepted upstream. Not all versions of Yosys work with all versions of ABC.
|
|||
So Yosys comes with its own yosys-abc to avoid compatibility issues between the
|
||||
two.
|
||||
|
||||
.. literalinclude:: /temp/yosys-abc
|
||||
.. literalinclude:: /generated/yosys-abc
|
||||
:start-at: usage
|
||||
:end-before: UC Berkeley
|
||||
|
||||
yosys-smtbmc
|
||||
------------
|
||||
|
|
@ -46,7 +45,7 @@ yosys-smtbmc
|
|||
The ``yosys-smtbmc`` tool is a utility used by SBY for interacting with smt
|
||||
solvers.
|
||||
|
||||
.. literalinclude:: /temp/yosys-smtbmc
|
||||
.. literalinclude:: /generated/yosys-smtbmc
|
||||
|
||||
yosys-witness
|
||||
-------------
|
||||
|
|
@ -55,7 +54,7 @@ yosys-witness
|
|||
This is used in SBY and SCY for producing traces in a consistent format
|
||||
independent of the solver.
|
||||
|
||||
.. literalinclude:: /temp/yosys-witness
|
||||
.. literalinclude:: /generated/yosys-witness
|
||||
:start-at: Usage
|
||||
|
||||
.. note:: ``yosys-witness`` requires `click`_ Python package for use.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
Command line reference
|
||||
================================================================================
|
||||
|
||||
.. literalinclude:: /temp/yosys
|
||||
.. literalinclude:: /generated/yosys
|
||||
:start-at: Usage
|
||||
|
||||
.. toctree::
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
my_cmd.so
|
||||
my_cmd.d
|
||||
*.log
|
||||
|
|
|
|||
|
|
@ -13,18 +13,18 @@ my_cmd.so: my_cmd.cc
|
|||
$(YOSYS)-config --exec --cxx $(subst $(DATDIR),../../../../share,$(CXXFLAGS)) --ldflags -o my_cmd.so -shared my_cmd.cc --ldlibs
|
||||
|
||||
test0.log: my_cmd.so
|
||||
$(YOSYS) -Ql test0.log_new -m ./my_cmd.so -p 'my_cmd foo bar' absval_ref.v
|
||||
$(YOSYS) -QTl test0.log_new -m ./my_cmd.so -p 'my_cmd foo bar' -f verilog absval_ref.v
|
||||
mv test0.log_new test0.log
|
||||
|
||||
test1.log: my_cmd.so
|
||||
$(YOSYS) -Ql test1.log_new -m ./my_cmd.so -p 'clean; test1; dump' absval_ref.v
|
||||
$(YOSYS) -QTl test1.log_new -m ./my_cmd.so -p 'clean; test1; dump' -f verilog absval_ref.v
|
||||
mv test1.log_new test1.log
|
||||
|
||||
test1.dot: my_cmd.so
|
||||
$(YOSYS) -m ./my_cmd.so -p 'test1; show -format dot -prefix test1'
|
||||
|
||||
test2.log: my_cmd.so
|
||||
$(YOSYS) -Ql test2.log_new -m ./my_cmd.so -p 'hierarchy -top test; test2' sigmap_test.v
|
||||
$(YOSYS) -QTl test2.log_new -m ./my_cmd.so -p 'hierarchy -top test; test2' -f verilog sigmap_test.v
|
||||
mv test2.log_new test2.log
|
||||
|
||||
.PHONY: clean
|
||||
|
|
|
|||
|
|
@ -619,6 +619,48 @@ Finite state machines
|
|||
|
||||
Add a brief description of the ``$fsm`` cell type.
|
||||
|
||||
Coarse arithmetics
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``$macc`` cell type represents a generalized multiply and accumulate operation. The cell is purely combinational. It outputs the result of summing up a sequence of products and other injected summands.
|
||||
|
||||
.. code-block::
|
||||
|
||||
Y = 0 +- a0factor1 * a0factor2 +- a1factor1 * a1factor2 +- ...
|
||||
+ B[0] + B[1] + ...
|
||||
|
||||
The A port consists of concatenated pairs of multiplier inputs ("factors").
|
||||
A zero length factor2 acts as a constant 1, turning factor1 into a simple summand.
|
||||
|
||||
In this pseudocode, ``u(foo)`` means an unsigned int that's foo bits long.
|
||||
|
||||
.. code-block::
|
||||
|
||||
struct A {
|
||||
u(CONFIG.mul_info[0].factor1_len) a0factor1;
|
||||
u(CONFIG.mul_info[0].factor2_len) a0factor2;
|
||||
u(CONFIG.mul_info[1].factor1_len) a1factor1;
|
||||
u(CONFIG.mul_info[1].factor2_len) a1factor2;
|
||||
...
|
||||
};
|
||||
|
||||
The cell's ``CONFIG`` parameter determines the layout of cell port ``A``.
|
||||
The CONFIG parameter carries the following information:
|
||||
|
||||
.. code-block::
|
||||
|
||||
struct CONFIG {
|
||||
u4 num_bits;
|
||||
struct mul_info {
|
||||
bool is_signed;
|
||||
bool is_subtract;
|
||||
u(num_bits) factor1_len;
|
||||
u(num_bits) factor2_len;
|
||||
}[num_ports];
|
||||
};
|
||||
|
||||
B is an array of concatenated 1-bit-wide unsigned integers to also be summed up.
|
||||
|
||||
Specify rules
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
|
@ -1152,4 +1194,4 @@ file via ABC using the abc pass.
|
|||
|
||||
.. todo:: Add information about ``$lut`` and ``$sop`` cells.
|
||||
|
||||
.. todo:: Add information about ``$alu``, ``$macc``, ``$fa``, and ``$lcu`` cells.
|
||||
.. todo:: Add information about ``$alu``, ``$fa``, and ``$lcu`` cells.
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ ifneq ($(DISABLE_VERIFIC_VHDL),1)
|
|||
$(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_1987/. share/verific.new/vhdl_vdbs_1987
|
||||
$(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_1993/. share/verific.new/vhdl_vdbs_1993
|
||||
$(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_2008/. share/verific.new/vhdl_vdbs_2008
|
||||
$(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_2019/. share/verific.new/vhdl_vdbs_2019
|
||||
endif
|
||||
$(Q) chmod -R a+rX share/verific.new
|
||||
$(Q) mv share/verific.new share/verific
|
||||
|
|
|
|||
|
|
@ -214,23 +214,120 @@ RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj)
|
|||
return s;
|
||||
}
|
||||
|
||||
// When used as attributes or parameter values Verific constants come already processed.
|
||||
// - Real string values are already under quotes
|
||||
// - Numeric values with specified width are always converted to binary
|
||||
// - Rest of user defined values are handled as 32bit integers
|
||||
// - There could be some internal values that are strings without quotes
|
||||
// so we check if value is all digits or not
|
||||
//
|
||||
// Note: For signed values, verific uses <len>'sb<bits> and decimal values can
|
||||
// also be negative.
|
||||
static const RTLIL::Const verific_const(const char *value, bool allow_string = true, bool output_signed = false)
|
||||
RTLIL::Const mkconst_str(const std::string &str)
|
||||
{
|
||||
size_t found;
|
||||
RTLIL::Const val;
|
||||
std::vector<RTLIL::State> data;
|
||||
data.reserve(str.size() * 8);
|
||||
for (size_t i = 0; i < str.size(); i++) {
|
||||
unsigned char ch = str[str.size() - i - 1];
|
||||
for (int j = 0; j < 8; j++) {
|
||||
data.push_back((ch & 1) ? State::S1 : State::S0);
|
||||
ch = ch >> 1;
|
||||
}
|
||||
}
|
||||
val.bits = data;
|
||||
val.flags |= RTLIL::CONST_FLAG_STRING;
|
||||
return val;
|
||||
}
|
||||
|
||||
static const RTLIL::Const extract_vhdl_boolean(std::string &val)
|
||||
{
|
||||
if (val == "false")
|
||||
return RTLIL::Const::from_string("0");
|
||||
if (val == "true")
|
||||
return RTLIL::Const::from_string("1");
|
||||
log_error("Expecting VHDL boolean value.\n");
|
||||
}
|
||||
|
||||
static const RTLIL::Const extract_vhdl_bit(std::string &val, std::string &typ)
|
||||
{
|
||||
if (val.size()==3 && val[0]=='\'' && val.back()=='\'')
|
||||
return RTLIL::Const::from_string(val.substr(1,val.size()-2));
|
||||
log_error("Error parsing VHDL %s.\n", typ.c_str());
|
||||
}
|
||||
|
||||
static const RTLIL::Const extract_vhdl_bit_vector(std::string &val, std::string &typ)
|
||||
{
|
||||
if (val.size()>1 && val[0]=='\"' && val.back()=='\"') {
|
||||
RTLIL::Const c = RTLIL::Const::from_string(val.substr(1,val.size()-2));
|
||||
if (typ == "signed")
|
||||
c.flags |= RTLIL::CONST_FLAG_SIGNED;
|
||||
return c;
|
||||
}
|
||||
log_error("Error parsing VHDL %s.\n", typ.c_str());
|
||||
}
|
||||
|
||||
static const RTLIL::Const extract_vhdl_integer(std::string &val)
|
||||
{
|
||||
char *end;
|
||||
return RTLIL::Const((int)std::strtol(val.c_str(), &end, 10), 32);
|
||||
}
|
||||
|
||||
static const RTLIL::Const extract_vhdl_char(std::string &val)
|
||||
{
|
||||
if (val.size()==3 && val[0]=='\"' && val.back()=='\"')
|
||||
return RTLIL::Const((int)val[1], 32);
|
||||
log_error("Error parsing VHDL character.\n");
|
||||
}
|
||||
|
||||
static const RTLIL::Const extract_real_value(std::string &val)
|
||||
{
|
||||
RTLIL::Const c = mkconst_str(val);
|
||||
c.flags |= RTLIL::CONST_FLAG_REAL;
|
||||
return c;
|
||||
}
|
||||
|
||||
static const RTLIL::Const extract_vhdl_string(std::string &val)
|
||||
{
|
||||
if (!(val.size()>1 && val[0]=='\"' && val.back()=='\"'))
|
||||
log_error("Error parsing VHDL string.\n");
|
||||
return RTLIL::Const(val.substr(1,val.size()-2));
|
||||
}
|
||||
|
||||
static const RTLIL::Const extract_vhdl_const(const char *value, bool output_signed)
|
||||
{
|
||||
RTLIL::Const c;
|
||||
char *end;
|
||||
int decimal;
|
||||
bool is_signed = false;
|
||||
RTLIL::Const c;
|
||||
std::string val = std::string(value);
|
||||
|
||||
if (val.size()>1 && val[0]=='\"' && val.back()=='\"') {
|
||||
std::string data = val.substr(1,val.size()-2);
|
||||
bool isBinary = std::all_of(data.begin(), data.end(), [](char c) {return c=='1' || c=='0'; });
|
||||
if (isBinary)
|
||||
c = RTLIL::Const::from_string(data);
|
||||
else
|
||||
c = RTLIL::Const(data);
|
||||
} else if (val.size()==3 && val[0]=='\'' && val.back()=='\'') {
|
||||
c = RTLIL::Const::from_string(val.substr(1,val.size()-2));
|
||||
} else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) &&
|
||||
((decimal = std::strtol(value, &end, 10)), !end[0])) {
|
||||
is_signed = output_signed;
|
||||
c = RTLIL::Const((int)decimal, 32);
|
||||
} else if (val == "false") {
|
||||
c = RTLIL::Const::from_string("0");
|
||||
} else if (val == "true") {
|
||||
c = RTLIL::Const::from_string("1");
|
||||
} else {
|
||||
c = mkconst_str(val);
|
||||
log_warning("encoding value '%s' as string.\n", value);
|
||||
}
|
||||
if (is_signed)
|
||||
c.flags |= RTLIL::CONST_FLAG_SIGNED;
|
||||
return c;
|
||||
}
|
||||
|
||||
static const RTLIL::Const extract_verilog_const(const char *value, bool allow_string, bool output_signed)
|
||||
{
|
||||
RTLIL::Const c;
|
||||
char *end;
|
||||
int decimal;
|
||||
bool is_signed = false;
|
||||
size_t found;
|
||||
std::string val = std::string(value);
|
||||
|
||||
if (allow_string && val.size()>1 && val[0]=='\"' && val.back()=='\"') {
|
||||
c = RTLIL::Const(val.substr(1,val.size()-2));
|
||||
} else if ((found = val.find("'sb")) != std::string::npos) {
|
||||
|
|
@ -245,15 +342,56 @@ static const RTLIL::Const verific_const(const char *value, bool allow_string = t
|
|||
} else if (allow_string) {
|
||||
c = RTLIL::Const(val);
|
||||
} else {
|
||||
log_error("expected numeric constant but found '%s'", value);
|
||||
c = mkconst_str(val);
|
||||
log_warning("encoding value '%s' as string.\n", value);
|
||||
}
|
||||
|
||||
if (is_signed)
|
||||
c.flags |= RTLIL::CONST_FLAG_SIGNED;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
// When used as attributes or parameter values Verific constants come already processed.
|
||||
// - Real string values are already under quotes
|
||||
// - Numeric values with specified width are always converted to binary
|
||||
// - Rest of user defined values are handled as 32bit integers
|
||||
// - There could be some internal values that are strings without quotes
|
||||
// so we check if value is all digits or not
|
||||
//
|
||||
// Note: For signed values, verific uses <len>'sb<bits> and decimal values can
|
||||
// also be negative.
|
||||
static const RTLIL::Const verific_const(const char* type_name, const char *value, DesignObj *obj, bool allow_string = true, bool output_signed = false)
|
||||
{
|
||||
std::string val = std::string(value);
|
||||
// VHDL
|
||||
if (obj->IsFromVhdl()) {
|
||||
if (type_name) {
|
||||
std::string typ = std::string(type_name);
|
||||
transform(typ.begin(), typ.end(), typ.begin(), ::tolower);
|
||||
if (typ == "integer" || typ == "natural" || typ=="positive") return extract_vhdl_integer(val);
|
||||
else if (typ =="boolean") return extract_vhdl_boolean(val);
|
||||
else if (typ == "bit" || typ =="std_logic" || typ == "std_ulogic") return extract_vhdl_bit(val,typ);
|
||||
else if (typ == "character") return extract_vhdl_char(val);
|
||||
else if (typ == "bit_vector" || typ == "std_logic_vector" || typ == "std_ulogic_vector" ||
|
||||
typ == "unsigned" || typ == "signed") return extract_vhdl_bit_vector(val,typ);
|
||||
else if (typ == "real") return extract_real_value(val);
|
||||
else if (typ == "string") return extract_vhdl_string(val);
|
||||
else {
|
||||
if (val.size()>1 && val[0]=='\"' && val.back()=='\"')
|
||||
return RTLIL::Const(val.substr(1,val.size()-2));
|
||||
else if (val.size()==3 && val[0]=='\'' && val.back()=='\'')
|
||||
return RTLIL::Const(val.substr(1,val.size()-2));
|
||||
else
|
||||
return RTLIL::Const(val);
|
||||
}
|
||||
} else extract_vhdl_const(value, output_signed);
|
||||
}
|
||||
// SystemVerilog
|
||||
if (type_name && strcmp(type_name, "real")==0) {
|
||||
return extract_real_value(val);
|
||||
} else
|
||||
return extract_verilog_const(value, allow_string, output_signed);
|
||||
}
|
||||
|
||||
static const std::string verific_unescape(const char *value)
|
||||
{
|
||||
std::string val = std::string(value);
|
||||
|
|
@ -276,7 +414,7 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
|
|||
FOREACH_ATTRIBUTE(obj, mi, attr) {
|
||||
if (attr->Key()[0] == ' ' || attr->Value() == nullptr)
|
||||
continue;
|
||||
attributes[RTLIL::escape_id(attr->Key())] = verific_const(attr->Value());
|
||||
attributes[RTLIL::escape_id(attr->Key())] = verific_const(nullptr, attr->Value(), obj);
|
||||
}
|
||||
|
||||
if (nl) {
|
||||
|
|
@ -298,7 +436,7 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
|
|||
const char *k, *v;
|
||||
FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mi, &k, &v) {
|
||||
if (nl->IsFromVerilog()) {
|
||||
auto const value = verific_const(v, false);
|
||||
auto const value = verific_const(type_name, v, nl, false);
|
||||
|
||||
attributes.emplace(stringf("\\enum_value_%s", value.as_string().c_str()), RTLIL::escape_id(k));
|
||||
}
|
||||
|
|
@ -1292,6 +1430,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
|
|||
}
|
||||
import_attributes(module->attributes, nl, nl);
|
||||
module->set_string_attribute(ID::hdlname, nl->CellBaseName());
|
||||
module->set_string_attribute(ID(library), nl->Owner()->Owner()->Name());
|
||||
#ifdef VERIFIC_VHDL_SUPPORT
|
||||
if (nl->IsFromVhdl()) {
|
||||
NameSpace name_space(0);
|
||||
|
|
@ -1304,7 +1443,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
|
|||
MapIter mi;
|
||||
FOREACH_PARAMETER_OF_NETLIST(nl, mi, param_name, param_value) {
|
||||
module->avail_parameters(RTLIL::escape_id(param_name));
|
||||
module->parameter_default_values[RTLIL::escape_id(param_name)] = verific_const(param_value);
|
||||
const TypeRange *tr = nl->GetTypeRange(param_name) ;
|
||||
module->parameter_default_values[RTLIL::escape_id(param_name)] = verific_const(tr->GetTypeName(), param_value, nl);
|
||||
}
|
||||
|
||||
SetIter si;
|
||||
|
|
@ -2004,7 +2144,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
|
|||
const char *param_value ;
|
||||
if (is_blackbox(inst->View())) {
|
||||
FOREACH_PARAMETER_OF_INST(inst, mi2, param_name, param_value) {
|
||||
cell->setParam(RTLIL::escape_id(param_name), verific_const(param_value));
|
||||
const TypeRange *tr = inst->View()->GetTypeRange(param_name) ;
|
||||
cell->setParam(RTLIL::escape_id(param_name), verific_const(tr->GetTypeName(), param_value, inst->View()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2699,7 +2840,7 @@ struct VerificPass : public Pass {
|
|||
log("\n");
|
||||
log("\n");
|
||||
#ifdef VERIFIC_VHDL_SUPPORT
|
||||
log(" verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
|
||||
log(" verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl2019|-vhdl} <vhdl-file>..\n");
|
||||
log("\n");
|
||||
log("Load the specified VHDL files into Verific.\n");
|
||||
log("\n");
|
||||
|
|
@ -3436,6 +3577,29 @@ struct VerificPass : public Pass {
|
|||
goto check_error;
|
||||
}
|
||||
|
||||
if (GetSize(args) > argidx && (args[argidx] == "-vhdl2019")) {
|
||||
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_2019").c_str());
|
||||
bool flag_lib = false;
|
||||
for (argidx++; argidx < GetSize(args); argidx++) {
|
||||
if (args[argidx] == "-lib") {
|
||||
flag_lib = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx].compare(0, 1, "-") == 0) {
|
||||
cmd_error(args, argidx, "unknown option");
|
||||
goto check_error;
|
||||
}
|
||||
Map map(POINTER_HASH);
|
||||
add_units_to_map(map, work, flag_lib);
|
||||
std::string filename = frontent_rewrite(args, argidx, tmp_files);
|
||||
if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_2019))
|
||||
log_cmd_error("Reading `%s' in VHDL_2019 mode failed.\n", filename.c_str());
|
||||
set_units_to_blackbox(map, work, flag_lib);
|
||||
}
|
||||
verific_import_pending = true;
|
||||
goto check_error;
|
||||
}
|
||||
|
||||
if (GetSize(args) > argidx && (args[argidx] == "-vhdl2008" || args[argidx] == "-vhdl")) {
|
||||
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_2008").c_str());
|
||||
bool flag_lib = false;
|
||||
|
|
@ -3979,7 +4143,7 @@ struct ReadPass : public Pass {
|
|||
log("\n");
|
||||
log("\n");
|
||||
#ifdef VERIFIC_VHDL_SUPPORT
|
||||
log(" read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
|
||||
log(" read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl2019|-vhdl} <vhdl-file>..\n");
|
||||
log("\n");
|
||||
log("Load the specified VHDL files. (Requires Verific.)\n");
|
||||
log("\n");
|
||||
|
|
@ -4083,7 +4247,7 @@ struct ReadPass : public Pass {
|
|||
}
|
||||
|
||||
#ifdef VERIFIC_VHDL_SUPPORT
|
||||
if (args[1] == "-vhdl87" || args[1] == "-vhdl93" || args[1] == "-vhdl2k" || args[1] == "-vhdl2008" || args[1] == "-vhdl") {
|
||||
if (args[1] == "-vhdl87" || args[1] == "-vhdl93" || args[1] == "-vhdl2k" || args[1] == "-vhdl2008" || args[1] == "-vhdl2019" || args[1] == "-vhdl") {
|
||||
if (use_verific) {
|
||||
args[0] = "verific";
|
||||
Pass::call(design, args);
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include "kernel/yosys_common.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <regex>
|
||||
|
|
@ -449,4 +449,6 @@ void log_dump_args_worker(const char *p, T first, Args ... args)
|
|||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,11 +17,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
|
||||
#ifndef REGISTER_H
|
||||
#define REGISTER_H
|
||||
|
||||
#include "kernel/yosys_common.h"
|
||||
#include "kernel/yosys.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
struct Pass
|
||||
|
|
|
|||
|
|
@ -17,11 +17,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
|
||||
#ifndef RTLIL_H
|
||||
#define RTLIL_H
|
||||
|
||||
#include "kernel/yosys_common.h"
|
||||
#include "kernel/yosys.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
namespace RTLIL
|
||||
|
|
|
|||
346
kernel/yosys.h
346
kernel/yosys.h
|
|
@ -39,323 +39,7 @@
|
|||
#ifndef YOSYS_H
|
||||
#define YOSYS_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
#ifndef _YOSYS_
|
||||
# error It looks like you are trying to build Yosys without the config defines set. \
|
||||
When building Yosys with a custom make system, make sure you set all the \
|
||||
defines the Yosys Makefile would set for your build configuration.
|
||||
#endif
|
||||
|
||||
#ifdef YOSYS_ENABLE_TCL
|
||||
# include <tcl.h>
|
||||
# ifdef YOSYS_MXE_HACKS
|
||||
extern Tcl_Command Tcl_CreateCommand(Tcl_Interp *interp, const char *cmdName, Tcl_CmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc);
|
||||
extern Tcl_Interp *Tcl_CreateInterp(void);
|
||||
extern void Tcl_Preserve(ClientData data);
|
||||
extern void Tcl_Release(ClientData clientData);
|
||||
extern int Tcl_InterpDeleted(Tcl_Interp *interp);
|
||||
extern void Tcl_DeleteInterp(Tcl_Interp *interp);
|
||||
extern int Tcl_Eval(Tcl_Interp *interp, const char *script);
|
||||
extern int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName);
|
||||
extern void Tcl_Finalize(void);
|
||||
extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr);
|
||||
extern const char *Tcl_GetStringResult(Tcl_Interp *interp);
|
||||
extern Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length);
|
||||
extern Tcl_Obj *Tcl_NewIntObj(int intValue);
|
||||
extern Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[]);
|
||||
extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags);
|
||||
# endif
|
||||
# undef CONST
|
||||
# undef INLINE
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# undef NOMINMAX
|
||||
# define NOMINMAX 1
|
||||
# undef YY_NO_UNISTD_H
|
||||
# define YY_NO_UNISTD_H 1
|
||||
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# include <direct.h>
|
||||
|
||||
# define strtok_r strtok_s
|
||||
# define strdup _strdup
|
||||
# define snprintf _snprintf
|
||||
# define getcwd _getcwd
|
||||
# define mkdir _mkdir
|
||||
# define popen _popen
|
||||
# define pclose _pclose
|
||||
|
||||
# ifndef __MINGW32__
|
||||
# define PATH_MAX MAX_PATH
|
||||
# define isatty _isatty
|
||||
# define fileno _fileno
|
||||
# endif
|
||||
|
||||
// The following defines conflict with our identifiers:
|
||||
# undef CONST
|
||||
// `wingdi.h` defines a TRANSPARENT macro that conflicts with X(TRANSPARENT) entry in kernel/constids.inc
|
||||
# undef TRANSPARENT
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
#define YOSYS_NAMESPACE Yosys
|
||||
#define PRIVATE_NAMESPACE_BEGIN namespace {
|
||||
#define PRIVATE_NAMESPACE_END }
|
||||
#define YOSYS_NAMESPACE_BEGIN namespace Yosys {
|
||||
#define YOSYS_NAMESPACE_END }
|
||||
#define YOSYS_NAMESPACE_PREFIX Yosys::
|
||||
#define USING_YOSYS_NAMESPACE using namespace Yosys;
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define YS_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
|
||||
#elif defined(_MSC_VER)
|
||||
# define YS_ATTRIBUTE(...)
|
||||
#else
|
||||
# define YS_ATTRIBUTE(...)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define YS_MAYBE_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
# define YS_MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
# define YS_FALLTHROUGH [[fallthrough]];
|
||||
#elif defined(__clang__)
|
||||
# define YS_FALLTHROUGH [[clang::fallthrough]];
|
||||
#elif defined(__GNUC__)
|
||||
# define YS_FALLTHROUGH [[gnu::fallthrough]];
|
||||
#else
|
||||
# define YS_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
// Note: All headers included in hashlib.h must be included
|
||||
// outside of YOSYS_NAMESPACE before this or bad things will happen.
|
||||
#ifdef HASHLIB_H
|
||||
# undef HASHLIB_H
|
||||
# include "kernel/hashlib.h"
|
||||
#else
|
||||
# include "kernel/hashlib.h"
|
||||
# undef HASHLIB_H
|
||||
#endif
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::tuple;
|
||||
using std::pair;
|
||||
|
||||
using std::make_tuple;
|
||||
using std::make_pair;
|
||||
using std::get;
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
// A primitive shared string implementation that does not
|
||||
// move its .c_str() when the object is copied or moved.
|
||||
struct shared_str {
|
||||
std::shared_ptr<string> content;
|
||||
shared_str() { }
|
||||
shared_str(string s) { content = std::shared_ptr<string>(new string(s)); }
|
||||
shared_str(const char *s) { content = std::shared_ptr<string>(new string(s)); }
|
||||
const char *c_str() const { return content->c_str(); }
|
||||
const string &str() const { return *content; }
|
||||
bool operator==(const shared_str &other) const { return *content == *other.content; }
|
||||
unsigned int hash() const { return hashlib::hash_ops<std::string>::hash(*content); }
|
||||
};
|
||||
|
||||
using hashlib::mkhash;
|
||||
using hashlib::mkhash_init;
|
||||
using hashlib::mkhash_add;
|
||||
using hashlib::mkhash_xorshift;
|
||||
using hashlib::hash_ops;
|
||||
using hashlib::hash_cstr_ops;
|
||||
using hashlib::hash_ptr_ops;
|
||||
using hashlib::hash_obj_ops;
|
||||
using hashlib::dict;
|
||||
using hashlib::idict;
|
||||
using hashlib::pool;
|
||||
using hashlib::mfp;
|
||||
|
||||
namespace RTLIL {
|
||||
struct IdString;
|
||||
struct Const;
|
||||
struct SigBit;
|
||||
struct SigSpec;
|
||||
struct Wire;
|
||||
struct Cell;
|
||||
struct Memory;
|
||||
struct Process;
|
||||
struct Module;
|
||||
struct Design;
|
||||
struct Monitor;
|
||||
enum State : unsigned char;
|
||||
}
|
||||
|
||||
namespace AST {
|
||||
struct AstNode;
|
||||
}
|
||||
|
||||
using RTLIL::IdString;
|
||||
using RTLIL::Const;
|
||||
using RTLIL::SigBit;
|
||||
using RTLIL::SigSpec;
|
||||
using RTLIL::Wire;
|
||||
using RTLIL::Cell;
|
||||
using RTLIL::Module;
|
||||
using RTLIL::Design;
|
||||
|
||||
namespace hashlib {
|
||||
template<> struct hash_ops<RTLIL::Wire*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Cell*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Memory*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Process*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Module*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Design*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Monitor*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<AST::AstNode*> : hash_obj_ops {};
|
||||
|
||||
template<> struct hash_ops<const RTLIL::Wire*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Cell*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Memory*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Process*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Module*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Design*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Monitor*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const AST::AstNode*> : hash_obj_ops {};
|
||||
}
|
||||
|
||||
void memhasher_on();
|
||||
void memhasher_off();
|
||||
void memhasher_do();
|
||||
|
||||
extern bool memhasher_active;
|
||||
inline void memhasher() { if (memhasher_active) memhasher_do(); }
|
||||
|
||||
void yosys_banner();
|
||||
int ceil_log2(int x) YS_ATTRIBUTE(const);
|
||||
|
||||
inline std::string vstringf(const char *fmt, va_list ap)
|
||||
{
|
||||
// For the common case of strings shorter than 128, save a heap
|
||||
// allocation by using a stack allocated buffer.
|
||||
const int kBufSize = 128;
|
||||
char buf[kBufSize];
|
||||
buf[0] = '\0';
|
||||
va_list apc;
|
||||
va_copy(apc, ap);
|
||||
int n = vsnprintf(buf, kBufSize, fmt, apc);
|
||||
va_end(apc);
|
||||
if (n < kBufSize)
|
||||
return std::string(buf);
|
||||
|
||||
std::string string;
|
||||
char *str = NULL;
|
||||
#if defined(_WIN32 )|| defined(__CYGWIN__)
|
||||
int sz = 2 * kBufSize, rc;
|
||||
while (1) {
|
||||
va_copy(apc, ap);
|
||||
str = (char*)realloc(str, sz);
|
||||
rc = vsnprintf(str, sz, fmt, apc);
|
||||
va_end(apc);
|
||||
if (rc >= 0 && rc < sz)
|
||||
break;
|
||||
sz *= 2;
|
||||
}
|
||||
if (str != NULL) {
|
||||
string = str;
|
||||
free(str);
|
||||
}
|
||||
return string;
|
||||
#else
|
||||
if (vasprintf(&str, fmt, ap) < 0)
|
||||
str = NULL;
|
||||
if (str != NULL) {
|
||||
string = str;
|
||||
free(str);
|
||||
}
|
||||
return string;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string stringf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 1, 2));
|
||||
|
||||
inline std::string stringf(const char *fmt, ...)
|
||||
{
|
||||
std::string string;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
string = vstringf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
int readsome(std::istream &f, char *s, int n);
|
||||
std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false);
|
||||
std::vector<std::string> split_tokens(const std::string &text, const char *sep = " \t\r\n");
|
||||
bool patmatch(const char *pattern, const char *string);
|
||||
#if !defined(YOSYS_DISABLE_SPAWN)
|
||||
int run_command(const std::string &command, std::function<void(const std::string&)> process_line = std::function<void(const std::string&)>());
|
||||
#endif
|
||||
std::string get_base_tmpdir();
|
||||
std::string make_temp_file(std::string template_str = get_base_tmpdir() + "/yosys_XXXXXX");
|
||||
std::string make_temp_dir(std::string template_str = get_base_tmpdir() + "/yosys_XXXXXX");
|
||||
bool check_file_exists(std::string filename, bool is_exec = false);
|
||||
bool check_directory_exists(const std::string& dirname);
|
||||
bool is_absolute_path(std::string filename);
|
||||
void remove_directory(std::string dirname);
|
||||
bool create_directory(const std::string& dirname);
|
||||
std::string escape_filename_spaces(const std::string& filename);
|
||||
|
||||
template<typename T> int GetSize(const T &obj) { return obj.size(); }
|
||||
inline int GetSize(RTLIL::Wire *wire);
|
||||
|
||||
extern int autoidx;
|
||||
extern int yosys_xtrace;
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
#include "kernel/yosys_common.h"
|
||||
|
||||
#include "kernel/log.h"
|
||||
#include "kernel/rtlil.h"
|
||||
|
|
@ -363,14 +47,6 @@ YOSYS_NAMESPACE_END
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
using RTLIL::State;
|
||||
using RTLIL::SigChunk;
|
||||
using RTLIL::SigSig;
|
||||
|
||||
namespace hashlib {
|
||||
template<> struct hash_ops<RTLIL::State> : hash_ops<int> {};
|
||||
}
|
||||
|
||||
void yosys_setup();
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
|
|
@ -385,26 +61,6 @@ Tcl_Interp *yosys_get_tcl_interp();
|
|||
|
||||
extern RTLIL::Design *yosys_design;
|
||||
|
||||
RTLIL::IdString new_id(std::string file, int line, std::string func);
|
||||
RTLIL::IdString new_id_suffix(std::string file, int line, std::string func, std::string suffix);
|
||||
|
||||
#define NEW_ID \
|
||||
YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__)
|
||||
#define NEW_ID_SUFFIX(suffix) \
|
||||
YOSYS_NAMESPACE_PREFIX new_id_suffix(__FILE__, __LINE__, __FUNCTION__, suffix)
|
||||
|
||||
// Create a statically allocated IdString object, using for example ID::A or ID($add).
|
||||
//
|
||||
// Recipe for Converting old code that is using conversion of strings like ID::A and
|
||||
// "$add" for creating IdStrings: Run below SED command on the .cc file and then use for
|
||||
// example "meld foo.cc foo.cc.orig" to manually compile errors, if necessary.
|
||||
//
|
||||
// sed -i.orig -r 's/"\\\\([a-zA-Z0-9_]+)"/ID(\1)/g; s/"(\$[a-zA-Z0-9_]+)"/ID(\1)/g;' <filename>
|
||||
//
|
||||
#define ID(_id) ([]() { const char *p = "\\" #_id, *q = p[1] == '$' ? p+1 : p; \
|
||||
static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id(q); return id; })()
|
||||
namespace ID = RTLIL::ID;
|
||||
|
||||
RTLIL::Design *yosys_get_design();
|
||||
std::string proc_self_dirname();
|
||||
std::string proc_share_dirname();
|
||||
|
|
|
|||
379
kernel/yosys_common.h
Normal file
379
kernel/yosys_common.h
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
/* -*- c++ -*-
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef YOSYS_COMMON_H
|
||||
#define YOSYS_COMMON_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
#ifndef _YOSYS_
|
||||
# error It looks like you are trying to build Yosys without the config defines set. \
|
||||
When building Yosys with a custom make system, make sure you set all the \
|
||||
defines the Yosys Makefile would set for your build configuration.
|
||||
#endif
|
||||
|
||||
#ifdef YOSYS_ENABLE_TCL
|
||||
# include <tcl.h>
|
||||
# ifdef YOSYS_MXE_HACKS
|
||||
extern Tcl_Command Tcl_CreateCommand(Tcl_Interp *interp, const char *cmdName, Tcl_CmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc);
|
||||
extern Tcl_Interp *Tcl_CreateInterp(void);
|
||||
extern void Tcl_Preserve(ClientData data);
|
||||
extern void Tcl_Release(ClientData clientData);
|
||||
extern int Tcl_InterpDeleted(Tcl_Interp *interp);
|
||||
extern void Tcl_DeleteInterp(Tcl_Interp *interp);
|
||||
extern int Tcl_Eval(Tcl_Interp *interp, const char *script);
|
||||
extern int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName);
|
||||
extern void Tcl_Finalize(void);
|
||||
extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr);
|
||||
extern const char *Tcl_GetStringResult(Tcl_Interp *interp);
|
||||
extern Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length);
|
||||
extern Tcl_Obj *Tcl_NewIntObj(int intValue);
|
||||
extern Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[]);
|
||||
extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags);
|
||||
# endif
|
||||
# undef CONST
|
||||
# undef INLINE
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# undef NOMINMAX
|
||||
# define NOMINMAX 1
|
||||
# undef YY_NO_UNISTD_H
|
||||
# define YY_NO_UNISTD_H 1
|
||||
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# include <direct.h>
|
||||
|
||||
# define strtok_r strtok_s
|
||||
# define strdup _strdup
|
||||
# define snprintf _snprintf
|
||||
# define getcwd _getcwd
|
||||
# define mkdir _mkdir
|
||||
# define popen _popen
|
||||
# define pclose _pclose
|
||||
|
||||
# ifndef __MINGW32__
|
||||
# define PATH_MAX MAX_PATH
|
||||
# define isatty _isatty
|
||||
# define fileno _fileno
|
||||
# endif
|
||||
|
||||
// The following defines conflict with our identifiers:
|
||||
# undef CONST
|
||||
// `wingdi.h` defines a TRANSPARENT macro that conflicts with X(TRANSPARENT) entry in kernel/constids.inc
|
||||
# undef TRANSPARENT
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
|
||||
#define YOSYS_NAMESPACE Yosys
|
||||
#define PRIVATE_NAMESPACE_BEGIN namespace {
|
||||
#define PRIVATE_NAMESPACE_END }
|
||||
#define YOSYS_NAMESPACE_BEGIN namespace Yosys {
|
||||
#define YOSYS_NAMESPACE_END }
|
||||
#define YOSYS_NAMESPACE_PREFIX Yosys::
|
||||
#define USING_YOSYS_NAMESPACE using namespace Yosys;
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define YS_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
|
||||
#elif defined(_MSC_VER)
|
||||
# define YS_ATTRIBUTE(...)
|
||||
#else
|
||||
# define YS_ATTRIBUTE(...)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define YS_MAYBE_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
# define YS_MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
# define YS_FALLTHROUGH [[fallthrough]];
|
||||
#elif defined(__clang__)
|
||||
# define YS_FALLTHROUGH [[clang::fallthrough]];
|
||||
#elif defined(__GNUC__)
|
||||
# define YS_FALLTHROUGH [[gnu::fallthrough]];
|
||||
#else
|
||||
# define YS_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
// Note: All headers included in hashlib.h must be included
|
||||
// outside of YOSYS_NAMESPACE before this or bad things will happen.
|
||||
#ifdef HASHLIB_H
|
||||
# undef HASHLIB_H
|
||||
# include "kernel/hashlib.h"
|
||||
#else
|
||||
# include "kernel/hashlib.h"
|
||||
# undef HASHLIB_H
|
||||
#endif
|
||||
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::tuple;
|
||||
using std::pair;
|
||||
|
||||
using std::make_tuple;
|
||||
using std::make_pair;
|
||||
using std::get;
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
// A primitive shared string implementation that does not
|
||||
// move its .c_str() when the object is copied or moved.
|
||||
struct shared_str {
|
||||
std::shared_ptr<string> content;
|
||||
shared_str() { }
|
||||
shared_str(string s) { content = std::shared_ptr<string>(new string(s)); }
|
||||
shared_str(const char *s) { content = std::shared_ptr<string>(new string(s)); }
|
||||
const char *c_str() const { return content->c_str(); }
|
||||
const string &str() const { return *content; }
|
||||
bool operator==(const shared_str &other) const { return *content == *other.content; }
|
||||
unsigned int hash() const { return hashlib::hash_ops<std::string>::hash(*content); }
|
||||
};
|
||||
|
||||
using hashlib::mkhash;
|
||||
using hashlib::mkhash_init;
|
||||
using hashlib::mkhash_add;
|
||||
using hashlib::mkhash_xorshift;
|
||||
using hashlib::hash_ops;
|
||||
using hashlib::hash_cstr_ops;
|
||||
using hashlib::hash_ptr_ops;
|
||||
using hashlib::hash_obj_ops;
|
||||
using hashlib::dict;
|
||||
using hashlib::idict;
|
||||
using hashlib::pool;
|
||||
using hashlib::mfp;
|
||||
|
||||
namespace RTLIL {
|
||||
struct IdString;
|
||||
struct Const;
|
||||
struct SigBit;
|
||||
struct SigSpec;
|
||||
struct Wire;
|
||||
struct Cell;
|
||||
struct Memory;
|
||||
struct Process;
|
||||
struct Module;
|
||||
struct Design;
|
||||
struct Monitor;
|
||||
struct Selection;
|
||||
struct SigChunk;
|
||||
enum State : unsigned char;
|
||||
|
||||
typedef std::pair<SigSpec, SigSpec> SigSig;
|
||||
|
||||
namespace ID {}
|
||||
}
|
||||
|
||||
namespace AST {
|
||||
struct AstNode;
|
||||
}
|
||||
|
||||
using RTLIL::IdString;
|
||||
using RTLIL::Const;
|
||||
using RTLIL::SigBit;
|
||||
using RTLIL::SigSpec;
|
||||
using RTLIL::Wire;
|
||||
using RTLIL::Cell;
|
||||
using RTLIL::Module;
|
||||
using RTLIL::Design;
|
||||
|
||||
using RTLIL::State;
|
||||
using RTLIL::SigChunk;
|
||||
using RTLIL::SigSig;
|
||||
|
||||
namespace hashlib {
|
||||
template<> struct hash_ops<RTLIL::Wire*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Cell*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Memory*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Process*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Module*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Design*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<RTLIL::Monitor*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<AST::AstNode*> : hash_obj_ops {};
|
||||
|
||||
template<> struct hash_ops<const RTLIL::Wire*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Cell*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Memory*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Process*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Module*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Design*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const RTLIL::Monitor*> : hash_obj_ops {};
|
||||
template<> struct hash_ops<const AST::AstNode*> : hash_obj_ops {};
|
||||
}
|
||||
|
||||
void memhasher_on();
|
||||
void memhasher_off();
|
||||
void memhasher_do();
|
||||
|
||||
extern bool memhasher_active;
|
||||
inline void memhasher() { if (memhasher_active) memhasher_do(); }
|
||||
|
||||
void yosys_banner();
|
||||
int ceil_log2(int x) YS_ATTRIBUTE(const);
|
||||
|
||||
inline std::string vstringf(const char *fmt, va_list ap)
|
||||
{
|
||||
// For the common case of strings shorter than 128, save a heap
|
||||
// allocation by using a stack allocated buffer.
|
||||
const int kBufSize = 128;
|
||||
char buf[kBufSize];
|
||||
buf[0] = '\0';
|
||||
va_list apc;
|
||||
va_copy(apc, ap);
|
||||
int n = vsnprintf(buf, kBufSize, fmt, apc);
|
||||
va_end(apc);
|
||||
if (n < kBufSize)
|
||||
return std::string(buf);
|
||||
|
||||
std::string string;
|
||||
char *str = NULL;
|
||||
#if defined(_WIN32 )|| defined(__CYGWIN__)
|
||||
int sz = 2 * kBufSize, rc;
|
||||
while (1) {
|
||||
va_copy(apc, ap);
|
||||
str = (char*)realloc(str, sz);
|
||||
rc = vsnprintf(str, sz, fmt, apc);
|
||||
va_end(apc);
|
||||
if (rc >= 0 && rc < sz)
|
||||
break;
|
||||
sz *= 2;
|
||||
}
|
||||
if (str != NULL) {
|
||||
string = str;
|
||||
free(str);
|
||||
}
|
||||
return string;
|
||||
#else
|
||||
if (vasprintf(&str, fmt, ap) < 0)
|
||||
str = NULL;
|
||||
if (str != NULL) {
|
||||
string = str;
|
||||
free(str);
|
||||
}
|
||||
return string;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string stringf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 1, 2));
|
||||
|
||||
inline std::string stringf(const char *fmt, ...)
|
||||
{
|
||||
std::string string;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
string = vstringf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
int readsome(std::istream &f, char *s, int n);
|
||||
std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false);
|
||||
std::vector<std::string> split_tokens(const std::string &text, const char *sep = " \t\r\n");
|
||||
bool patmatch(const char *pattern, const char *string);
|
||||
#if !defined(YOSYS_DISABLE_SPAWN)
|
||||
int run_command(const std::string &command, std::function<void(const std::string&)> process_line = std::function<void(const std::string&)>());
|
||||
#endif
|
||||
std::string get_base_tmpdir();
|
||||
std::string make_temp_file(std::string template_str = get_base_tmpdir() + "/yosys_XXXXXX");
|
||||
std::string make_temp_dir(std::string template_str = get_base_tmpdir() + "/yosys_XXXXXX");
|
||||
bool check_file_exists(std::string filename, bool is_exec = false);
|
||||
bool check_directory_exists(const std::string& dirname);
|
||||
bool is_absolute_path(std::string filename);
|
||||
void remove_directory(std::string dirname);
|
||||
bool create_directory(const std::string& dirname);
|
||||
std::string escape_filename_spaces(const std::string& filename);
|
||||
|
||||
template<typename T> int GetSize(const T &obj) { return obj.size(); }
|
||||
inline int GetSize(RTLIL::Wire *wire);
|
||||
|
||||
extern int autoidx;
|
||||
extern int yosys_xtrace;
|
||||
|
||||
RTLIL::IdString new_id(std::string file, int line, std::string func);
|
||||
RTLIL::IdString new_id_suffix(std::string file, int line, std::string func, std::string suffix);
|
||||
|
||||
#define NEW_ID \
|
||||
YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__)
|
||||
#define NEW_ID_SUFFIX(suffix) \
|
||||
YOSYS_NAMESPACE_PREFIX new_id_suffix(__FILE__, __LINE__, __FUNCTION__, suffix)
|
||||
|
||||
// Create a statically allocated IdString object, using for example ID::A or ID($add).
|
||||
//
|
||||
// Recipe for Converting old code that is using conversion of strings like ID::A and
|
||||
// "$add" for creating IdStrings: Run below SED command on the .cc file and then use for
|
||||
// example "meld foo.cc foo.cc.orig" to manually compile errors, if necessary.
|
||||
//
|
||||
// sed -i.orig -r 's/"\\\\([a-zA-Z0-9_]+)"/ID(\1)/g; s/"(\$[a-zA-Z0-9_]+)"/ID(\1)/g;' <filename>
|
||||
//
|
||||
#define ID(_id) ([]() { const char *p = "\\" #_id, *q = p[1] == '$' ? p+1 : p; \
|
||||
static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id(q); return id; })()
|
||||
namespace ID = RTLIL::ID;
|
||||
|
||||
namespace hashlib {
|
||||
template<> struct hash_ops<RTLIL::State> : hash_ops<int> {};
|
||||
}
|
||||
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
|
@ -36,7 +36,8 @@ struct cell_area_t {
|
|||
struct statdata_t
|
||||
{
|
||||
#define STAT_INT_MEMBERS X(num_wires) X(num_wire_bits) X(num_pub_wires) X(num_pub_wire_bits) \
|
||||
X(num_memories) X(num_memory_bits) X(num_cells) X(num_processes)
|
||||
X(num_ports) X(num_port_bits) X(num_memories) X(num_memory_bits) X(num_cells) \
|
||||
X(num_processes)
|
||||
|
||||
#define STAT_NUMERIC_MEMBERS STAT_INT_MEMBERS X(area)
|
||||
|
||||
|
|
@ -90,6 +91,11 @@ struct statdata_t
|
|||
|
||||
for (auto wire : mod->selected_wires())
|
||||
{
|
||||
if (wire->port_input || wire->port_output) {
|
||||
num_ports++;
|
||||
num_port_bits += wire->width;
|
||||
}
|
||||
|
||||
if (wire->name.isPublic()) {
|
||||
num_pub_wires++;
|
||||
num_pub_wire_bits += wire->width;
|
||||
|
|
@ -239,6 +245,8 @@ struct statdata_t
|
|||
log(" Number of wire bits: %6u\n", num_wire_bits);
|
||||
log(" Number of public wires: %6u\n", num_pub_wires);
|
||||
log(" Number of public wire bits: %6u\n", num_pub_wire_bits);
|
||||
log(" Number of ports: %6u\n", num_ports);
|
||||
log(" Number of port bits: %6u\n", num_port_bits);
|
||||
log(" Number of memories: %6u\n", num_memories);
|
||||
log(" Number of memory bits: %6u\n", num_memory_bits);
|
||||
log(" Number of processes: %6u\n", num_processes);
|
||||
|
|
@ -284,6 +292,8 @@ struct statdata_t
|
|||
log(" \"num_wire_bits\": %u,\n", num_wire_bits);
|
||||
log(" \"num_pub_wires\": %u,\n", num_pub_wires);
|
||||
log(" \"num_pub_wire_bits\": %u,\n", num_pub_wire_bits);
|
||||
log(" \"num_ports\": %u,\n", num_ports);
|
||||
log(" \"num_port_bits\": %u,\n", num_port_bits);
|
||||
log(" \"num_memories\": %u,\n", num_memories);
|
||||
log(" \"num_memory_bits\": %u,\n", num_memory_bits);
|
||||
log(" \"num_processes\": %u,\n", num_processes);
|
||||
|
|
@ -494,6 +504,8 @@ struct StatPass : public Pass {
|
|||
design->scratchpad_set_int("stat.num_wire_bits", data.num_wire_bits);
|
||||
design->scratchpad_set_int("stat.num_pub_wires", data.num_pub_wires);
|
||||
design->scratchpad_set_int("stat.num_pub_wire_bits", data.num_pub_wire_bits);
|
||||
design->scratchpad_set_int("stat.num_ports", data.num_ports);
|
||||
design->scratchpad_set_int("stat.num_port_bits", data.num_port_bits);
|
||||
design->scratchpad_set_int("stat.num_memories", data.num_memories);
|
||||
design->scratchpad_set_int("stat.num_memory_bits", data.num_memory_bits);
|
||||
design->scratchpad_set_int("stat.num_processes", data.num_processes);
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ struct MemoryMapPass : public Pass {
|
|||
log(" to any of the values.\n");
|
||||
log("\n");
|
||||
log(" -iattr\n");
|
||||
log(" for -attr, ignore case of <value>.\n");
|
||||
log(" for -attr, suppress case sensitivity in matching of <value>.\n");
|
||||
log("\n");
|
||||
log(" -rom-only\n");
|
||||
log(" only perform conversion for ROMs (memories with no write ports).\n");
|
||||
|
|
|
|||
|
|
@ -443,13 +443,6 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
|||
if (!raw_used_signals.check_any(s1)) {
|
||||
// delete wires that aren't used by anything directly
|
||||
goto delete_this_wire;
|
||||
} else
|
||||
if (!used_signals.check_any(s2)) {
|
||||
// this path shouldn't be possible: this wire is used directly (otherwise it would get cleaned up above), and indirectly
|
||||
// used wires are a superset of those used directly
|
||||
log_assert(false);
|
||||
// delete wires that aren't used by anything indirectly, even though other wires may alias it
|
||||
goto delete_this_wire;
|
||||
}
|
||||
|
||||
if (0)
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ struct OptDemorganPass : public Pass {
|
|||
{
|
||||
log_header(design, "Executing OPT_DEMORGAN pass (push inverters through $reduce_* cells).\n");
|
||||
|
||||
int argidx = 0;
|
||||
int argidx = 1;
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
unsigned int cells_changed = 0;
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ struct InitValWorker
|
|||
return true;
|
||||
if (ff.has_ce && initconst(ff.sig_ce.as_bit()) == (ff.pol_ce ? State::S0 : State::S1))
|
||||
continue;
|
||||
if (ff.has_srst && initconst(ff.sig_ce.as_bit()) == (ff.pol_srst ? State::S1 : State::S0))
|
||||
if (ff.has_srst && initconst(ff.sig_srst.as_bit()) == (ff.pol_srst ? State::S1 : State::S0))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -35,3 +35,4 @@ $(eval $(call add_share_file,share,techlibs/common/abc9_map.v))
|
|||
$(eval $(call add_share_file,share,techlibs/common/abc9_unmap.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/cmp2softlogic.v))
|
||||
$(eval $(call add_share_file,share/choices,techlibs/common/choices/kogge-stone.v))
|
||||
|
|
|
|||
54
techlibs/common/choices/kogge-stone.v
Normal file
54
techlibs/common/choices/kogge-stone.v
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2024 Martin Povišer <povik@cutebit.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
(* techmap_celltype = "$lcu" *)
|
||||
module _80_lcu_kogge_stone (P, G, CI, CO);
|
||||
parameter WIDTH = 2;
|
||||
|
||||
(* force_downto *)
|
||||
input [WIDTH-1:0] P, G;
|
||||
input CI;
|
||||
|
||||
(* force_downto *)
|
||||
output [WIDTH-1:0] CO;
|
||||
|
||||
integer i, j;
|
||||
(* force_downto *)
|
||||
reg [WIDTH-1:0] p, g;
|
||||
|
||||
wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast";
|
||||
|
||||
always @* begin
|
||||
p = P;
|
||||
g = G;
|
||||
|
||||
// in almost all cases CI will be constant zero
|
||||
g[0] = g[0] | (p[0] & CI);
|
||||
|
||||
for (i = 0; i < $clog2(WIDTH); i = i + 1) begin
|
||||
// iterate in reverse so we don't confuse a result from this stage and the previous
|
||||
for (j = WIDTH - 1; j >= 2**i; j = j - 1) begin
|
||||
g[j] = g[j] | p[j] & g[j - 2**i];
|
||||
p[j] = p[j] & p[j - 2**i];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign CO = g;
|
||||
endmodule
|
||||
|
|
@ -902,18 +902,34 @@ endgenerate
|
|||
endmodule
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
//-
|
||||
//- $macc (A, B, Y)
|
||||
//-
|
||||
//- Multiply and accumulate.
|
||||
//- A building block for summing any number of negated and unnegated signals
|
||||
//- and arithmetic products of pairs of signals. Cell port A concatenates pairs
|
||||
//- of signals to be multiplied together. When the second signal in a pair is zero
|
||||
//- length, a constant 1 is used instead as the second factor. Cell port B
|
||||
//- concatenates 1-bit-wide signals to also be summed, such as "carry in" in adders.
|
||||
//- Typically created by the `alumacc` pass, which transforms $add and $mul
|
||||
//- into $macc cells.
|
||||
module \$macc (A, B, Y);
|
||||
|
||||
parameter A_WIDTH = 0;
|
||||
parameter B_WIDTH = 0;
|
||||
parameter Y_WIDTH = 0;
|
||||
// CONFIG determines the layout of A, as explained below
|
||||
parameter CONFIG = 4'b0000;
|
||||
parameter CONFIG_WIDTH = 4;
|
||||
|
||||
input [A_WIDTH-1:0] A;
|
||||
input [B_WIDTH-1:0] B;
|
||||
output reg [Y_WIDTH-1:0] Y;
|
||||
// In the terms used for this cell, there's mixed meanings for the term "port". To disambiguate:
|
||||
// A cell port is for example the A input (it is constructed in C++ as cell->setPort(ID::A, ...))
|
||||
// Multiplier ports are pairs of multiplier inputs ("factors").
|
||||
// If the second signal in such a pair is zero length, no multiplication is necessary, and the first signal is just added to the sum.
|
||||
input [A_WIDTH-1:0] A; // Cell port A is the concatenation of all arithmetic ports
|
||||
input [B_WIDTH-1:0] B; // Cell port B is the concatenation of single-bit unsigned signals to be also added to the sum
|
||||
output reg [Y_WIDTH-1:0] Y; // Output sum
|
||||
|
||||
// Xilinx XSIM does not like $clog2() below..
|
||||
function integer my_clog2;
|
||||
|
|
@ -929,10 +945,42 @@ function integer my_clog2;
|
|||
end
|
||||
endfunction
|
||||
|
||||
// Bits that a factor's length field in CONFIG per factor in cell port A
|
||||
localparam integer num_bits = CONFIG[3:0] > 0 ? CONFIG[3:0] : 1;
|
||||
// Number of multiplier ports
|
||||
localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits);
|
||||
// Minium bit width of an induction variable to iterate over all bits of cell port A
|
||||
localparam integer num_abits = my_clog2(A_WIDTH) > 0 ? my_clog2(A_WIDTH) : 1;
|
||||
|
||||
// In this pseudocode, u(foo) means an unsigned int that's foo bits long.
|
||||
// The CONFIG parameter carries the following information:
|
||||
// struct CONFIG {
|
||||
// u4 num_bits;
|
||||
// struct port_field {
|
||||
// bool is_signed;
|
||||
// bool is_subtract;
|
||||
// u(num_bits) factor1_len;
|
||||
// u(num_bits) factor2_len;
|
||||
// }[num_ports];
|
||||
// };
|
||||
|
||||
// The A cell port carries the following information:
|
||||
// struct A {
|
||||
// u(CONFIG.port_field[0].factor1_len) port0factor1;
|
||||
// u(CONFIG.port_field[0].factor2_len) port0factor2;
|
||||
// u(CONFIG.port_field[1].factor1_len) port1factor1;
|
||||
// u(CONFIG.port_field[1].factor2_len) port1factor2;
|
||||
// ...
|
||||
// };
|
||||
// and log(sizeof(A)) is num_abits.
|
||||
// No factor1 may have a zero length.
|
||||
// A factor2 having a zero length implies factor2 is replaced with a constant 1.
|
||||
|
||||
// Additionally, B is an array of 1-bit-wide unsigned integers to also be summed up.
|
||||
// Finally, we have:
|
||||
// Y = port0factor1 * port0factor2 + port1factor1 * port1factor2 + ...
|
||||
// * B[0] + B[1] + ...
|
||||
|
||||
function [2*num_ports*num_abits-1:0] get_port_offsets;
|
||||
input [CONFIG_WIDTH-1:0] cfg;
|
||||
integer i, cursor;
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ module _90_fa (A, B, C, X, Y);
|
|||
endmodule
|
||||
|
||||
(* techmap_celltype = "$lcu" *)
|
||||
module _90_lcu (P, G, CI, CO);
|
||||
module _90_lcu_brent_kung (P, G, CI, CO);
|
||||
parameter WIDTH = 2;
|
||||
|
||||
(* force_downto *)
|
||||
|
|
|
|||
|
|
@ -113,7 +113,31 @@ module EFX_GBUFCE(
|
|||
|
||||
endmodule
|
||||
|
||||
module EFX_RAM_5K(
|
||||
module EFX_RAM_5K
|
||||
# (
|
||||
parameter READ_WIDTH = 20,
|
||||
parameter WRITE_WIDTH = 20,
|
||||
localparam READ_ADDR_WIDTH =
|
||||
(READ_WIDTH == 16) ? 8 : // 256x16
|
||||
(READ_WIDTH == 8) ? 9 : // 512x8
|
||||
(READ_WIDTH == 4) ? 10 : // 1024x4
|
||||
(READ_WIDTH == 2) ? 11 : // 2048x2
|
||||
(READ_WIDTH == 1) ? 12 : // 4096x1
|
||||
(READ_WIDTH == 20) ? 8 : // 256x20
|
||||
(READ_WIDTH == 10) ? 9 : // 512x10
|
||||
(READ_WIDTH == 5) ? 10 : -1, // 1024x5
|
||||
|
||||
localparam WRITE_ADDR_WIDTH =
|
||||
(WRITE_WIDTH == 16) ? 8 : // 256x16
|
||||
(WRITE_WIDTH == 8) ? 9 : // 512x8
|
||||
(WRITE_WIDTH == 4) ? 10 : // 1024x4
|
||||
(WRITE_WIDTH == 2) ? 11 : // 2048x2
|
||||
(WRITE_WIDTH == 1) ? 12 : // 4096x1
|
||||
(WRITE_WIDTH == 20) ? 8 : // 256x20
|
||||
(WRITE_WIDTH == 10) ? 9 : // 512x10
|
||||
(WRITE_WIDTH == 5) ? 10 : -1 // 1024x5
|
||||
)
|
||||
(
|
||||
input [WRITE_WIDTH-1:0] WDATA,
|
||||
input [WRITE_ADDR_WIDTH-1:0] WADDR,
|
||||
input WE,
|
||||
|
|
@ -126,8 +150,6 @@ module EFX_RAM_5K(
|
|||
(* clkbuf_sink *)
|
||||
input RCLK
|
||||
);
|
||||
parameter READ_WIDTH = 20;
|
||||
parameter WRITE_WIDTH = 20;
|
||||
parameter OUTPUT_REG = 1'b0;
|
||||
parameter RCLK_POLARITY = 1'b1;
|
||||
parameter RE_POLARITY = 1'b1;
|
||||
|
|
@ -155,25 +177,4 @@ module EFX_RAM_5K(
|
|||
parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
||||
localparam READ_ADDR_WIDTH =
|
||||
(READ_WIDTH == 16) ? 8 : // 256x16
|
||||
(READ_WIDTH == 8) ? 9 : // 512x8
|
||||
(READ_WIDTH == 4) ? 10 : // 1024x4
|
||||
(READ_WIDTH == 2) ? 11 : // 2048x2
|
||||
(READ_WIDTH == 1) ? 12 : // 4096x1
|
||||
(READ_WIDTH == 20) ? 8 : // 256x20
|
||||
(READ_WIDTH == 10) ? 9 : // 512x10
|
||||
(READ_WIDTH == 5) ? 10 : -1; // 1024x5
|
||||
|
||||
localparam WRITE_ADDR_WIDTH =
|
||||
(WRITE_WIDTH == 16) ? 8 : // 256x16
|
||||
(WRITE_WIDTH == 8) ? 9 : // 512x8
|
||||
(WRITE_WIDTH == 4) ? 10 : // 1024x4
|
||||
(WRITE_WIDTH == 2) ? 11 : // 2048x2
|
||||
(WRITE_WIDTH == 1) ? 12 : // 4096x1
|
||||
(WRITE_WIDTH == 20) ? 8 : // 256x20
|
||||
(WRITE_WIDTH == 10) ? 9 : // 512x10
|
||||
(WRITE_WIDTH == 5) ? 10 : -1; // 1024x5
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
2
tests/arch/quicklogic/.gitignore
vendored
2
tests/arch/quicklogic/.gitignore
vendored
|
|
@ -1,4 +1,4 @@
|
|||
*.log
|
||||
/run-test.mk
|
||||
run-test.mk
|
||||
+*_synth.v
|
||||
+*_testbench
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ for arch in ../../techlibs/*; do
|
|||
done
|
||||
else
|
||||
echo -n "Test $path ->"
|
||||
iverilog -t null -I$arch $path
|
||||
iverilog -t null -I$arch -g2005-sv $path
|
||||
echo " ok"
|
||||
fi
|
||||
done
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
module RAM_9b1B (
|
||||
module RAM_9b1B
|
||||
#(
|
||||
parameter INIT = 0,
|
||||
parameter OPTION_INIT = "UNDEFINED",
|
||||
parameter PORT_R_WIDTH = 9,
|
||||
parameter PORT_W_WIDTH = 9,
|
||||
parameter PORT_R_CLK_POL = 0,
|
||||
parameter PORT_W_CLK_POL = 0,
|
||||
parameter PORT_W_WR_EN_WIDTH = 1
|
||||
)
|
||||
(
|
||||
input PORT_R_CLK,
|
||||
input [6:0] PORT_R_ADDR,
|
||||
output reg [PORT_R_WIDTH-1:0] PORT_R_RD_DATA,
|
||||
|
|
@ -8,14 +18,6 @@ module RAM_9b1B (
|
|||
input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA
|
||||
);
|
||||
|
||||
parameter INIT = 0;
|
||||
parameter OPTION_INIT = "UNDEFINED";
|
||||
parameter PORT_R_WIDTH = 9;
|
||||
parameter PORT_W_WIDTH = 9;
|
||||
parameter PORT_R_CLK_POL = 0;
|
||||
parameter PORT_W_CLK_POL = 0;
|
||||
parameter PORT_W_WR_EN_WIDTH = 1;
|
||||
|
||||
reg [8:0] mem [0:15];
|
||||
|
||||
integer i;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
module RAM_WREN (
|
||||
module RAM_WREN #(
|
||||
parameter ABITS=4,
|
||||
parameter WIDTH=8,
|
||||
parameter PORT_A_WR_EN_WIDTH=1,
|
||||
parameter PORT_A_WR_BE_WIDTH=0,
|
||||
parameter OPTION_BYTESIZE=WIDTH,
|
||||
parameter WB=OPTION_BYTESIZE
|
||||
)(
|
||||
input PORT_A_CLK,
|
||||
input [ABITS-1:0] PORT_A_ADDR,
|
||||
input [WIDTH-1:0] PORT_A_WR_DATA,
|
||||
|
|
@ -7,13 +14,6 @@ module RAM_WREN (
|
|||
input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE
|
||||
);
|
||||
|
||||
parameter ABITS=4;
|
||||
parameter WIDTH=8;
|
||||
parameter PORT_A_WR_EN_WIDTH=1;
|
||||
parameter PORT_A_WR_BE_WIDTH=0;
|
||||
parameter OPTION_BYTESIZE=WIDTH;
|
||||
parameter WB=OPTION_BYTESIZE;
|
||||
|
||||
reg [WIDTH-1:0] mem [0:2**ABITS-1];
|
||||
|
||||
integer i;
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@
|
|||
// expect-rd-ports 1
|
||||
// expect-rd-clk \clk
|
||||
|
||||
module ram2 (input clk,
|
||||
module ram2 #(
|
||||
parameter SIZE = 5 // Address size
|
||||
) (input clk,
|
||||
input sel,
|
||||
input we,
|
||||
input [SIZE-1:0] adr,
|
||||
input [63:0] dat_i,
|
||||
output reg [63:0] dat_o);
|
||||
parameter SIZE = 5; // Address size
|
||||
|
||||
|
||||
reg [63:0] mem [0:(1 << SIZE)-1];
|
||||
integer i;
|
||||
|
|
|
|||
1
tests/simple/.gitignore
vendored
1
tests/simple/.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
*.log
|
||||
*.out
|
||||
*.err
|
||||
|
|
|
|||
1
tests/techmap/kogge-stone.ys
Normal file
1
tests/techmap/kogge-stone.ys
Normal file
|
|
@ -0,0 +1 @@
|
|||
test_cell -s 1711533949 -n 10 -map +/techmap.v -map +/choices/kogge-stone.v $lcu
|
||||
4
tests/verilog/.gitignore
vendored
4
tests/verilog/.gitignore
vendored
|
|
@ -1,6 +1,10 @@
|
|||
/*.log
|
||||
/*.out
|
||||
/*.err
|
||||
/run-test.mk
|
||||
/const_arst.v
|
||||
/const_sr.v
|
||||
/doubleslash.v
|
||||
/roundtrip_proc_1.v
|
||||
/roundtrip_proc_2.v
|
||||
/assign_to_reg.v
|
||||
|
|
|
|||
22
tests/verilog/assign_to_reg.ys
Normal file
22
tests/verilog/assign_to_reg.ys
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# https://github.com/yosyshq/yosys/issues/2035
|
||||
|
||||
read_ilang <<END
|
||||
module \top
|
||||
wire width 1 input 0 \halfbrite
|
||||
wire width 2 output 1 \r_on
|
||||
process $1
|
||||
assign \r_on [1:0] 2'00
|
||||
assign \r_on [1:0] 2'11
|
||||
switch \halfbrite [0]
|
||||
case 1'1
|
||||
assign \r_on [1] 1'0
|
||||
end
|
||||
end
|
||||
end
|
||||
END
|
||||
proc_prune
|
||||
write_verilog assign_to_reg.v
|
||||
design -reset
|
||||
|
||||
logger -expect-no-warnings
|
||||
read_verilog assign_to_reg.v
|
||||
Loading…
Add table
Add a link
Reference in a new issue