mirror of https://github.com/YosysHQ/yosys.git
Merge branch 'master' into firrtl_err_on_unsupported_cell
# Conflicts: # backends/firrtl/firrtl.cc
This commit is contained in:
commit
5e8a98c8fd
|
@ -36,6 +36,7 @@ matrix:
|
|||
- libboost-system-dev
|
||||
- libboost-python-dev
|
||||
- libboost-filesystem-dev
|
||||
- zlib1g-dev
|
||||
env:
|
||||
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8"
|
||||
|
||||
|
@ -64,6 +65,7 @@ matrix:
|
|||
- libboost-system-dev
|
||||
- libboost-python-dev
|
||||
- libboost-filesystem-dev
|
||||
- zlib1g-dev
|
||||
env:
|
||||
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-6 && CXX=g++-6"
|
||||
|
||||
|
@ -92,6 +94,7 @@ matrix:
|
|||
- libboost-system-dev
|
||||
- libboost-python-dev
|
||||
- libboost-filesystem-dev
|
||||
- zlib1g-dev
|
||||
env:
|
||||
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7"
|
||||
|
||||
|
@ -121,6 +124,7 @@ matrix:
|
|||
- libboost-system-dev
|
||||
- libboost-python-dev
|
||||
- libboost-filesystem-dev
|
||||
- zlib1g-dev
|
||||
env:
|
||||
- MATRIX_EVAL="CONFIG=clang && CC=clang-3.8 && CXX=clang++-3.8"
|
||||
|
||||
|
@ -149,6 +153,7 @@ matrix:
|
|||
- libboost-system-dev
|
||||
- libboost-python-dev
|
||||
- libboost-filesystem-dev
|
||||
- zlib1g-dev
|
||||
env:
|
||||
- MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"
|
||||
|
||||
|
|
|
@ -14,7 +14,11 @@ Yosys 0.9 .. Yosys 0.9-dev
|
|||
- Added "synth -abc9" (experimental)
|
||||
- Added "script -scriptwire
|
||||
- "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable)
|
||||
|
||||
- Added automatic gzip decompression for frontends
|
||||
- Added $_NMUX_ cell type
|
||||
- Added automatic gzip compression (based on filename extension) for backends
|
||||
- Improve attribute and parameter encoding in JSON to avoid ambiguities between
|
||||
bit vectors and strings containing [01xz]*
|
||||
|
||||
Yosys 0.8 .. Yosys 0.8-dev
|
||||
--------------------------
|
||||
|
|
16
Makefile
16
Makefile
|
@ -19,6 +19,7 @@ ENABLE_VERIFIC := 0
|
|||
ENABLE_COVER := 1
|
||||
ENABLE_LIBYOSYS := 0
|
||||
ENABLE_PROTOBUF := 0
|
||||
ENABLE_ZLIB := 1
|
||||
|
||||
# python wrappers
|
||||
ENABLE_PYOSYS := 0
|
||||
|
@ -122,7 +123,7 @@ OBJS = kernel/version_$(GIT_REV).o
|
|||
# is just a symlink to your actual ABC working directory, as 'make mrproper'
|
||||
# will remove the 'abc' directory and you do not want to accidentally
|
||||
# delete your work on ABC..
|
||||
ABCREV = 62487de
|
||||
ABCREV = 5776ad0
|
||||
ABCPULL = 1
|
||||
ABCURL ?= https://github.com/berkeley-abc/abc
|
||||
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
|
||||
|
@ -260,7 +261,8 @@ CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
|
|||
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
|
||||
LDLIBS := $(filter-out -lrt,$(LDLIBS))
|
||||
ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
||||
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
|
||||
# TODO: Try to solve pthread linking issue in more appropriate way
|
||||
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" LDFLAGS="-Wl,--allow-multiple-definition" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
|
||||
EXE = .exe
|
||||
|
||||
else ifeq ($(CONFIG),msys2)
|
||||
|
@ -384,6 +386,12 @@ ifeq ($(ENABLE_GLOB),1)
|
|||
CXXFLAGS += -DYOSYS_ENABLE_GLOB
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_ZLIB),1)
|
||||
CXXFLAGS += -DYOSYS_ENABLE_ZLIB
|
||||
LDLIBS += -lz
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(ENABLE_TCL),1)
|
||||
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
|
||||
ifeq ($(OS), FreeBSD)
|
||||
|
@ -394,7 +402,7 @@ endif
|
|||
|
||||
ifeq ($(CONFIG),mxe)
|
||||
CXXFLAGS += -DYOSYS_ENABLE_TCL
|
||||
LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz
|
||||
LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz -luserenv
|
||||
else
|
||||
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
|
||||
ifeq ($(OS), FreeBSD)
|
||||
|
@ -862,9 +870,11 @@ config-mxe: clean
|
|||
|
||||
config-msys2: clean
|
||||
echo 'CONFIG := msys2' > Makefile.conf
|
||||
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
|
||||
|
||||
config-msys2-64: clean
|
||||
echo 'CONFIG := msys2-64' > Makefile.conf
|
||||
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
|
||||
|
||||
config-cygwin: clean
|
||||
echo 'CONFIG := cygwin' > Makefile.conf
|
||||
|
|
73
README.md
73
README.md
|
@ -67,13 +67,13 @@ prerequisites for building yosys:
|
|||
$ sudo apt-get install build-essential clang bison flex \
|
||||
libreadline-dev gawk tcl-dev libffi-dev git \
|
||||
graphviz xdot pkg-config python3 libboost-system-dev \
|
||||
libboost-python-dev libboost-filesystem-dev
|
||||
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
||||
|
||||
Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies:
|
||||
|
||||
$ brew tap Homebrew/bundle && brew bundle
|
||||
$ sudo port install bison flex readline gawk libffi \
|
||||
git graphviz pkgconfig python36 boost
|
||||
git graphviz pkgconfig python36 boost zlib
|
||||
|
||||
On FreeBSD use the following command to install all prerequisites:
|
||||
|
||||
|
@ -85,7 +85,7 @@ On FreeBSD system use gmake instead of make. To run tests use:
|
|||
|
||||
For Cygwin use the following command to install all prerequisites, or select these additional packages:
|
||||
|
||||
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build
|
||||
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
|
||||
|
||||
There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well
|
||||
as a source distribution for Visual Studio. Visit the Yosys download page for
|
||||
|
@ -130,18 +130,15 @@ commands and ``help <command>`` to print details on the specified command:
|
|||
|
||||
yosys> help help
|
||||
|
||||
reading the design using the Verilog frontend:
|
||||
reading and elaborating the design using the Verilog frontend:
|
||||
|
||||
yosys> read_verilog tests/simple/fiedler-cooley.v
|
||||
yosys> read -sv tests/simple/fiedler-cooley.v
|
||||
yosys> hierarchy -top up3down5
|
||||
|
||||
writing the design to the console in Yosys's internal format:
|
||||
|
||||
yosys> write_ilang
|
||||
|
||||
elaborate design hierarchy:
|
||||
|
||||
yosys> hierarchy
|
||||
|
||||
convert processes (``always`` blocks) to netlist elements and perform
|
||||
some simple optimizations:
|
||||
|
||||
|
@ -163,51 +160,26 @@ write design netlist to a new Verilog file:
|
|||
|
||||
yosys> write_verilog synth.v
|
||||
|
||||
a similar synthesis can be performed using yosys command line options only:
|
||||
|
||||
$ ./yosys -o synth.v -p hierarchy -p proc -p opt \
|
||||
-p techmap -p opt tests/simple/fiedler-cooley.v
|
||||
|
||||
or using a simple synthesis script:
|
||||
|
||||
$ cat synth.ys
|
||||
read_verilog tests/simple/fiedler-cooley.v
|
||||
hierarchy; proc; opt; techmap; opt
|
||||
read -sv tests/simple/fiedler-cooley.v
|
||||
hierarchy -top up3down5
|
||||
proc; opt; techmap; opt
|
||||
write_verilog synth.v
|
||||
|
||||
$ ./yosys synth.ys
|
||||
|
||||
It is also possible to only have the synthesis commands but not the read/write
|
||||
commands in the synthesis script:
|
||||
|
||||
$ cat synth.ys
|
||||
hierarchy; proc; opt; techmap; opt
|
||||
|
||||
$ ./yosys -o synth.v tests/simple/fiedler-cooley.v synth.ys
|
||||
|
||||
The following very basic synthesis script should work well with all designs:
|
||||
|
||||
# check design hierarchy
|
||||
hierarchy
|
||||
|
||||
# translate processes (always blocks)
|
||||
proc; opt
|
||||
|
||||
# detect and optimize FSM encodings
|
||||
fsm; opt
|
||||
|
||||
# implement memories (arrays)
|
||||
memory; opt
|
||||
|
||||
# convert to gate logic
|
||||
techmap; opt
|
||||
|
||||
If ABC is enabled in the Yosys build configuration and a cell library is given
|
||||
in the liberty file ``mycells.lib``, the following synthesis script will
|
||||
synthesize for the given cell library:
|
||||
|
||||
# read design
|
||||
read -sv tests/simple/fiedler-cooley.v
|
||||
hierarchy -top up3down5
|
||||
|
||||
# the high-level stuff
|
||||
hierarchy; proc; fsm; opt; memory; opt
|
||||
proc; fsm; opt; memory; opt
|
||||
|
||||
# mapping to internal cell library
|
||||
techmap; opt
|
||||
|
@ -222,7 +194,8 @@ synthesize for the given cell library:
|
|||
clean
|
||||
|
||||
If you do not have a liberty file but want to test this synthesis script,
|
||||
you can use the file ``examples/cmos/cmos_cells.lib`` from the yosys sources.
|
||||
you can use the file ``examples/cmos/cmos_cells.lib`` from the yosys sources
|
||||
as simple example.
|
||||
|
||||
Liberty file downloads for and information about free and open ASIC standard
|
||||
cell libraries can be found here:
|
||||
|
@ -231,20 +204,18 @@ cell libraries can be found here:
|
|||
- http://www.vlsitechnology.org/synopsys/vsclib013.lib
|
||||
|
||||
The command ``synth`` provides a good default synthesis script (see
|
||||
``help synth``). If possible a synthesis script should borrow from ``synth``.
|
||||
For example:
|
||||
``help synth``):
|
||||
|
||||
# the high-level stuff
|
||||
hierarchy
|
||||
synth -run coarse
|
||||
read -sv tests/simple/fiedler-cooley.v
|
||||
synth -top up3down5
|
||||
|
||||
# mapping to internal cells
|
||||
techmap; opt -fast
|
||||
# mapping to target cells
|
||||
dfflibmap -liberty mycells.lib
|
||||
abc -liberty mycells.lib
|
||||
clean
|
||||
|
||||
Yosys is under construction. A more detailed documentation will follow.
|
||||
The command ``prep`` provides a good default word-level synthesis script, as
|
||||
used in SMT-based formal verification.
|
||||
|
||||
|
||||
Unsupported Verilog-2005 Features
|
||||
|
|
|
@ -53,7 +53,7 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
|
||||
inline int32_t to_big_endian(int32_t i32) {
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
return __builtin_bswap32(i32);
|
||||
return bswap32(i32);
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
return i32;
|
||||
#else
|
||||
|
@ -610,15 +610,15 @@ struct XAigerWriter
|
|||
std::stringstream h_buffer;
|
||||
auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1);
|
||||
write_h_buffer(1);
|
||||
log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size());
|
||||
log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits));
|
||||
write_h_buffer(input_bits.size() + ci_bits.size());
|
||||
log_debug("coNum = %zu\n", output_bits.size() + co_bits.size());
|
||||
log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits));
|
||||
write_h_buffer(output_bits.size() + co_bits.size());
|
||||
log_debug("piNum = %zu\n", input_bits.size());
|
||||
log_debug("piNum = %d\n", GetSize(input_bits));
|
||||
write_h_buffer(input_bits.size());
|
||||
log_debug("poNum = %zu\n", output_bits.size());
|
||||
log_debug("poNum = %d\n", GetSize(output_bits));
|
||||
write_h_buffer(output_bits.size());
|
||||
log_debug("boxNum = %zu\n", box_list.size());
|
||||
log_debug("boxNum = %d\n", GetSize(box_list));
|
||||
write_h_buffer(box_list.size());
|
||||
|
||||
RTLIL::Module *holes_module = nullptr;
|
||||
|
@ -772,7 +772,7 @@ struct XAigerWriter
|
|||
|
||||
if (output_bits.count(b)) {
|
||||
int o = ordered_outputs.at(b);
|
||||
output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire));
|
||||
output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), i, log_id(wire));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -327,6 +327,13 @@ struct BlifDumper
|
|||
goto internal_cell;
|
||||
}
|
||||
|
||||
if (!config->icells_mode && cell->type == "$_NMUX_") {
|
||||
f << stringf(".names %s %s %s %s\n0-0 1\n-01 1\n",
|
||||
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
|
||||
cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y")));
|
||||
goto internal_cell;
|
||||
}
|
||||
|
||||
if (!config->icells_mode && cell->type == "$_FF_") {
|
||||
f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
|
||||
cstr_init(cell->getPort("\\Q")));
|
||||
|
|
|
@ -496,7 +496,7 @@ struct BtorWorker
|
|||
goto okay;
|
||||
}
|
||||
|
||||
if (cell->type.in("$mux", "$_MUX_"))
|
||||
if (cell->type.in("$mux", "$_MUX_", "$_NMUX_"))
|
||||
{
|
||||
SigSpec sig_a = sigmap(cell->getPort("\\A"));
|
||||
SigSpec sig_b = sigmap(cell->getPort("\\B"));
|
||||
|
@ -511,6 +511,12 @@ struct BtorWorker
|
|||
int nid = next_nid++;
|
||||
btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a);
|
||||
|
||||
if (cell->type == "$_NMUX_") {
|
||||
int tmp = nid;
|
||||
nid = next_nid++;
|
||||
btorf("%d not %d %d\n", nid, sid, tmp);
|
||||
}
|
||||
|
||||
add_nid_sig(nid, sig_y);
|
||||
goto okay;
|
||||
}
|
||||
|
|
|
@ -381,10 +381,10 @@ struct FirrtlWorker
|
|||
|
||||
// Given an expression for a shift amount, and a maximum width,
|
||||
// generate the FIRRTL expression for equivalent dynamic shift taking into account FIRRTL shift semantics.
|
||||
std::string gen_dshl(const string b_expr, const int b_padded_width)
|
||||
std::string gen_dshl(const string b_expr, const int b_width)
|
||||
{
|
||||
string result = b_expr;
|
||||
if (b_padded_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) {
|
||||
if (b_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) {
|
||||
int max_shift_width_bits = FIRRTL_MAX_DSH_WIDTH_ERROR - 1;
|
||||
string max_shift_string = stringf("UInt<%d>(%d)", max_shift_width_bits, (1<<max_shift_width_bits) - 1);
|
||||
// Deal with the difference in semantics between FIRRTL and verilog
|
||||
|
@ -422,22 +422,33 @@ struct FirrtlWorker
|
|||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
bool extract_y_bits = false; // Assume no extraction of final bits will be required.
|
||||
static Const ndef(0, 0);
|
||||
|
||||
// Is this cell is a module instance?
|
||||
if (cell->type[0] != '$')
|
||||
{
|
||||
process_instance(cell, wire_exprs);
|
||||
continue;
|
||||
}
|
||||
// Not a module instance. Set up cell properties
|
||||
bool extract_y_bits = false; // Assume no extraction of final bits will be required.
|
||||
int a_width = cell->parameters.at("\\A_WIDTH", ndef).as_int(); // The width of "A"
|
||||
int b_width = cell->parameters.at("\\B_WIDTH", ndef).as_int(); // The width of "A"
|
||||
const int y_width = cell->parameters.at("\\Y_WIDTH", ndef).as_int(); // The width of the result
|
||||
const bool a_signed = cell->parameters.at("\\A_SIGNED", ndef).as_bool();
|
||||
const bool b_signed = cell->parameters.at("\\B_SIGNED", ndef).as_bool();
|
||||
bool firrtl_is_signed = a_signed; // The result is signed (subsequent code may change this).
|
||||
int firrtl_width = 0;
|
||||
string primop;
|
||||
bool always_uint = false;
|
||||
string y_id = make_id(cell->name);
|
||||
|
||||
if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor"))
|
||||
{
|
||||
string y_id = make_id(cell->name);
|
||||
bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
|
||||
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
|
||||
string a_expr = make_expr(cell->getPort("\\A"));
|
||||
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
|
||||
|
||||
if (cell->parameters.at("\\A_SIGNED").as_bool()) {
|
||||
if (a_signed) {
|
||||
a_expr = "asSInt(" + a_expr + ")";
|
||||
}
|
||||
|
||||
|
@ -446,12 +457,13 @@ struct FirrtlWorker
|
|||
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
|
||||
}
|
||||
|
||||
string primop;
|
||||
bool always_uint = false;
|
||||
// Assume the FIRRTL width is a single bit.
|
||||
firrtl_width = 1;
|
||||
if (cell->type == "$not") primop = "not";
|
||||
else if (cell->type == "$neg") {
|
||||
primop = "neg";
|
||||
is_signed = true; // Result of "neg" is signed (an SInt).
|
||||
firrtl_is_signed = true; // Result of "neg" is signed (an SInt).
|
||||
firrtl_width = a_width;
|
||||
} else if (cell->type == "$logic_not") {
|
||||
primop = "eq";
|
||||
a_expr = stringf("%s, UInt(0)", a_expr.c_str());
|
||||
|
@ -466,14 +478,12 @@ struct FirrtlWorker
|
|||
else if (cell->type == "$reduce_bool") {
|
||||
primop = "neq";
|
||||
// Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand.
|
||||
bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool();
|
||||
int a_width = cell->parameters.at("\\A_WIDTH").as_int();
|
||||
a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width);
|
||||
}
|
||||
|
||||
string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str());
|
||||
|
||||
if ((is_signed && !always_uint))
|
||||
if ((firrtl_is_signed && !always_uint))
|
||||
expr = stringf("asUInt(%s)", expr.c_str());
|
||||
|
||||
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
|
||||
|
@ -481,81 +491,121 @@ struct FirrtlWorker
|
|||
|
||||
continue;
|
||||
}
|
||||
if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx",
|
||||
if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or", "$eq", "$eqx",
|
||||
"$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl",
|
||||
"$logic_and", "$logic_or"))
|
||||
"$logic_and", "$logic_or", "$pow"))
|
||||
{
|
||||
string y_id = make_id(cell->name);
|
||||
bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
|
||||
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
|
||||
string a_expr = make_expr(cell->getPort("\\A"));
|
||||
string b_expr = make_expr(cell->getPort("\\B"));
|
||||
int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int();
|
||||
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
|
||||
|
||||
if (cell->parameters.at("\\A_SIGNED").as_bool()) {
|
||||
if (a_signed) {
|
||||
a_expr = "asSInt(" + a_expr + ")";
|
||||
}
|
||||
// Shift amount is always unsigned, and needn't be padded to result width.
|
||||
if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) {
|
||||
if (cell->parameters.at("\\B_SIGNED").as_bool()) {
|
||||
b_expr = "asSInt(" + b_expr + ")";
|
||||
// Expand the "A" operand to the result width
|
||||
if (a_width < y_width) {
|
||||
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
|
||||
a_width = y_width;
|
||||
}
|
||||
if (b_padded_width < y_width) {
|
||||
auto b_sig = cell->getPort("\\B");
|
||||
b_padded_width = y_width;
|
||||
}
|
||||
// Shift amount is always unsigned, and needn't be padded to result width,
|
||||
// otherwise, we need to cast the b_expr appropriately
|
||||
if (b_signed && !cell->type.in("$shr", "$sshr", "$shl", "$sshl", "$pow")) {
|
||||
b_expr = "asSInt(" + b_expr + ")";
|
||||
// Expand the "B" operand to the result width
|
||||
if (b_width < y_width) {
|
||||
b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
|
||||
b_width = y_width;
|
||||
}
|
||||
}
|
||||
|
||||
// For the arithmetic ops, expand operand widths to result widths befor performing the operation.
|
||||
// This corresponds (according to iverilog) to what verilog compilers implement.
|
||||
if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or"))
|
||||
{
|
||||
if (a_width < y_width) {
|
||||
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
|
||||
a_width = y_width;
|
||||
}
|
||||
if (b_width < y_width) {
|
||||
b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
|
||||
b_width = y_width;
|
||||
}
|
||||
}
|
||||
// Assume the FIRRTL width is the width of "A"
|
||||
firrtl_width = a_width;
|
||||
auto a_sig = cell->getPort("\\A");
|
||||
|
||||
if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) {
|
||||
a_expr = "asUInt(" + a_expr + ")";
|
||||
if (cell->type == "$add") {
|
||||
primop = "add";
|
||||
firrtl_is_signed = a_signed | b_signed;
|
||||
firrtl_width = max(a_width, b_width);
|
||||
} else if (cell->type == "$sub") {
|
||||
primop = "sub";
|
||||
firrtl_is_signed = true;
|
||||
int a_widthInc = (!a_signed && b_signed) ? 2 : (a_signed && !b_signed) ? 1 : 0;
|
||||
int b_widthInc = (a_signed && !b_signed) ? 2 : (!a_signed && b_signed) ? 1 : 0;
|
||||
firrtl_width = max(a_width + a_widthInc, b_width + b_widthInc);
|
||||
} else if (cell->type == "$mul") {
|
||||
primop = "mul";
|
||||
firrtl_is_signed = a_signed | b_signed;
|
||||
firrtl_width = a_width + b_width;
|
||||
} else if (cell->type == "$div") {
|
||||
primop = "div";
|
||||
firrtl_is_signed = a_signed | b_signed;
|
||||
firrtl_width = a_width;
|
||||
} else if (cell->type == "$mod") {
|
||||
primop = "rem";
|
||||
firrtl_width = min(a_width, b_width);
|
||||
} else if (cell->type == "$and") {
|
||||
primop = "and";
|
||||
always_uint = true;
|
||||
firrtl_width = max(a_width, b_width);
|
||||
}
|
||||
|
||||
string primop;
|
||||
bool always_uint = false;
|
||||
if (cell->type == "$add") primop = "add";
|
||||
else if (cell->type == "$sub") primop = "sub";
|
||||
else if (cell->type == "$mul") primop = "mul";
|
||||
else if (cell->type == "$div") primop = "div";
|
||||
else if (cell->type == "$mod") primop = "rem";
|
||||
else if (cell->type == "$and") {
|
||||
primop = "and";
|
||||
always_uint = true;
|
||||
}
|
||||
else if (cell->type == "$or" ) {
|
||||
primop = "or";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "or";
|
||||
always_uint = true;
|
||||
firrtl_width = max(a_width, b_width);
|
||||
}
|
||||
else if (cell->type == "$xor") {
|
||||
primop = "xor";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "xor";
|
||||
always_uint = true;
|
||||
firrtl_width = max(a_width, b_width);
|
||||
}
|
||||
else if (cell->type == "$xnor") {
|
||||
primop = "xnor";
|
||||
always_uint = true;
|
||||
firrtl_width = max(a_width, b_width);
|
||||
}
|
||||
else if ((cell->type == "$eq") | (cell->type == "$eqx")) {
|
||||
primop = "eq";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "eq";
|
||||
always_uint = true;
|
||||
firrtl_width = 1;
|
||||
}
|
||||
else if ((cell->type == "$ne") | (cell->type == "$nex")) {
|
||||
primop = "neq";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "neq";
|
||||
always_uint = true;
|
||||
firrtl_width = 1;
|
||||
}
|
||||
else if (cell->type == "$gt") {
|
||||
primop = "gt";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "gt";
|
||||
always_uint = true;
|
||||
firrtl_width = 1;
|
||||
}
|
||||
else if (cell->type == "$ge") {
|
||||
primop = "geq";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "geq";
|
||||
always_uint = true;
|
||||
firrtl_width = 1;
|
||||
}
|
||||
else if (cell->type == "$lt") {
|
||||
primop = "lt";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "lt";
|
||||
always_uint = true;
|
||||
firrtl_width = 1;
|
||||
}
|
||||
else if (cell->type == "$le") {
|
||||
primop = "leq";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "leq";
|
||||
always_uint = true;
|
||||
firrtl_width = 1;
|
||||
}
|
||||
else if ((cell->type == "$shl") | (cell->type == "$sshl")) {
|
||||
// FIRRTL will widen the result (y) by the amount of the shift.
|
||||
// We'll need to offset this by extracting the un-widened portion as Verilog would do.
|
||||
|
@ -564,11 +614,14 @@ struct FirrtlWorker
|
|||
auto b_sig = cell->getPort("\\B");
|
||||
if (b_sig.is_fully_const()) {
|
||||
primop = "shl";
|
||||
b_expr = std::to_string(b_sig.as_int());
|
||||
int shift_amount = b_sig.as_int();
|
||||
b_expr = std::to_string(shift_amount);
|
||||
firrtl_width = a_width + shift_amount;
|
||||
} else {
|
||||
primop = "dshl";
|
||||
// Convert from FIRRTL left shift semantics.
|
||||
b_expr = gen_dshl(b_expr, b_padded_width);
|
||||
b_expr = gen_dshl(b_expr, b_width);
|
||||
firrtl_width = a_width + (1 << b_width) - 1;
|
||||
}
|
||||
}
|
||||
else if ((cell->type == "$shr") | (cell->type == "$sshr")) {
|
||||
|
@ -578,36 +631,86 @@ struct FirrtlWorker
|
|||
auto b_sig = cell->getPort("\\B");
|
||||
if (b_sig.is_fully_const()) {
|
||||
primop = "shr";
|
||||
b_expr = std::to_string(b_sig.as_int());
|
||||
int shift_amount = b_sig.as_int();
|
||||
b_expr = std::to_string(shift_amount);
|
||||
firrtl_width = max(1, a_width - shift_amount);
|
||||
} else {
|
||||
primop = "dshr";
|
||||
firrtl_width = a_width;
|
||||
}
|
||||
// We'll need to do some special fixups if the source (and thus result) is signed.
|
||||
if (firrtl_is_signed) {
|
||||
// If this is a "logical" shift right, pretend the source is unsigned.
|
||||
if (cell->type == "$shr") {
|
||||
a_expr = "asUInt(" + a_expr + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((cell->type == "$logic_and")) {
|
||||
primop = "and";
|
||||
a_expr = "neq(" + a_expr + ", UInt(0))";
|
||||
b_expr = "neq(" + b_expr + ", UInt(0))";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "and";
|
||||
a_expr = "neq(" + a_expr + ", UInt(0))";
|
||||
b_expr = "neq(" + b_expr + ", UInt(0))";
|
||||
always_uint = true;
|
||||
firrtl_width = 1;
|
||||
}
|
||||
else if ((cell->type == "$logic_or")) {
|
||||
primop = "or";
|
||||
a_expr = "neq(" + a_expr + ", UInt(0))";
|
||||
b_expr = "neq(" + b_expr + ", UInt(0))";
|
||||
always_uint = true;
|
||||
}
|
||||
primop = "or";
|
||||
a_expr = "neq(" + a_expr + ", UInt(0))";
|
||||
b_expr = "neq(" + b_expr + ", UInt(0))";
|
||||
always_uint = true;
|
||||
firrtl_width = 1;
|
||||
}
|
||||
else if ((cell->type == "$pow")) {
|
||||
if (a_sig.is_fully_const() && a_sig.as_int() == 2) {
|
||||
// We'll convert this to a shift. To simplify things, change the a_expr to "1"
|
||||
// so we can use b_expr directly as a shift amount.
|
||||
// Only support 2 ** N (i.e., shift left)
|
||||
// FIRRTL will widen the result (y) by the amount of the shift.
|
||||
// We'll need to offset this by extracting the un-widened portion as Verilog would do.
|
||||
a_expr = firrtl_is_signed ? "SInt(1)" : "UInt(1)";
|
||||
extract_y_bits = true;
|
||||
// Is the shift amount constant?
|
||||
auto b_sig = cell->getPort("\\B");
|
||||
if (b_sig.is_fully_const()) {
|
||||
primop = "shl";
|
||||
int shiftAmount = b_sig.as_int();
|
||||
if (shiftAmount < 0) {
|
||||
log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, log_id(module), log_id(cell));
|
||||
}
|
||||
b_expr = std::to_string(shiftAmount);
|
||||
firrtl_width = a_width + shiftAmount;
|
||||
} else {
|
||||
primop = "dshl";
|
||||
// Convert from FIRRTL left shift semantics.
|
||||
b_expr = gen_dshl(b_expr, b_width);
|
||||
firrtl_width = a_width + (1 << b_width) - 1;
|
||||
}
|
||||
} else {
|
||||
log_error("Non power 2: %s.%s\n", log_id(module), log_id(cell));
|
||||
}
|
||||
}
|
||||
|
||||
if (!cell->parameters.at("\\B_SIGNED").as_bool()) {
|
||||
b_expr = "asUInt(" + b_expr + ")";
|
||||
}
|
||||
|
||||
string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str());
|
||||
|
||||
// Deal with FIRRTL's "shift widens" semantics
|
||||
if (extract_y_bits) {
|
||||
expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1);
|
||||
string expr;
|
||||
// Deal with $xnor == ~^ (not xor)
|
||||
if (primop == "xnor") {
|
||||
expr = stringf("not(xor(%s, %s))", a_expr.c_str(), b_expr.c_str());
|
||||
} else {
|
||||
expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str());
|
||||
}
|
||||
|
||||
if ((is_signed && !always_uint) || cell->type.in("$sub"))
|
||||
// Deal with FIRRTL's "shift widens" semantics, or the need to widen the FIRRTL result.
|
||||
// If the operation is signed, the FIRRTL width will be 1 one bit larger.
|
||||
if (extract_y_bits) {
|
||||
expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1);
|
||||
} else if (firrtl_is_signed && (firrtl_width + 1) < y_width) {
|
||||
expr = stringf("pad(%s, %d)", expr.c_str(), y_width);
|
||||
}
|
||||
|
||||
if ((firrtl_is_signed && !always_uint))
|
||||
expr = stringf("asUInt(%s)", expr.c_str());
|
||||
|
||||
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
|
||||
|
@ -618,7 +721,6 @@ struct FirrtlWorker
|
|||
|
||||
if (cell->type.in("$mux"))
|
||||
{
|
||||
string y_id = make_id(cell->name);
|
||||
int width = cell->parameters.at("\\WIDTH").as_int();
|
||||
string a_expr = make_expr(cell->getPort("\\A"));
|
||||
string b_expr = make_expr(cell->getPort("\\B"));
|
||||
|
@ -762,15 +864,14 @@ struct FirrtlWorker
|
|||
if (clkpol == false)
|
||||
log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell));
|
||||
|
||||
string q_id = make_id(cell->name);
|
||||
int width = cell->parameters.at("\\WIDTH").as_int();
|
||||
string expr = make_expr(cell->getPort("\\D"));
|
||||
string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")";
|
||||
|
||||
wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", q_id.c_str(), width, clk_expr.c_str()));
|
||||
wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", y_id.c_str(), width, clk_expr.c_str()));
|
||||
|
||||
cell_exprs.push_back(stringf(" %s <= %s\n", q_id.c_str(), expr.c_str()));
|
||||
register_reverse_wire_map(q_id, cell->getPort("\\Q"));
|
||||
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
|
||||
register_reverse_wire_map(y_id, cell->getPort("\\Q"));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -785,8 +886,6 @@ struct FirrtlWorker
|
|||
// assign y = a[b +: y_width];
|
||||
// We'll extract the correct bits as part of the primop.
|
||||
|
||||
string y_id = make_id(cell->name);
|
||||
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
|
||||
string a_expr = make_expr(cell->getPort("\\A"));
|
||||
// Get the initial bit selector
|
||||
string b_expr = make_expr(cell->getPort("\\B"));
|
||||
|
@ -808,18 +907,15 @@ struct FirrtlWorker
|
|||
// assign y = a >> b;
|
||||
// where b may be negative
|
||||
|
||||
string y_id = make_id(cell->name);
|
||||
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
|
||||
string a_expr = make_expr(cell->getPort("\\A"));
|
||||
string b_expr = make_expr(cell->getPort("\\B"));
|
||||
auto b_string = b_expr.c_str();
|
||||
int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int();
|
||||
string expr;
|
||||
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
|
||||
|
||||
if (cell->getParam("\\B_SIGNED").as_bool()) {
|
||||
// We generate a left or right shift based on the sign of b.
|
||||
std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_padded_width).c_str(), y_width);
|
||||
std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_width).c_str(), y_width);
|
||||
std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string);
|
||||
expr = stringf("mux(%s < 0, %s, %s)",
|
||||
b_string,
|
||||
|
@ -833,6 +929,20 @@ struct FirrtlWorker
|
|||
register_reverse_wire_map(y_id, cell->getPort("\\Y"));
|
||||
continue;
|
||||
}
|
||||
if (cell->type == "$pos") {
|
||||
// assign y = a;
|
||||
// printCell(cell);
|
||||
string a_expr = make_expr(cell->getPort("\\A"));
|
||||
// Verilog appears to treat the result as signed, so if the result is wider than "A",
|
||||
// we need to pad.
|
||||
if (a_width < y_width) {
|
||||
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
|
||||
}
|
||||
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
|
||||
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), a_expr.c_str()));
|
||||
register_reverse_wire_map(y_id, cell->getPort("\\Y"));
|
||||
continue;
|
||||
}
|
||||
log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
|
||||
}
|
||||
|
||||
|
|
|
@ -83,20 +83,43 @@ struct JsonWriter
|
|||
return str + " ]";
|
||||
}
|
||||
|
||||
void write_parameter_value(const Const &value)
|
||||
{
|
||||
if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) {
|
||||
string str = value.decode_string();
|
||||
int state = 0;
|
||||
for (char c : str) {
|
||||
if (state == 0) {
|
||||
if (c == '0' || c == '1' || c == 'x' || c == 'z')
|
||||
state = 0;
|
||||
else if (c == ' ')
|
||||
state = 1;
|
||||
else
|
||||
state = 2;
|
||||
} else if (state == 1 && c != ' ')
|
||||
state = 2;
|
||||
}
|
||||
if (state < 2)
|
||||
str += " ";
|
||||
f << get_string(str);
|
||||
} else
|
||||
if (GetSize(value) == 32 && value.is_fully_def()) {
|
||||
if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
|
||||
f << stringf("%d", value.as_int());
|
||||
else
|
||||
f << stringf("%u", value.as_int());
|
||||
} else {
|
||||
f << get_string(value.as_string());
|
||||
}
|
||||
}
|
||||
|
||||
void write_parameters(const dict<IdString, Const> ¶meters, bool for_module=false)
|
||||
{
|
||||
bool first = true;
|
||||
for (auto ¶m : parameters) {
|
||||
f << stringf("%s\n", first ? "" : ",");
|
||||
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str());
|
||||
if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0)
|
||||
f << get_string(param.second.decode_string());
|
||||
else if (GetSize(param.second.bits) > 32)
|
||||
f << get_string(param.second.as_string());
|
||||
else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
|
||||
f << stringf("%d", param.second.as_int());
|
||||
else
|
||||
f << stringf("%u", param.second.as_int());
|
||||
write_parameter_value(param.second);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
@ -342,12 +365,13 @@ struct JsonBackend : public Backend {
|
|||
log("Module and cell ports and nets can be single bit wide or vectors of multiple\n");
|
||||
log("bits. Each individual signal bit is assigned a unique integer. The <bit_vector>\n");
|
||||
log("values referenced above are vectors of this integers. Signal bits that are\n");
|
||||
log("connected to a constant driver are denoted as string \"0\" or \"1\" instead of\n");
|
||||
log("a number.\n");
|
||||
log("connected to a constant driver are denoted as string \"0\", \"1\", \"x\", or\n");
|
||||
log("\"z\" instead of a number.\n");
|
||||
log("\n");
|
||||
log("Numeric parameter and attribute values up to 32 bits are written as decimal\n");
|
||||
log("values. Numbers larger than that are written as string holding the binary\n");
|
||||
log("representation of the value.\n");
|
||||
log("Numeric 32-bit parameter and attribute values are written as decimal values.\n");
|
||||
log("Bit verctors of different sizes, or ones containing 'x' or 'z' bits, are written\n");
|
||||
log("as string holding the binary representation of the value. Strings are written\n");
|
||||
log("as strings, with an appended blank in cases of strings of the form /[01xz]* */.\n");
|
||||
log("\n");
|
||||
log("For example the following Verilog code:\n");
|
||||
log("\n");
|
||||
|
|
|
@ -472,7 +472,7 @@ struct SimplecWorker
|
|||
return;
|
||||
}
|
||||
|
||||
if (cell->type == "$_MUX_")
|
||||
if (cell->type.in("$_MUX_", "$_NMUX_"))
|
||||
{
|
||||
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
|
||||
SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
|
||||
|
@ -484,7 +484,9 @@ struct SimplecWorker
|
|||
string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0";
|
||||
|
||||
// casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933)
|
||||
string expr = stringf("%s ? (bool)%s : (bool)%s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str());
|
||||
string expr = stringf("%s ? %s(bool)%s : %s(bool)%s", s_expr.c_str(),
|
||||
cell->type == "$_NMUX_" ? "!" : "", b_expr.c_str(),
|
||||
cell->type == "$_NMUX_" ? "!" : "", a_expr.c_str());
|
||||
|
||||
log_assert(y.wire);
|
||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||
|
|
|
@ -510,6 +510,7 @@ struct Smt2Worker
|
|||
if (cell->type == "$_ANDNOT_") return export_gate(cell, "(and A (not B))");
|
||||
if (cell->type == "$_ORNOT_") return export_gate(cell, "(or A (not B))");
|
||||
if (cell->type == "$_MUX_") return export_gate(cell, "(ite S B A)");
|
||||
if (cell->type == "$_NMUX_") return export_gate(cell, "(not (ite S B A))");
|
||||
if (cell->type == "$_AOI3_") return export_gate(cell, "(not (or (and A B) C))");
|
||||
if (cell->type == "$_OAI3_") return export_gate(cell, "(not (and (or A B) C))");
|
||||
if (cell->type == "$_AOI4_") return export_gate(cell, "(not (or (and A B) (and C D)))");
|
||||
|
|
|
@ -537,6 +537,13 @@ struct SmvWorker
|
|||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == "$_NMUX_")
|
||||
{
|
||||
definitions.push_back(stringf("%s := !(bool(%s) ? %s : %s);", lvalue(cell->getPort("\\Y")),
|
||||
rvalue(cell->getPort("\\S")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\A"))));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == "$_AOI3_")
|
||||
{
|
||||
definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")),
|
||||
|
|
|
@ -558,6 +558,20 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == "$_NMUX_") {
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort("\\Y"));
|
||||
f << stringf(" = !(");
|
||||
dump_cell_expr_port(f, cell, "S", false);
|
||||
f << stringf(" ? ");
|
||||
dump_attributes(f, "", cell->attributes, ' ');
|
||||
dump_cell_expr_port(f, cell, "B", false);
|
||||
f << stringf(" : ");
|
||||
dump_cell_expr_port(f, cell, "A", false);
|
||||
f << stringf(");\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type.in("$_AOI3_", "$_OAI3_")) {
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort("\\Y"));
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
A simple example design, based on the Numato Labs Mimas V2 board
|
||||
================================================================
|
||||
|
||||
This example uses Yosys for synthesis and Xilinx ISE
|
||||
for place&route and bit-stream creation.
|
||||
|
||||
To synthesize:
|
||||
bash run.sh
|
|
@ -0,0 +1,13 @@
|
|||
CONFIG VCCAUX = "3.3" ;
|
||||
|
||||
|
||||
NET "CLK" LOC = D9 | IOSTANDARD = LVCMOS33 | PERIOD = 12MHz ;
|
||||
|
||||
NET "LED[7]" LOC = P15 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
|
||||
NET "LED[6]" LOC = P16 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
|
||||
NET "LED[5]" LOC = N15 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
|
||||
NET "LED[4]" LOC = N16 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
|
||||
NET "LED[3]" LOC = U17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
|
||||
NET "LED[2]" LOC = U18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
|
||||
NET "LED[1]" LOC = T17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
|
||||
NET "LED[0]" LOC = T18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
|
|
@ -0,0 +1,14 @@
|
|||
module example(
|
||||
input wire CLK,
|
||||
output wire [7:0] LED
|
||||
);
|
||||
|
||||
reg [27:0] ctr;
|
||||
initial ctr = 0;
|
||||
|
||||
always @(posedge CLK)
|
||||
ctr <= ctr + 1;
|
||||
|
||||
assign LED = ctr[27:20];
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
yosys run_yosys.ys
|
||||
edif2ngd example.edif
|
||||
ngdbuild example -uc example.ucf -p xc6slx9csg324-3
|
||||
map -w example
|
||||
par -w example.ncd example_par.ncd
|
||||
bitgen -w example_par.ncd -g StartupClk:JTAGClk
|
|
@ -0,0 +1,4 @@
|
|||
read_verilog example.v
|
||||
synth_xilinx -top example -family xc6s
|
||||
iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I
|
||||
write_edif -pvector bra example.edif
|
|
@ -301,7 +301,11 @@ static uint32_t parse_xaiger_literal(std::istream &f)
|
|||
uint32_t l;
|
||||
f.read(reinterpret_cast<char*>(&l), sizeof(l));
|
||||
if (f.gcount() != sizeof(l))
|
||||
#if defined(_WIN32) && defined(__MINGW32__)
|
||||
log_error("Offset %I64d: unable to read literal!\n", static_cast<int64_t>(f.tellg()));
|
||||
#else
|
||||
log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast<int64_t>(f.tellg()));
|
||||
#endif
|
||||
return from_big_endian(l);
|
||||
}
|
||||
|
||||
|
|
|
@ -3439,19 +3439,11 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
{
|
||||
std::map<std::string, AstNode*> backup_scope;
|
||||
std::map<std::string, AstNode::varinfo_t> variables;
|
||||
bool delete_temp_block = false;
|
||||
AstNode *block = NULL;
|
||||
AstNode *block = new AstNode(AST_BLOCK);
|
||||
|
||||
size_t argidx = 0;
|
||||
for (auto child : children)
|
||||
{
|
||||
if (child->type == AST_BLOCK)
|
||||
{
|
||||
log_assert(block == NULL);
|
||||
block = child;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child->type == AST_WIRE)
|
||||
{
|
||||
while (child->simplify(true, false, false, 1, -1, false, true)) { }
|
||||
|
@ -3468,13 +3460,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
continue;
|
||||
}
|
||||
|
||||
log_assert(block == NULL);
|
||||
delete_temp_block = true;
|
||||
block = new AstNode(AST_BLOCK);
|
||||
block->children.push_back(child->clone());
|
||||
}
|
||||
|
||||
log_assert(block != NULL);
|
||||
log_assert(variables.count(str) != 0);
|
||||
|
||||
while (!block->children.empty())
|
||||
|
@ -3642,8 +3630,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
|
|||
log_abort();
|
||||
}
|
||||
|
||||
if (delete_temp_block)
|
||||
delete block;
|
||||
delete block;
|
||||
|
||||
for (auto &it : backup_scope)
|
||||
if (it.second == NULL)
|
||||
|
|
|
@ -25,7 +25,7 @@ struct JsonNode
|
|||
{
|
||||
char type; // S=String, N=Number, A=Array, D=Dict
|
||||
string data_string;
|
||||
int data_number;
|
||||
int64_t data_number;
|
||||
vector<JsonNode*> data_array;
|
||||
dict<string, JsonNode*> data_dict;
|
||||
vector<string> data_dict_keys;
|
||||
|
@ -206,6 +206,38 @@ struct JsonNode
|
|||
}
|
||||
};
|
||||
|
||||
Const json_parse_attr_param_value(JsonNode *node)
|
||||
{
|
||||
Const value;
|
||||
|
||||
if (node->type == 'S') {
|
||||
string &s = node->data_string;
|
||||
size_t cursor = s.find_first_not_of("01xz");
|
||||
if (cursor == string::npos) {
|
||||
value = Const::from_string(s);
|
||||
} else if (s.find_first_not_of(' ', cursor) == string::npos) {
|
||||
value = Const(s.substr(0, GetSize(s)-1));
|
||||
} else {
|
||||
value = Const(s);
|
||||
}
|
||||
} else
|
||||
if (node->type == 'N') {
|
||||
value = Const(node->data_number, 32);
|
||||
if (node->data_number < 0)
|
||||
value.flags |= RTLIL::CONST_FLAG_SIGNED;
|
||||
} else
|
||||
if (node->type == 'A') {
|
||||
log_error("JSON attribute or parameter value is an array.\n");
|
||||
} else
|
||||
if (node->type == 'D') {
|
||||
log_error("JSON attribute or parameter value is a dict.\n");
|
||||
} else {
|
||||
log_abort();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
|
||||
{
|
||||
if (node->type != 'D')
|
||||
|
@ -214,28 +246,7 @@ void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
|
|||
for (auto it : node->data_dict)
|
||||
{
|
||||
IdString key = RTLIL::escape_id(it.first.c_str());
|
||||
JsonNode *value_node = it.second;
|
||||
Const value;
|
||||
|
||||
if (value_node->type == 'S') {
|
||||
string &s = value_node->data_string;
|
||||
if (s.find_first_not_of("01xz") == string::npos)
|
||||
value = Const::from_string(s);
|
||||
else
|
||||
value = Const(s);
|
||||
} else
|
||||
if (value_node->type == 'N') {
|
||||
value = Const(value_node->data_number, 32);
|
||||
} else
|
||||
if (value_node->type == 'A') {
|
||||
log_error("JSON attribute or parameter value is an array.\n");
|
||||
} else
|
||||
if (value_node->type == 'D') {
|
||||
log_error("JSON attribute or parameter value is a dict.\n");
|
||||
} else {
|
||||
log_abort();
|
||||
}
|
||||
|
||||
Const value = json_parse_attr_param_value(it.second);
|
||||
results[key] = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2484,7 +2484,7 @@ struct ReadPass : public Pass {
|
|||
args[0] = "verific";
|
||||
} else {
|
||||
args[0] = "read_verilog";
|
||||
args.erase(args.begin()+1, args.begin()+2);
|
||||
args[1] = "-defer";
|
||||
}
|
||||
Pass::call(design, args);
|
||||
return;
|
||||
|
@ -2498,6 +2498,7 @@ struct ReadPass : public Pass {
|
|||
if (args[1] == "-formal")
|
||||
args.insert(args.begin()+1, std::string());
|
||||
args[1] = "-sv";
|
||||
args.insert(args.begin()+1, "-defer");
|
||||
}
|
||||
Pass::call(design, args);
|
||||
return;
|
||||
|
|
|
@ -70,6 +70,9 @@ YOSYS_NAMESPACE_END
|
|||
#define YY_INPUT(buf,result,max_size) \
|
||||
result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
|
||||
|
||||
#undef YY_BUF_SIZE
|
||||
#define YY_BUF_SIZE 65536
|
||||
|
||||
%}
|
||||
|
||||
%option yylineno
|
||||
|
|
|
@ -325,6 +325,8 @@ Aig::Aig(Cell *cell)
|
|||
int A = mk.inport("\\A", i);
|
||||
int B = mk.inport("\\B", i);
|
||||
int Y = mk.mux_gate(A, B, S);
|
||||
if (cell->type == "$_NMUX_")
|
||||
Y = mk.not_gate(Y);
|
||||
mk.outport(Y, "\\Y", i);
|
||||
}
|
||||
goto optimize;
|
||||
|
|
|
@ -193,6 +193,7 @@ struct CellTypes
|
|||
setup_type("$_ANDNOT_", {A, B}, {Y}, true);
|
||||
setup_type("$_ORNOT_", {A, B}, {Y}, true);
|
||||
setup_type("$_MUX_", {A, B, S}, {Y}, true);
|
||||
setup_type("$_NMUX_", {A, B, S}, {Y}, true);
|
||||
setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true);
|
||||
setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
|
||||
setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);
|
||||
|
|
|
@ -145,7 +145,7 @@ struct ConstEval
|
|||
if (cell->hasPort("\\B"))
|
||||
sig_b = cell->getPort("\\B");
|
||||
|
||||
if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_")
|
||||
if (cell->type.in("$mux", "$pmux", "$_MUX_", "$_NMUX_"))
|
||||
{
|
||||
std::vector<RTLIL::SigSpec> y_candidates;
|
||||
int count_maybe_set_s_bits = 0;
|
||||
|
@ -175,7 +175,10 @@ struct ConstEval
|
|||
for (auto &yc : y_candidates) {
|
||||
if (!eval(yc, undef, cell))
|
||||
return false;
|
||||
y_values.push_back(yc.as_const());
|
||||
if (cell->type == "$_NMUX_")
|
||||
y_values.push_back(RTLIL::const_not(yc.as_const(), Const(), false, false, GetSize(yc)));
|
||||
else
|
||||
y_values.push_back(yc.as_const());
|
||||
}
|
||||
|
||||
if (y_values.size() > 1)
|
||||
|
|
134
kernel/cost.h
134
kernel/cost.h
|
@ -24,62 +24,92 @@
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr);
|
||||
|
||||
inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const> ¶meters = dict<RTLIL::IdString, RTLIL::Const>(),
|
||||
RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr)
|
||||
struct CellCosts
|
||||
{
|
||||
static dict<RTLIL::IdString, int> gate_cost = {
|
||||
{ "$_BUF_", 1 },
|
||||
{ "$_NOT_", 2 },
|
||||
{ "$_AND_", 4 },
|
||||
{ "$_NAND_", 4 },
|
||||
{ "$_OR_", 4 },
|
||||
{ "$_NOR_", 4 },
|
||||
{ "$_ANDNOT_", 4 },
|
||||
{ "$_ORNOT_", 4 },
|
||||
{ "$_XOR_", 8 },
|
||||
{ "$_XNOR_", 8 },
|
||||
{ "$_AOI3_", 6 },
|
||||
{ "$_OAI3_", 6 },
|
||||
{ "$_AOI4_", 8 },
|
||||
{ "$_OAI4_", 8 },
|
||||
{ "$_MUX_", 4 }
|
||||
};
|
||||
|
||||
if (gate_cost.count(type))
|
||||
return gate_cost.at(type);
|
||||
|
||||
if (parameters.empty() && design && design->module(type))
|
||||
{
|
||||
RTLIL::Module *mod = design->module(type);
|
||||
|
||||
if (mod->attributes.count("\\cost"))
|
||||
return mod->attributes.at("\\cost").as_int();
|
||||
|
||||
dict<RTLIL::IdString, int> local_mod_cost_cache;
|
||||
if (mod_cost_cache == nullptr)
|
||||
mod_cost_cache = &local_mod_cost_cache;
|
||||
|
||||
if (mod_cost_cache->count(mod->name))
|
||||
return mod_cost_cache->at(mod->name);
|
||||
|
||||
int module_cost = 1;
|
||||
for (auto c : mod->cells())
|
||||
module_cost += get_cell_cost(c, mod_cost_cache);
|
||||
|
||||
(*mod_cost_cache)[mod->name] = module_cost;
|
||||
return module_cost;
|
||||
static const dict<RTLIL::IdString, int>& default_gate_cost() {
|
||||
static const dict<RTLIL::IdString, int> db = {
|
||||
{ "$_BUF_", 1 },
|
||||
{ "$_NOT_", 2 },
|
||||
{ "$_AND_", 4 },
|
||||
{ "$_NAND_", 4 },
|
||||
{ "$_OR_", 4 },
|
||||
{ "$_NOR_", 4 },
|
||||
{ "$_ANDNOT_", 4 },
|
||||
{ "$_ORNOT_", 4 },
|
||||
{ "$_XOR_", 5 },
|
||||
{ "$_XNOR_", 5 },
|
||||
{ "$_AOI3_", 6 },
|
||||
{ "$_OAI3_", 6 },
|
||||
{ "$_AOI4_", 7 },
|
||||
{ "$_OAI4_", 7 },
|
||||
{ "$_MUX_", 4 },
|
||||
{ "$_NMUX_", 4 }
|
||||
};
|
||||
return db;
|
||||
}
|
||||
|
||||
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters));
|
||||
return 1;
|
||||
}
|
||||
static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
|
||||
static const dict<RTLIL::IdString, int> db = {
|
||||
{ "$_BUF_", 1 },
|
||||
{ "$_NOT_", 2 },
|
||||
{ "$_AND_", 6 },
|
||||
{ "$_NAND_", 4 },
|
||||
{ "$_OR_", 6 },
|
||||
{ "$_NOR_", 4 },
|
||||
{ "$_ANDNOT_", 6 },
|
||||
{ "$_ORNOT_", 6 },
|
||||
{ "$_XOR_", 12 },
|
||||
{ "$_XNOR_", 12 },
|
||||
{ "$_AOI3_", 6 },
|
||||
{ "$_OAI3_", 6 },
|
||||
{ "$_AOI4_", 8 },
|
||||
{ "$_OAI4_", 8 },
|
||||
{ "$_MUX_", 12 },
|
||||
{ "$_NMUX_", 10 }
|
||||
};
|
||||
return db;
|
||||
}
|
||||
|
||||
inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache)
|
||||
{
|
||||
return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache);
|
||||
}
|
||||
dict<RTLIL::IdString, int> mod_cost_cache;
|
||||
const dict<RTLIL::IdString, int> *gate_cost = nullptr;
|
||||
Design *design = nullptr;
|
||||
|
||||
int get(RTLIL::IdString type) const
|
||||
{
|
||||
if (gate_cost && gate_cost->count(type))
|
||||
return gate_cost->at(type);
|
||||
|
||||
log_warning("Can't determine cost of %s cell.\n", log_id(type));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get(RTLIL::Cell *cell)
|
||||
{
|
||||
if (gate_cost && gate_cost->count(cell->type))
|
||||
return gate_cost->at(cell->type);
|
||||
|
||||
if (design && design->module(cell->type) && cell->parameters.empty())
|
||||
{
|
||||
RTLIL::Module *mod = design->module(cell->type);
|
||||
|
||||
if (mod->attributes.count("\\cost"))
|
||||
return mod->attributes.at("\\cost").as_int();
|
||||
|
||||
if (mod_cost_cache.count(mod->name))
|
||||
return mod_cost_cache.at(mod->name);
|
||||
|
||||
int module_cost = 1;
|
||||
for (auto c : mod->cells())
|
||||
module_cost += get(c);
|
||||
|
||||
mod_cost_cache[mod->name] = module_cost;
|
||||
return module_cost;
|
||||
}
|
||||
|
||||
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
|
|
|
@ -522,6 +522,12 @@ int main(int argc, char **argv)
|
|||
if (!backend_command.empty())
|
||||
run_backend(output_filename, backend_command);
|
||||
|
||||
yosys_design->check();
|
||||
for (auto it : saved_designs)
|
||||
it.second->check();
|
||||
for (auto it : pushed_designs)
|
||||
it->check();
|
||||
|
||||
if (!depsfile.empty())
|
||||
{
|
||||
FILE *f = fopen(depsfile.c_str(), "wt");
|
||||
|
|
|
@ -25,6 +25,65 @@
|
|||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef YOSYS_ENABLE_ZLIB
|
||||
#include <zlib.h>
|
||||
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
#define GZ_BUFFER_SIZE 8192
|
||||
void decompress_gzip(const std::string &filename, std::stringstream &out)
|
||||
{
|
||||
char buffer[GZ_BUFFER_SIZE];
|
||||
int bytes_read;
|
||||
gzFile gzf = gzopen(filename.c_str(), "rb");
|
||||
while(!gzeof(gzf)) {
|
||||
bytes_read = gzread(gzf, reinterpret_cast<void *>(buffer), GZ_BUFFER_SIZE);
|
||||
out.write(buffer, bytes_read);
|
||||
}
|
||||
gzclose(gzf);
|
||||
}
|
||||
|
||||
/*
|
||||
An output stream that uses a stringbuf to buffer data internally,
|
||||
using zlib to write gzip-compressed data every time the stream is flushed.
|
||||
*/
|
||||
class gzip_ostream : public std::ostream {
|
||||
public:
|
||||
gzip_ostream()
|
||||
{
|
||||
rdbuf(&outbuf);
|
||||
}
|
||||
bool open(const std::string &filename)
|
||||
{
|
||||
return outbuf.open(filename);
|
||||
}
|
||||
private:
|
||||
class gzip_streambuf : public std::stringbuf {
|
||||
public:
|
||||
gzip_streambuf() { };
|
||||
bool open(const std::string &filename)
|
||||
{
|
||||
gzf = gzopen(filename.c_str(), "wb");
|
||||
return gzf != nullptr;
|
||||
}
|
||||
virtual int sync() override
|
||||
{
|
||||
gzwrite(gzf, reinterpret_cast<const void *>(str().c_str()), unsigned(str().size()));
|
||||
str("");
|
||||
return 0;
|
||||
}
|
||||
~gzip_streambuf()
|
||||
{
|
||||
sync();
|
||||
gzclose(gzf);
|
||||
}
|
||||
private:
|
||||
gzFile gzf = nullptr;
|
||||
} outbuf;
|
||||
};
|
||||
PRIVATE_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
#define MAX_REG_COUNT 1000
|
||||
|
@ -236,8 +295,6 @@ void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
|
|||
pass_register[args[0]]->post_execute(state);
|
||||
while (design->selection_stack.size() > orig_sel_stack_pos)
|
||||
design->selection_stack.pop_back();
|
||||
|
||||
design->check();
|
||||
}
|
||||
|
||||
void Pass::call_on_selection(RTLIL::Design *design, const RTLIL::Selection &selection, std::string command)
|
||||
|
@ -319,8 +376,10 @@ void ScriptPass::run(std::string command, std::string info)
|
|||
log(" %s\n", command.c_str());
|
||||
else
|
||||
log(" %s %s\n", command.c_str(), info.c_str());
|
||||
} else
|
||||
} else {
|
||||
Pass::call(active_design, command);
|
||||
active_design->check();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to)
|
||||
|
@ -436,6 +495,28 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
|
|||
delete ff;
|
||||
else
|
||||
f = ff;
|
||||
if (f != NULL) {
|
||||
// Check for gzip magic
|
||||
unsigned char magic[3];
|
||||
int n = readsome(*ff, reinterpret_cast<char*>(magic), 3);
|
||||
if (n == 3 && magic[0] == 0x1f && magic[1] == 0x8b) {
|
||||
#ifdef YOSYS_ENABLE_ZLIB
|
||||
log("Found gzip magic in file `%s', decompressing using zlib.\n", filename.c_str());
|
||||
if (magic[2] != 8)
|
||||
log_cmd_error("gzip file `%s' uses unsupported compression type %02x\n",
|
||||
filename.c_str(), unsigned(magic[2]));
|
||||
delete ff;
|
||||
std::stringstream *df = new std::stringstream();
|
||||
decompress_gzip(filename, *df);
|
||||
f = df;
|
||||
#else
|
||||
log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", filename.c_str());
|
||||
#endif
|
||||
} else {
|
||||
ff->clear();
|
||||
ff->seekg(0, std::ios::beg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f == NULL)
|
||||
log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
|
||||
|
@ -492,8 +573,6 @@ void Frontend::frontend_call(RTLIL::Design *design, std::istream *f, std::string
|
|||
args.push_back(filename);
|
||||
frontend_register[args[0]]->execute(args, design);
|
||||
}
|
||||
|
||||
design->check();
|
||||
}
|
||||
|
||||
Backend::Backend(std::string name, std::string short_help) :
|
||||
|
@ -546,14 +625,28 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
|
|||
|
||||
filename = arg;
|
||||
rewrite_filename(filename);
|
||||
std::ofstream *ff = new std::ofstream;
|
||||
ff->open(filename.c_str(), std::ofstream::trunc);
|
||||
yosys_output_files.insert(filename);
|
||||
if (ff->fail()) {
|
||||
delete ff;
|
||||
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
|
||||
if (filename.size() > 3 && filename.substr(filename.size()-3) == ".gz") {
|
||||
#ifdef YOSYS_ENABLE_ZLIB
|
||||
gzip_ostream *gf = new gzip_ostream;
|
||||
if (!gf->open(filename)) {
|
||||
delete gf;
|
||||
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
|
||||
}
|
||||
yosys_output_files.insert(filename);
|
||||
f = gf;
|
||||
#else
|
||||
log_cmd_error("Yosys is compiled without zlib support, unable to write gzip output.\n");
|
||||
#endif
|
||||
} else {
|
||||
std::ofstream *ff = new std::ofstream;
|
||||
ff->open(filename.c_str(), std::ofstream::trunc);
|
||||
yosys_output_files.insert(filename);
|
||||
if (ff->fail()) {
|
||||
delete ff;
|
||||
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
|
||||
}
|
||||
f = ff;
|
||||
}
|
||||
f = ff;
|
||||
}
|
||||
|
||||
if (called_with_fp)
|
||||
|
@ -603,8 +696,6 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f
|
|||
|
||||
while (design->selection_stack.size() > orig_sel_stack_pos)
|
||||
design->selection_stack.pop_back();
|
||||
|
||||
design->check();
|
||||
}
|
||||
|
||||
static struct CellHelpMessages {
|
||||
|
|
|
@ -1249,6 +1249,7 @@ namespace {
|
|||
if (cell->type == "$_ANDNOT_") { check_gate("ABY"); return; }
|
||||
if (cell->type == "$_ORNOT_") { check_gate("ABY"); return; }
|
||||
if (cell->type == "$_MUX_") { check_gate("ABSY"); return; }
|
||||
if (cell->type == "$_NMUX_") { check_gate("ABSY"); return; }
|
||||
if (cell->type == "$_AOI3_") { check_gate("ABCY"); return; }
|
||||
if (cell->type == "$_OAI3_") { check_gate("ABCY"); return; }
|
||||
if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; }
|
||||
|
@ -1976,6 +1977,7 @@ DEF_METHOD_3(XnorGate, "$_XNOR_", A, B, Y)
|
|||
DEF_METHOD_3(AndnotGate, "$_ANDNOT_", A, B, Y)
|
||||
DEF_METHOD_3(OrnotGate, "$_ORNOT_", A, B, Y)
|
||||
DEF_METHOD_4(MuxGate, "$_MUX_", A, B, S, Y)
|
||||
DEF_METHOD_4(NmuxGate, "$_NMUX_", A, B, S, Y)
|
||||
DEF_METHOD_4(Aoi3Gate, "$_AOI3_", A, B, C, Y)
|
||||
DEF_METHOD_4(Oai3Gate, "$_OAI3_", A, B, C, Y)
|
||||
DEF_METHOD_5(Aoi4Gate, "$_AOI4_", A, B, C, D, Y)
|
||||
|
|
|
@ -420,8 +420,12 @@ namespace RTLIL
|
|||
// It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
|
||||
|
||||
template<typename T>
|
||||
struct ObjIterator
|
||||
{
|
||||
struct ObjIterator {
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
typename dict<RTLIL::IdString, T>::iterator it;
|
||||
dict<RTLIL::IdString, T> *list_p;
|
||||
int *refcount_p;
|
||||
|
@ -474,13 +478,25 @@ namespace RTLIL
|
|||
return it != other.it;
|
||||
}
|
||||
|
||||
inline void operator++() {
|
||||
|
||||
inline bool operator==(const RTLIL::ObjIterator<T> &other) const {
|
||||
return !(*this != other);
|
||||
}
|
||||
|
||||
inline ObjIterator<T>& operator++() {
|
||||
log_assert(list_p != nullptr);
|
||||
if (++it == list_p->end()) {
|
||||
(*refcount_p)--;
|
||||
list_p = nullptr;
|
||||
refcount_p = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const ObjIterator<T> operator++(int) {
|
||||
ObjIterator<T> result(*this);
|
||||
++(*this);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -772,6 +788,7 @@ public:
|
|||
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const;
|
||||
RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
|
||||
RTLIL::SigSpec extract(int offset, int length = 1) const;
|
||||
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, width_ - offset); }
|
||||
|
||||
void append(const RTLIL::SigSpec &signal);
|
||||
void append_bit(const RTLIL::SigBit &bit);
|
||||
|
@ -818,6 +835,7 @@ public:
|
|||
|
||||
operator std::vector<RTLIL::SigChunk>() const { return chunks(); }
|
||||
operator std::vector<RTLIL::SigBit>() const { return bits(); }
|
||||
RTLIL::SigBit at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; }
|
||||
|
||||
unsigned int hash() const { if (!hash_) updhash(); return hash_; };
|
||||
|
||||
|
@ -1138,6 +1156,7 @@ public:
|
|||
RTLIL::Cell* addAndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addOrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addMuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addNmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addOai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y, const std::string &src = "");
|
||||
|
@ -1213,6 +1232,7 @@ public:
|
|||
RTLIL::SigBit AndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit OrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit MuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = "");
|
||||
RTLIL::SigBit NmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = "");
|
||||
RTLIL::SigBit Aoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = "");
|
||||
RTLIL::SigBit Oai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = "");
|
||||
RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, const std::string &src = "");
|
||||
|
|
|
@ -475,7 +475,7 @@ struct SatGen
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == "$_MUX_" || cell->type == "$mux")
|
||||
if (cell->type == "$_MUX_" || cell->type == "$mux" || cell->type == "$_NMUX_")
|
||||
{
|
||||
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
|
||||
std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
|
||||
|
@ -483,7 +483,10 @@ struct SatGen
|
|||
std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
|
||||
|
||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||
ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy));
|
||||
if (cell->type == "$_NMUX_")
|
||||
ez->assume(ez->vec_eq(ez->vec_not(ez->vec_ite(s.at(0), b, a)), yy));
|
||||
else
|
||||
ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy));
|
||||
|
||||
if (model_undef)
|
||||
{
|
||||
|
|
|
@ -894,23 +894,26 @@ void run_frontend(std::string filename, std::string command, std::string *backen
|
|||
design = yosys_design;
|
||||
|
||||
if (command == "auto") {
|
||||
if (filename.size() > 2 && filename.substr(filename.size()-2) == ".v")
|
||||
std::string filename_trim = filename;
|
||||
if (filename_trim.size() > 3 && filename_trim.substr(filename_trim.size()-3) == ".gz")
|
||||
filename_trim.erase(filename_trim.size()-3);
|
||||
if (filename_trim.size() > 2 && filename_trim.substr(filename_trim.size()-2) == ".v")
|
||||
command = "verilog";
|
||||
else if (filename.size() > 2 && filename.substr(filename.size()-3) == ".sv")
|
||||
else if (filename_trim.size() > 2 && filename_trim.substr(filename_trim.size()-3) == ".sv")
|
||||
command = "verilog -sv";
|
||||
else if (filename.size() > 3 && filename.substr(filename.size()-4) == ".vhd")
|
||||
else if (filename_trim.size() > 3 && filename_trim.substr(filename_trim.size()-4) == ".vhd")
|
||||
command = "vhdl";
|
||||
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".blif")
|
||||
else if (filename_trim.size() > 4 && filename_trim.substr(filename_trim.size()-5) == ".blif")
|
||||
command = "blif";
|
||||
else if (filename.size() > 5 && filename.substr(filename.size()-6) == ".eblif")
|
||||
else if (filename_trim.size() > 5 && filename_trim.substr(filename_trim.size()-6) == ".eblif")
|
||||
command = "blif";
|
||||
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".json")
|
||||
else if (filename_trim.size() > 4 && filename_trim.substr(filename_trim.size()-5) == ".json")
|
||||
command = "json";
|
||||
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
|
||||
else if (filename_trim.size() > 3 && filename_trim.substr(filename_trim.size()-3) == ".il")
|
||||
command = "ilang";
|
||||
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".ys")
|
||||
else if (filename_trim.size() > 3 && filename_trim.substr(filename_trim.size()-3) == ".ys")
|
||||
command = "script";
|
||||
else if (filename.size() > 3 && filename.substr(filename.size()-4) == ".tcl")
|
||||
else if (filename_trim.size() > 3 && filename_trim.substr(filename_trim.size()-4) == ".tcl")
|
||||
command = "tcl";
|
||||
else if (filename == "-")
|
||||
command = "script";
|
||||
|
@ -961,14 +964,18 @@ void run_frontend(std::string filename, std::string command, std::string *backen
|
|||
command += next_line;
|
||||
}
|
||||
handle_label(command, from_to_active, run_from, run_to);
|
||||
if (from_to_active)
|
||||
if (from_to_active) {
|
||||
Pass::call(design, command);
|
||||
design->check();
|
||||
}
|
||||
}
|
||||
|
||||
if (!command.empty()) {
|
||||
handle_label(command, from_to_active, run_from, run_to);
|
||||
if (from_to_active)
|
||||
if (from_to_active) {
|
||||
Pass::call(design, command);
|
||||
design->check();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
|
@ -997,6 +1004,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen
|
|||
Pass::call(design, vector<string>({command, filename}));
|
||||
else
|
||||
Frontend::frontend_call(design, NULL, filename, command);
|
||||
design->check();
|
||||
}
|
||||
|
||||
void run_frontend(std::string filename, std::string command, RTLIL::Design *design)
|
||||
|
@ -1180,6 +1188,7 @@ void shell(RTLIL::Design *design)
|
|||
design->selection_stack.pop_back();
|
||||
log_reset_stack();
|
||||
}
|
||||
design->check();
|
||||
}
|
||||
if (command == NULL)
|
||||
printf("exit\n");
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
@ -87,6 +88,10 @@ 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
|
||||
#endif
|
||||
|
||||
|
|
|
@ -494,6 +494,6 @@ Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLA
|
|||
\end{fixme}
|
||||
|
||||
\begin{fixme}
|
||||
Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells.
|
||||
Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, {\tt \$\_OAI4\_}, and {\tt \$\_NMUX\_} cells.
|
||||
\end{fixme}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ SOFTWARE. */
|
|||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int child_pid=0;
|
||||
|
||||
|
@ -338,7 +339,7 @@ int run(int argc, char **argv, int is_gui) {
|
|||
|
||||
if (is_gui) {
|
||||
/* Use exec, we don't need to wait for the GUI to finish */
|
||||
execv(ptr, (const char * const *)(newargs));
|
||||
execv(ptr, (char * const *)(newargs));
|
||||
return fail("Could not exec %s", ptr); /* shouldn't get here! */
|
||||
}
|
||||
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "passes/techmap/libparse.h"
|
||||
|
||||
#include "kernel/log.h"
|
||||
#include "kernel/cost.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
@ -228,21 +227,16 @@ struct statdata_t
|
|||
{
|
||||
int tran_cnt = 0;
|
||||
bool tran_cnt_exact = true;
|
||||
auto &gate_costs = CellCosts::cmos_gate_cost();
|
||||
|
||||
for (auto it : num_cells_by_type) {
|
||||
auto ctype = it.first;
|
||||
auto cnum = it.second;
|
||||
|
||||
if (ctype == "$_NOT_")
|
||||
tran_cnt += 2*cnum;
|
||||
else if (ctype.in("$_NAND_", "$_NOR_"))
|
||||
tran_cnt += 4*cnum;
|
||||
else if (ctype.in("$_AOI3_", "$_OAI3_"))
|
||||
tran_cnt += 6*cnum;
|
||||
else if (ctype.in("$_AOI4_", "$_OAI4_"))
|
||||
tran_cnt += 8*cnum;
|
||||
if (gate_costs.count(ctype))
|
||||
tran_cnt += cnum * gate_costs.at(ctype);
|
||||
else if (ctype.in("$_DFF_P_", "$_DFF_N_"))
|
||||
tran_cnt += 16*cnum;
|
||||
tran_cnt += cnum * 16;
|
||||
else
|
||||
tran_cnt_exact = false;
|
||||
}
|
||||
|
|
|
@ -641,6 +641,31 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
did_something = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (cell->type.in("$add", "$sub")) {
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
|
||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
|
||||
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
|
||||
bool sub = cell->type == "$sub";
|
||||
|
||||
int i;
|
||||
for (i = 0; i < GetSize(sig_y); i++) {
|
||||
if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx)
|
||||
module->connect(sig_y[i], sig_a[i]);
|
||||
else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx)
|
||||
module->connect(sig_y[i], sig_b[i]);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (i > 0) {
|
||||
cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str());
|
||||
cell->setPort("\\A", sig_a.extract_end(i));
|
||||
cell->setPort("\\B", sig_b.extract_end(i));
|
||||
cell->setPort("\\Y", sig_y.extract_end(i));
|
||||
cell->fixup_parameters();
|
||||
did_something = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || cell->type == "$shift" || cell->type == "$shiftx" ||
|
||||
|
|
|
@ -81,7 +81,7 @@ struct OptLutWorker
|
|||
}
|
||||
}
|
||||
|
||||
log("Number of LUTs: %8zu\n", luts.size());
|
||||
log("Number of LUTs: %8d\n", GetSize(luts));
|
||||
for (int arity = 1; arity <= max_arity; arity++)
|
||||
{
|
||||
if (arity_counts[arity])
|
||||
|
@ -351,14 +351,14 @@ struct OptLutWorker
|
|||
|
||||
int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size();
|
||||
if (lutA_dlogic_inputs.size())
|
||||
log_debug(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size());
|
||||
log_debug(" Cell A is a %d-LUT with %d dedicated connections. ", lutA_arity, GetSize(lutA_dlogic_inputs));
|
||||
else
|
||||
log_debug(" Cell A is a %d-LUT. ", lutA_arity);
|
||||
if (lutB_dlogic_inputs.size())
|
||||
log_debug("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size());
|
||||
log_debug("Cell B is a %d-LUT with %d dedicated connections.\n", lutB_arity, GetSize(lutB_dlogic_inputs));
|
||||
else
|
||||
log_debug("Cell B is a %d-LUT.\n", lutB_arity);
|
||||
log_debug(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity);
|
||||
log_debug(" Cells share %d input(s) and can be merged into one %d-LUT.\n", GetSize(common_inputs), lutM_arity);
|
||||
|
||||
const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B;
|
||||
int combine_mask = 0;
|
||||
|
|
|
@ -171,7 +171,7 @@ struct RmportsPassPass : public Pass {
|
|||
wire->port_output = false;
|
||||
wire->port_id = 0;
|
||||
}
|
||||
log("Removed %zu unused ports.\n", unused_ports.size());
|
||||
log("Removed %d unused ports.\n", GetSize(unused_ports));
|
||||
|
||||
// Re-number all of the wires that DO have ports still on them
|
||||
for(size_t i=0; i<module->ports.size(); i++)
|
||||
|
|
|
@ -342,9 +342,9 @@ struct WreduceWorker
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor"))
|
||||
if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor", "$sub"))
|
||||
{
|
||||
bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
|
||||
bool is_signed = cell->getParam("\\A_SIGNED").as_bool() || cell->type == "$sub";
|
||||
|
||||
int a_size = 0, b_size = 0;
|
||||
if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A"));
|
||||
|
@ -352,7 +352,7 @@ struct WreduceWorker
|
|||
|
||||
int max_y_size = max(a_size, b_size);
|
||||
|
||||
if (cell->type == "$add")
|
||||
if (cell->type.in("$add", "$sub"))
|
||||
max_y_size++;
|
||||
|
||||
if (cell->type == "$mul")
|
||||
|
|
|
@ -82,14 +82,23 @@ struct PruneWorker
|
|||
if (root) {
|
||||
bool promotable = true;
|
||||
for (auto &bit : lhs) {
|
||||
if (bit.wire && affected[bit]) {
|
||||
if (bit.wire && affected[bit] && !assigned[bit]) {
|
||||
promotable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (promotable) {
|
||||
RTLIL::SigSpec rhs = sigmap(it->second);
|
||||
RTLIL::SigSig conn;
|
||||
for (int i = 0; i < GetSize(lhs); i++) {
|
||||
RTLIL::SigBit lhs_bit = lhs[i];
|
||||
if (lhs_bit.wire && !assigned[lhs_bit]) {
|
||||
conn.first.append_bit(lhs_bit);
|
||||
conn.second.append(rhs.extract(i));
|
||||
}
|
||||
}
|
||||
promoted_count++;
|
||||
module->connect(*it);
|
||||
module->connect(conn);
|
||||
remove.insert(*it);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <sstream>
|
||||
#include <climits>
|
||||
|
@ -81,6 +82,7 @@ enum class gate_type_t {
|
|||
G_ANDNOT,
|
||||
G_ORNOT,
|
||||
G_MUX,
|
||||
G_NMUX,
|
||||
G_AOI3,
|
||||
G_OAI3,
|
||||
G_AOI4,
|
||||
|
@ -111,7 +113,7 @@ std::vector<gate_t> signal_list;
|
|||
std::map<RTLIL::SigBit, int> signal_map;
|
||||
std::map<RTLIL::SigBit, RTLIL::State> signal_init;
|
||||
pool<std::string> enabled_gates;
|
||||
bool recover_init;
|
||||
bool recover_init, cmos_cost;
|
||||
|
||||
bool clk_polarity, en_polarity;
|
||||
RTLIL::SigSpec clk_sig, en_sig;
|
||||
|
@ -257,7 +259,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
|
|||
return;
|
||||
}
|
||||
|
||||
if (cell->type == "$_MUX_")
|
||||
if (cell->type.in("$_MUX_", "$_NMUX_"))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = cell->getPort("\\A");
|
||||
RTLIL::SigSpec sig_b = cell->getPort("\\B");
|
||||
|
@ -273,7 +275,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
|
|||
int mapped_b = map_signal(sig_b);
|
||||
int mapped_s = map_signal(sig_s);
|
||||
|
||||
map_signal(sig_y, G(MUX), mapped_a, mapped_b, mapped_s);
|
||||
map_signal(sig_y, cell->type == "$_MUX_" ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s);
|
||||
|
||||
module->remove(cell);
|
||||
return;
|
||||
|
@ -885,6 +887,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
|||
fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
|
||||
fprintf(f, "1-0 1\n");
|
||||
fprintf(f, "-11 1\n");
|
||||
} else if (si.type == G(NMUX)) {
|
||||
fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
|
||||
fprintf(f, "0-0 1\n");
|
||||
fprintf(f, "-01 1\n");
|
||||
} else if (si.type == G(AOI3)) {
|
||||
fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
|
||||
fprintf(f, "-00 1\n");
|
||||
|
@ -925,46 +931,50 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
|||
{
|
||||
log_header(design, "Executing ABC.\n");
|
||||
|
||||
auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost();
|
||||
|
||||
buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
|
||||
f = fopen(buffer.c_str(), "wt");
|
||||
if (f == NULL)
|
||||
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
|
||||
fprintf(f, "GATE ZERO 1 Y=CONST0;\n");
|
||||
fprintf(f, "GATE ONE 1 Y=CONST1;\n");
|
||||
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_BUF_"));
|
||||
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOT_"));
|
||||
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_BUF_"));
|
||||
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOT_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("AND"))
|
||||
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_AND_"));
|
||||
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_AND_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("NAND"))
|
||||
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NAND_"));
|
||||
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NAND_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("OR"))
|
||||
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_OR_"));
|
||||
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_OR_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("NOR"))
|
||||
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOR_"));
|
||||
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOR_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("XOR"))
|
||||
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_"));
|
||||
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XOR_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("XNOR"))
|
||||
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_"));
|
||||
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XNOR_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("ANDNOT"))
|
||||
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ANDNOT_"));
|
||||
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ANDNOT_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("ORNOT"))
|
||||
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ORNOT_"));
|
||||
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ORNOT_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("AOI3"))
|
||||
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI3_"));
|
||||
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI3_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("OAI3"))
|
||||
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI3_"));
|
||||
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI3_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("AOI4"))
|
||||
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI4_"));
|
||||
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI4_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("OAI4"))
|
||||
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_"));
|
||||
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI4_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("MUX"))
|
||||
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_MUX_"));
|
||||
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_MUX_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("NMUX"))
|
||||
fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_NMUX_"));
|
||||
if (map_mux4)
|
||||
fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*get_cell_cost("$_MUX_"));
|
||||
fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at("$_MUX_"));
|
||||
if (map_mux8)
|
||||
fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_"));
|
||||
fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at("$_MUX_"));
|
||||
if (map_mux16)
|
||||
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_"));
|
||||
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at("$_MUX_"));
|
||||
fclose(f);
|
||||
|
||||
if (!lut_costs.empty()) {
|
||||
|
@ -1065,8 +1075,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
|||
design->select(module, cell);
|
||||
continue;
|
||||
}
|
||||
if (c->type == "\\MUX") {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_");
|
||||
if (c->type == "\\MUX" || c->type == "\\NMUX") {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
|
||||
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
|
||||
|
@ -1406,11 +1416,12 @@ struct AbcPass : public Pass {
|
|||
log("\n");
|
||||
log(" The following aliases can be used to reference common sets of gate types:\n");
|
||||
log(" simple: AND OR XOR MUX\n");
|
||||
log(" cmos2: NAND NOR\n");
|
||||
log(" cmos3: NAND NOR AOI3 OAI3\n");
|
||||
log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n");
|
||||
log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
|
||||
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n");
|
||||
log(" cmos2: NAND NOR\n");
|
||||
log(" cmos3: NAND NOR AOI3 OAI3\n");
|
||||
log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n");
|
||||
log(" cmos: NAND NOR AOI3 OAI3 AOI4 OAI4 NMUX MUX XOR XNOR\n");
|
||||
log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
|
||||
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n");
|
||||
log("\n");
|
||||
log(" Prefix a gate type with a '-' to remove it from the list. For example\n");
|
||||
log(" the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent.\n");
|
||||
|
@ -1488,6 +1499,7 @@ struct AbcPass : public Pass {
|
|||
map_mux8 = false;
|
||||
map_mux16 = false;
|
||||
enabled_gates.clear();
|
||||
cmos_cost = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef ABCEXTERNAL
|
||||
|
@ -1628,11 +1640,15 @@ struct AbcPass : public Pass {
|
|||
goto ok_alias;
|
||||
}
|
||||
if (g == "cmos2") {
|
||||
if (!remove_gates)
|
||||
cmos_cost = true;
|
||||
gate_list.push_back("NAND");
|
||||
gate_list.push_back("NOR");
|
||||
goto ok_alias;
|
||||
}
|
||||
if (g == "cmos3") {
|
||||
if (!remove_gates)
|
||||
cmos_cost = true;
|
||||
gate_list.push_back("NAND");
|
||||
gate_list.push_back("NOR");
|
||||
gate_list.push_back("AOI3");
|
||||
|
@ -1640,6 +1656,8 @@ struct AbcPass : public Pass {
|
|||
goto ok_alias;
|
||||
}
|
||||
if (g == "cmos4") {
|
||||
if (!remove_gates)
|
||||
cmos_cost = true;
|
||||
gate_list.push_back("NAND");
|
||||
gate_list.push_back("NOR");
|
||||
gate_list.push_back("AOI3");
|
||||
|
@ -1648,6 +1666,21 @@ struct AbcPass : public Pass {
|
|||
gate_list.push_back("OAI4");
|
||||
goto ok_alias;
|
||||
}
|
||||
if (g == "cmos") {
|
||||
if (!remove_gates)
|
||||
cmos_cost = true;
|
||||
gate_list.push_back("NAND");
|
||||
gate_list.push_back("NOR");
|
||||
gate_list.push_back("AOI3");
|
||||
gate_list.push_back("OAI3");
|
||||
gate_list.push_back("AOI4");
|
||||
gate_list.push_back("OAI4");
|
||||
gate_list.push_back("NMUX");
|
||||
gate_list.push_back("MUX");
|
||||
gate_list.push_back("XOR");
|
||||
gate_list.push_back("XNOR");
|
||||
goto ok_alias;
|
||||
}
|
||||
if (g == "gates") {
|
||||
gate_list.push_back("AND");
|
||||
gate_list.push_back("NAND");
|
||||
|
|
|
@ -86,7 +86,7 @@ struct ExtractFaWorker
|
|||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (cell->type.in( "$_BUF_", "$_NOT_", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_",
|
||||
"$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_",
|
||||
"$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_", "$_NMUX_",
|
||||
"$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_"))
|
||||
{
|
||||
SigBit y = sigmap(SigBit(cell->getPort("\\Y")));
|
||||
|
|
|
@ -783,7 +783,7 @@ struct FlowmapWorker
|
|||
int depth = 0;
|
||||
for (auto label : labels)
|
||||
depth = max(depth, label.second);
|
||||
log("Mapped to %zu LUTs with maximum depth %d.\n", lut_nodes.size(), depth);
|
||||
log("Mapped to %d LUTs with maximum depth %d.\n", GetSize(lut_nodes), depth);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
|
@ -1195,7 +1195,7 @@ struct FlowmapWorker
|
|||
|
||||
bool relax_depth_for_bound(bool first, int depth_bound, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> &lut_critical_outputs)
|
||||
{
|
||||
size_t initial_count = lut_nodes.size();
|
||||
int initial_count = GetSize(lut_nodes);
|
||||
|
||||
for (auto node : lut_nodes)
|
||||
{
|
||||
|
@ -1215,7 +1215,7 @@ struct FlowmapWorker
|
|||
|
||||
if (potentials.empty())
|
||||
{
|
||||
log(" Relaxed to %zu (+%zu) LUTs.\n", lut_nodes.size(), lut_nodes.size() - initial_count);
|
||||
log(" Relaxed to %d (+%d) LUTs.\n", GetSize(lut_nodes), GetSize(lut_nodes) - initial_count);
|
||||
if (!first && break_num == 1)
|
||||
{
|
||||
log(" Design fully relaxed.\n");
|
||||
|
@ -1419,9 +1419,9 @@ struct FlowmapWorker
|
|||
lut_area += lut_table.size();
|
||||
|
||||
if ((int)input_nodes.size() >= minlut)
|
||||
log(" Packed into a %zu-LUT %s.%s.\n", input_nodes.size(), log_id(module), log_id(lut));
|
||||
log(" Packed into a %d-LUT %s.%s.\n", GetSize(input_nodes), log_id(module), log_id(lut));
|
||||
else
|
||||
log(" Packed into a %zu-LUT %s.%s (implemented as %d-LUT).\n", input_nodes.size(), log_id(module), log_id(lut), minlut);
|
||||
log(" Packed into a %d-LUT %s.%s (implemented as %d-LUT).\n", GetSize(input_nodes), log_id(module), log_id(lut), minlut);
|
||||
}
|
||||
|
||||
for (auto node : mapped_nodes)
|
||||
|
|
|
@ -50,7 +50,7 @@ struct AnlogicDetermineInitPass : public Pass {
|
|||
|
||||
extra_args(args, args.size(), design);
|
||||
|
||||
size_t cnt = 0;
|
||||
int cnt = 0;
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
for (auto cell : module->selected_cells())
|
||||
|
@ -65,7 +65,7 @@ struct AnlogicDetermineInitPass : public Pass {
|
|||
}
|
||||
}
|
||||
}
|
||||
log_header(design, "Updated %lu cells with determined init value.\n", cnt);
|
||||
log_header(design, "Updated %d cells with determined init value.\n", cnt);
|
||||
}
|
||||
} AnlogicDetermineInitPass;
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ struct AnlogicEqnPass : public Pass {
|
|||
|
||||
extra_args(args, args.size(), design);
|
||||
|
||||
size_t cnt = 0;
|
||||
int cnt = 0;
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
for (auto cell : module->selected_cells())
|
||||
|
@ -106,7 +106,7 @@ struct AnlogicEqnPass : public Pass {
|
|||
}
|
||||
}
|
||||
}
|
||||
log_header(design, "Updated %lu of AL_MAP_LUT* elements with equation.\n", cnt);
|
||||
log_header(design, "Updated %d of AL_MAP_LUT* elements with equation.\n", cnt);
|
||||
}
|
||||
} AnlogicEqnPass;
|
||||
|
||||
|
|
|
@ -42,10 +42,9 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
|||
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||
wire [Y_WIDTH+1:0] COx;
|
||||
wire [Y_WIDTH+1:0] C = {COx, CI};
|
||||
wire [Y_WIDTH+2:0] C = {COx, CI};
|
||||
|
||||
wire dummy;
|
||||
(* keep *)
|
||||
AL_MAP_ADDER #(
|
||||
.ALUTYPE("ADD_CARRY"))
|
||||
adder_cin (
|
||||
|
@ -55,19 +54,6 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
|||
|
||||
genvar i;
|
||||
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
|
||||
if(i==Y_WIDTH-1) begin
|
||||
(* keep *)
|
||||
AL_MAP_ADDER #(
|
||||
.ALUTYPE("ADD"))
|
||||
adder_cout (
|
||||
.c(C[Y_WIDTH]),
|
||||
.o(COx[Y_WIDTH])
|
||||
);
|
||||
assign CO = COx[Y_WIDTH];
|
||||
end
|
||||
else
|
||||
begin
|
||||
(* keep *)
|
||||
AL_MAP_ADDER #(
|
||||
.ALUTYPE("ADD")
|
||||
) adder_i (
|
||||
|
@ -76,9 +62,15 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
|||
.c(C[i+1]),
|
||||
.o({COx[i+1],Y[i]})
|
||||
);
|
||||
end
|
||||
end: slice
|
||||
endgenerate
|
||||
/* End implementation */
|
||||
AL_MAP_ADDER #(
|
||||
.ALUTYPE("ADD"))
|
||||
adder_cout (
|
||||
.c(C[Y_WIDTH+1]),
|
||||
.o(COx[Y_WIDTH+1])
|
||||
);
|
||||
assign CO = COx[Y_WIDTH+1];
|
||||
assign X = AA ^ BB;
|
||||
endmodule
|
|
@ -228,6 +228,25 @@ output Y;
|
|||
assign Y = S ? B : A;
|
||||
endmodule
|
||||
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
//-
|
||||
//- $_NMUX_ (A, B, S, Y)
|
||||
//-
|
||||
//- A 2-input inverting MUX gate.
|
||||
//-
|
||||
//- Truth table: A B S | Y
|
||||
//- -------+---
|
||||
//- 0 - 0 | 1
|
||||
//- 1 - 0 | 0
|
||||
//- - 0 1 | 1
|
||||
//- - 1 1 | 0
|
||||
//-
|
||||
module \$_NMUX_ (A, B, S, Y);
|
||||
input A, B, S;
|
||||
output Y;
|
||||
assign Y = S ? !B : !A;
|
||||
endmodule
|
||||
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
//-
|
||||
//- $_MUX4_ (A, B, C, D, S, T, Y)
|
||||
|
|
|
@ -333,6 +333,31 @@ module TRELLIS_SLICE(
|
|||
parameter [127:0] CCU2_INJECT1_0 = "NO";
|
||||
parameter [127:0] CCU2_INJECT1_1 = "NO";
|
||||
parameter WREMUX = "WRE";
|
||||
parameter WCKMUX = "WCK";
|
||||
|
||||
parameter A0MUX = "A0";
|
||||
parameter A1MUX = "A1";
|
||||
parameter B0MUX = "B0";
|
||||
parameter B1MUX = "B1";
|
||||
parameter C0MUX = "C0";
|
||||
parameter C1MUX = "C1";
|
||||
parameter D0MUX = "D0";
|
||||
parameter D1MUX = "D1";
|
||||
|
||||
wire A0m, B0m, C0m, D0m;
|
||||
wire A1m, B1m, C1m, D1m;
|
||||
|
||||
generate
|
||||
if (A0MUX == "1") assign A0m = 1'b1; else assign A0m = A0;
|
||||
if (B0MUX == "1") assign B0m = 1'b1; else assign B0m = B0;
|
||||
if (C0MUX == "1") assign C0m = 1'b1; else assign C0m = C0;
|
||||
if (D0MUX == "1") assign D0m = 1'b1; else assign D0m = D0;
|
||||
if (A1MUX == "1") assign A1m = 1'b1; else assign A1m = A1;
|
||||
if (B1MUX == "1") assign B1m = 1'b1; else assign B1m = B1;
|
||||
if (C1MUX == "1") assign C1m = 1'b1; else assign C1m = C1;
|
||||
if (D1MUX == "1") assign D1m = 1'b1; else assign D1m = D1;
|
||||
|
||||
endgenerate
|
||||
|
||||
function [15:0] permute_initval;
|
||||
input [15:0] initval;
|
||||
|
@ -350,13 +375,13 @@ module TRELLIS_SLICE(
|
|||
LUT4 #(
|
||||
.INIT(LUT0_INITVAL)
|
||||
) lut4_0 (
|
||||
.A(A0), .B(B0), .C(C0), .D(D0),
|
||||
.A(A0m), .B(B0m), .C(C0m), .D(D0m),
|
||||
.Z(F0)
|
||||
);
|
||||
LUT4 #(
|
||||
.INIT(LUT1_INITVAL)
|
||||
) lut4_1 (
|
||||
.A(A1), .B(B1), .C(C1), .D(D1),
|
||||
.A(A1m), .B(B1m), .C(C1m), .D(D1m),
|
||||
.Z(F1)
|
||||
);
|
||||
// LUT expansion muxes
|
||||
|
@ -370,20 +395,20 @@ module TRELLIS_SLICE(
|
|||
.INJECT1_1(CCU2_INJECT1_1)
|
||||
) ccu2c_i (
|
||||
.CIN(FCI),
|
||||
.A0(A0), .B0(B0), .C0(C0), .D0(D0),
|
||||
.A1(A1), .B1(B1), .C1(C1), .D1(D1),
|
||||
.A0(A0m), .B0(B0m), .C0(C0m), .D0(D0m),
|
||||
.A1(A1m), .B1(B1m), .C1(C1m), .D1(D1m),
|
||||
.S0(F0), .S1(F1),
|
||||
.COUT(FCO)
|
||||
);
|
||||
end else if (MODE == "RAMW") begin
|
||||
assign WDO0 = C1;
|
||||
assign WDO1 = A1;
|
||||
assign WDO2 = D1;
|
||||
assign WDO3 = B1;
|
||||
assign WADO0 = D0;
|
||||
assign WADO1 = B0;
|
||||
assign WADO2 = C0;
|
||||
assign WADO3 = A0;
|
||||
assign WDO0 = C1m;
|
||||
assign WDO1 = A1m;
|
||||
assign WDO2 = D1m;
|
||||
assign WDO3 = B1m;
|
||||
assign WADO0 = D0m;
|
||||
assign WADO1 = B0m;
|
||||
assign WADO2 = C0m;
|
||||
assign WADO3 = A0m;
|
||||
end else if (MODE == "DPRAM") begin
|
||||
TRELLIS_RAM16X2 #(
|
||||
.INITVAL_0(permute_initval(LUT0_INITVAL)),
|
||||
|
@ -393,17 +418,19 @@ module TRELLIS_SLICE(
|
|||
.DI0(WD0), .DI1(WD1),
|
||||
.WAD0(WAD0), .WAD1(WAD1), .WAD2(WAD2), .WAD3(WAD3),
|
||||
.WRE(WRE), .WCK(WCK),
|
||||
.RAD0(D0), .RAD1(B0), .RAD2(C0), .RAD3(A0),
|
||||
.RAD0(D0m), .RAD1(B0m), .RAD2(C0m), .RAD3(A0m),
|
||||
.DO0(F0), .DO1(F1)
|
||||
);
|
||||
// TODO: confirm RAD and INITVAL ordering
|
||||
// DPRAM mode contract?
|
||||
`ifdef FORMAL
|
||||
always @(*) begin
|
||||
assert(A0==A1);
|
||||
assert(B0==B1);
|
||||
assert(C0==C1);
|
||||
assert(D0==D1);
|
||||
assert(A0m==A1m);
|
||||
assert(B0m==B1m);
|
||||
assert(C0m==C1m);
|
||||
assert(D0m==D1m);
|
||||
end
|
||||
`endif
|
||||
end else begin
|
||||
ERROR_UNKNOWN_SLICE_MODE error();
|
||||
end
|
||||
|
@ -455,90 +482,206 @@ module DP16KD(
|
|||
input CSB2, CSB1, CSB0,
|
||||
output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0
|
||||
);
|
||||
parameter DATA_WIDTH_A = 18;
|
||||
parameter DATA_WIDTH_B = 18;
|
||||
parameter DATA_WIDTH_A = 18;
|
||||
parameter DATA_WIDTH_B = 18;
|
||||
|
||||
parameter REGMODE_A = "NOREG";
|
||||
parameter REGMODE_B = "NOREG";
|
||||
parameter REGMODE_A = "NOREG";
|
||||
parameter REGMODE_B = "NOREG";
|
||||
|
||||
parameter RESETMODE = "SYNC";
|
||||
parameter ASYNC_RESET_RELEASE = "SYNC";
|
||||
parameter RESETMODE = "SYNC";
|
||||
parameter ASYNC_RESET_RELEASE = "SYNC";
|
||||
|
||||
parameter CSDECODE_A = "0b000";
|
||||
parameter CSDECODE_B = "0b000";
|
||||
parameter CSDECODE_A = "0b000";
|
||||
parameter CSDECODE_B = "0b000";
|
||||
|
||||
parameter WRITEMODE_A = "NORMAL";
|
||||
parameter WRITEMODE_B = "NORMAL";
|
||||
parameter WRITEMODE_A = "NORMAL";
|
||||
parameter WRITEMODE_B = "NORMAL";
|
||||
|
||||
parameter CLKAMUX = "CLKA";
|
||||
parameter CLKBMUX = "CLKB";
|
||||
parameter DIA17MUX = "DIA17";
|
||||
parameter DIA16MUX = "DIA16";
|
||||
parameter DIA15MUX = "DIA15";
|
||||
parameter DIA14MUX = "DIA14";
|
||||
parameter DIA13MUX = "DIA13";
|
||||
parameter DIA12MUX = "DIA12";
|
||||
parameter DIA11MUX = "DIA11";
|
||||
parameter DIA10MUX = "DIA10";
|
||||
parameter DIA9MUX = "DIA9";
|
||||
parameter DIA8MUX = "DIA8";
|
||||
parameter DIA7MUX = "DIA7";
|
||||
parameter DIA6MUX = "DIA6";
|
||||
parameter DIA5MUX = "DIA5";
|
||||
parameter DIA4MUX = "DIA4";
|
||||
parameter DIA3MUX = "DIA3";
|
||||
parameter DIA2MUX = "DIA2";
|
||||
parameter DIA1MUX = "DIA1";
|
||||
parameter DIA0MUX = "DIA0";
|
||||
parameter ADA13MUX = "ADA13";
|
||||
parameter ADA12MUX = "ADA12";
|
||||
parameter ADA11MUX = "ADA11";
|
||||
parameter ADA10MUX = "ADA10";
|
||||
parameter ADA9MUX = "ADA9";
|
||||
parameter ADA8MUX = "ADA8";
|
||||
parameter ADA7MUX = "ADA7";
|
||||
parameter ADA6MUX = "ADA6";
|
||||
parameter ADA5MUX = "ADA5";
|
||||
parameter ADA4MUX = "ADA4";
|
||||
parameter ADA3MUX = "ADA3";
|
||||
parameter ADA2MUX = "ADA2";
|
||||
parameter ADA1MUX = "ADA1";
|
||||
parameter ADA0MUX = "ADA0";
|
||||
parameter CEAMUX = "CEA";
|
||||
parameter OCEAMUX = "OCEA";
|
||||
parameter CLKAMUX = "CLKA";
|
||||
parameter WEAMUX = "WEA";
|
||||
parameter RSTAMUX = "RSTA";
|
||||
parameter CSA2MUX = "CSA2";
|
||||
parameter CSA1MUX = "CSA1";
|
||||
parameter CSA0MUX = "CSA0";
|
||||
parameter DOA17MUX = "DOA17";
|
||||
parameter DOA16MUX = "DOA16";
|
||||
parameter DOA15MUX = "DOA15";
|
||||
parameter DOA14MUX = "DOA14";
|
||||
parameter DOA13MUX = "DOA13";
|
||||
parameter DOA12MUX = "DOA12";
|
||||
parameter DOA11MUX = "DOA11";
|
||||
parameter DOA10MUX = "DOA10";
|
||||
parameter DOA9MUX = "DOA9";
|
||||
parameter DOA8MUX = "DOA8";
|
||||
parameter DOA7MUX = "DOA7";
|
||||
parameter DOA6MUX = "DOA6";
|
||||
parameter DOA5MUX = "DOA5";
|
||||
parameter DOA4MUX = "DOA4";
|
||||
parameter DOA3MUX = "DOA3";
|
||||
parameter DOA2MUX = "DOA2";
|
||||
parameter DOA1MUX = "DOA1";
|
||||
parameter DOA0MUX = "DOA0";
|
||||
parameter DIB17MUX = "DIB17";
|
||||
parameter DIB16MUX = "DIB16";
|
||||
parameter DIB15MUX = "DIB15";
|
||||
parameter DIB14MUX = "DIB14";
|
||||
parameter DIB13MUX = "DIB13";
|
||||
parameter DIB12MUX = "DIB12";
|
||||
parameter DIB11MUX = "DIB11";
|
||||
parameter DIB10MUX = "DIB10";
|
||||
parameter DIB9MUX = "DIB9";
|
||||
parameter DIB8MUX = "DIB8";
|
||||
parameter DIB7MUX = "DIB7";
|
||||
parameter DIB6MUX = "DIB6";
|
||||
parameter DIB5MUX = "DIB5";
|
||||
parameter DIB4MUX = "DIB4";
|
||||
parameter DIB3MUX = "DIB3";
|
||||
parameter DIB2MUX = "DIB2";
|
||||
parameter DIB1MUX = "DIB1";
|
||||
parameter DIB0MUX = "DIB0";
|
||||
parameter ADB13MUX = "ADB13";
|
||||
parameter ADB12MUX = "ADB12";
|
||||
parameter ADB11MUX = "ADB11";
|
||||
parameter ADB10MUX = "ADB10";
|
||||
parameter ADB9MUX = "ADB9";
|
||||
parameter ADB8MUX = "ADB8";
|
||||
parameter ADB7MUX = "ADB7";
|
||||
parameter ADB6MUX = "ADB6";
|
||||
parameter ADB5MUX = "ADB5";
|
||||
parameter ADB4MUX = "ADB4";
|
||||
parameter ADB3MUX = "ADB3";
|
||||
parameter ADB2MUX = "ADB2";
|
||||
parameter ADB1MUX = "ADB1";
|
||||
parameter ADB0MUX = "ADB0";
|
||||
parameter CEBMUX = "CEB";
|
||||
parameter OCEBMUX = "OCEB";
|
||||
parameter CLKBMUX = "CLKB";
|
||||
parameter WEBMUX = "WEB";
|
||||
parameter RSTBMUX = "RSTB";
|
||||
parameter CSB2MUX = "CSB2";
|
||||
parameter CSB1MUX = "CSB1";
|
||||
parameter CSB0MUX = "CSB0";
|
||||
parameter DOB17MUX = "DOB17";
|
||||
parameter DOB16MUX = "DOB16";
|
||||
parameter DOB15MUX = "DOB15";
|
||||
parameter DOB14MUX = "DOB14";
|
||||
parameter DOB13MUX = "DOB13";
|
||||
parameter DOB12MUX = "DOB12";
|
||||
parameter DOB11MUX = "DOB11";
|
||||
parameter DOB10MUX = "DOB10";
|
||||
parameter DOB9MUX = "DOB9";
|
||||
parameter DOB8MUX = "DOB8";
|
||||
parameter DOB7MUX = "DOB7";
|
||||
parameter DOB6MUX = "DOB6";
|
||||
parameter DOB5MUX = "DOB5";
|
||||
parameter DOB4MUX = "DOB4";
|
||||
parameter DOB3MUX = "DOB3";
|
||||
parameter DOB2MUX = "DOB2";
|
||||
parameter DOB1MUX = "DOB1";
|
||||
parameter DOB0MUX = "DOB0";
|
||||
|
||||
parameter GSR = "ENABLED";
|
||||
parameter WID = 0;
|
||||
|
||||
parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter GSR = "ENABLED";
|
||||
|
||||
parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
endmodule
|
||||
|
||||
// TODO: Diamond flip-flops
|
||||
|
|
|
@ -50,7 +50,7 @@ struct DetermineInitPass : public Pass {
|
|||
|
||||
extra_args(args, args.size(), design);
|
||||
|
||||
size_t cnt = 0;
|
||||
int cnt = 0;
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
for (auto cell : module->selected_cells())
|
||||
|
@ -65,7 +65,7 @@ struct DetermineInitPass : public Pass {
|
|||
}
|
||||
}
|
||||
}
|
||||
log_header(design, "Updated %lu cells with determined init value.\n", cnt);
|
||||
log_header(design, "Updated %d cells with determined init value.\n", cnt);
|
||||
}
|
||||
} DetermineInitPass;
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ OBJS += techlibs/intel/synth_intel.o
|
|||
|
||||
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/m9k_bb.v))
|
||||
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/altpll_bb.v))
|
||||
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams.txt))
|
||||
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map.v))
|
||||
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k.txt))
|
||||
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v))
|
||||
$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/cells_sim.v))
|
||||
$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/cells_sim.v))
|
||||
$(eval $(call add_share_file,share/intel/cyclonev,techlibs/intel/cyclonev/cells_sim.v))
|
||||
|
|
|
@ -61,8 +61,8 @@ struct SynthIntelPass : public ScriptPass {
|
|||
log(" from label is synonymous to 'begin', and empty to label is\n");
|
||||
log(" synonymous to the end of the command list.\n");
|
||||
log("\n");
|
||||
log(" -noiopads\n");
|
||||
log(" do not use IO pad cells in output netlist\n");
|
||||
log(" -iopads\n");
|
||||
log(" use IO pad cells in output netlist\n");
|
||||
log("\n");
|
||||
log(" -nobram\n");
|
||||
log(" do not use block RAM cells in output netlist\n");
|
||||
|
@ -79,7 +79,7 @@ struct SynthIntelPass : public ScriptPass {
|
|||
}
|
||||
|
||||
string top_opt, family_opt, vout_file, blif_file;
|
||||
bool retime, flatten, nobram, noiopads;
|
||||
bool retime, flatten, nobram, iopads;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ struct SynthIntelPass : public ScriptPass {
|
|||
retime = false;
|
||||
flatten = true;
|
||||
nobram = false;
|
||||
noiopads = false;
|
||||
iopads = false;
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
@ -125,8 +125,8 @@ struct SynthIntelPass : public ScriptPass {
|
|||
run_to = args[argidx].substr(pos + 1);
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-noiopads") {
|
||||
noiopads = true;
|
||||
if (args[argidx] == "-iopads") {
|
||||
iopads = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nobram") {
|
||||
|
@ -187,8 +187,15 @@ struct SynthIntelPass : public ScriptPass {
|
|||
}
|
||||
|
||||
if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
|
||||
run("memory_bram -rules +/intel/common/brams.txt");
|
||||
run("techmap -map +/intel/common/brams_map.v");
|
||||
if (family_opt == "cycloneiv" ||
|
||||
family_opt == "cycloneive" ||
|
||||
family_opt == "max10" ||
|
||||
help_mode) {
|
||||
run("memory_bram -rules +/intel/common/brams_m9k.txt", "(if applicable for family)");
|
||||
run("techmap -map +/intel/common/brams_map_m9k.v", "(if applicable for family)");
|
||||
} else {
|
||||
log_warning("BRAM mapping is not currently supported for %s.\n", family_opt.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label("map_ffram")) {
|
||||
|
@ -215,10 +222,9 @@ struct SynthIntelPass : public ScriptPass {
|
|||
}
|
||||
|
||||
if (check_label("map_cells")) {
|
||||
if (!noiopads)
|
||||
run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(unless -noiopads)");
|
||||
if (iopads || help_mode)
|
||||
run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(if -iopads)");
|
||||
run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str()));
|
||||
|
||||
run("dffinit -highlow -ff dffeas q power_up");
|
||||
run("clean -purge");
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLA
|
|||
(* techmap_celltype = "$_DFF_PN0_" *)
|
||||
module _90_dff_pn0_to_pp0 (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
(* techmap_celltype = "$_DFF_NN1_" *)
|
||||
module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
(* techmap_celltype = "$_DFF_PN1_" *)
|
||||
module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
|
||||
module \$__SHREG_ (input C, input D, input E, output Q);
|
||||
parameter DEPTH = 0;
|
||||
|
|
|
@ -52,7 +52,7 @@ module \$__XILINX_RAMB8BWER_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DAT
|
|||
.CLKBRDCLK(CLK2 ^ !CLKPOL2),
|
||||
.ENBRDEN(A1EN),
|
||||
.REGCEBREGCE(|1),
|
||||
.RSTB(|0)
|
||||
.RSTBRST(|0)
|
||||
);
|
||||
endmodule
|
||||
|
||||
|
@ -217,7 +217,7 @@ module \$__XILINX_RAMB8BWER_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DAT
|
|||
.CLKBRDCLK(CLK3 ^ !CLKPOL3),
|
||||
.ENBRDEN(|1),
|
||||
.REGCEBREGCE(|0),
|
||||
.RSTB(|0),
|
||||
.RSTBRST(|0),
|
||||
.WEBWEU(B1EN_2)
|
||||
);
|
||||
end else begin
|
||||
|
@ -248,7 +248,7 @@ module \$__XILINX_RAMB8BWER_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DAT
|
|||
.CLKBRDCLK(CLK3 ^ !CLKPOL3),
|
||||
.ENBRDEN(|1),
|
||||
.REGCEBREGCE(|0),
|
||||
.RSTB(|0),
|
||||
.RSTBRST(|0),
|
||||
.WEBWEU(B1EN_2)
|
||||
);
|
||||
end endgenerate
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
# This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures.
|
||||
arraycells.v inst id[0] of
|
||||
defvalue.sv Initial value not supported
|
||||
dff_different_styles.v
|
||||
dff_init.v Initial value not supported
|
||||
generate.v combinational loop
|
||||
hierdefparam.v inst id[0] of
|
||||
i2c_master_tests.v $adff
|
||||
implicit_ports.v not fully initialized
|
||||
macros.v drops modules
|
||||
mem2reg.v drops modules
|
||||
mem_arst.v $adff
|
||||
|
@ -12,7 +14,6 @@ memory.v $adff
|
|||
multiplier.v inst id[0] of
|
||||
muxtree.v drops modules
|
||||
omsp_dbg_uart.v $adff
|
||||
operators.v $pow
|
||||
partsel.v drops modules
|
||||
process.v drops modules
|
||||
realexpr.v drops modules
|
||||
|
@ -23,5 +24,6 @@ specify.v no code (empty module generates error
|
|||
subbytes.v $adff
|
||||
task_func.v drops modules
|
||||
values.v combinational loop
|
||||
wandwor.v Invalid connect to an expression that is not a reference or a WritePort.
|
||||
vloghammer.v combinational loop
|
||||
wreduce.v original verilog issues ( -x where x isn't declared signed)
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
/*.log
|
||||
/*.out
|
||||
/write_gzip.v
|
||||
/write_gzip.v.gz
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
read_verilog gzip_verilog.v.gz
|
||||
select -assert-any top
|
|
@ -0,0 +1,148 @@
|
|||
|
||||
read_verilog <<EOT
|
||||
module opt_expr_add_test(input [3:0] i, input [7:0] j, output [8:0] o);
|
||||
assign o = (i << 4) + j;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
proc
|
||||
design -save gold
|
||||
|
||||
opt_expr -fine
|
||||
wreduce
|
||||
|
||||
select -assert-count 1 t:$add r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
|
||||
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
##########
|
||||
|
||||
read_verilog <<EOT
|
||||
module opt_expr_add_signed_test(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
|
||||
assign o = (i << 4) + j;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
proc
|
||||
design -save gold
|
||||
|
||||
opt_expr -fine
|
||||
wreduce
|
||||
|
||||
select -assert-count 1 t:$add r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
|
||||
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
##########
|
||||
|
||||
read_verilog <<EOT
|
||||
module opt_expr_sub_test1(input [3:0] i, input [7:0] j, output [8:0] o);
|
||||
assign o = j - (i << 4);
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
proc
|
||||
design -save gold
|
||||
|
||||
opt_expr -fine
|
||||
wreduce
|
||||
|
||||
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
|
||||
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
##########
|
||||
|
||||
read_verilog <<EOT
|
||||
module opt_expr_sub_signed_test1(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
|
||||
assign o = j - (i << 4);
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
proc
|
||||
design -save gold
|
||||
|
||||
opt_expr -fine
|
||||
wreduce
|
||||
|
||||
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
|
||||
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
##########
|
||||
|
||||
read_verilog <<EOT
|
||||
module opt_expr_sub_test2(input [3:0] i, input [7:0] j, output [8:0] o);
|
||||
assign o = (i << 4) - j;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
proc
|
||||
design -save gold
|
||||
|
||||
opt_expr -fine
|
||||
wreduce
|
||||
|
||||
select -assert-count 1 t:$sub r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
|
||||
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
##########
|
||||
|
||||
read_verilog <<EOT
|
||||
module opt_expr_sub_test4(input [3:0] i, output [8:0] o);
|
||||
assign o = 5'b00010 - i;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
proc
|
||||
design -save gold
|
||||
|
||||
opt_expr -fine
|
||||
wreduce
|
||||
|
||||
select -assert-count 1 t:$sub r:A_WIDTH=2 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
|
||||
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
|
@ -0,0 +1,48 @@
|
|||
read_verilog <<EOT
|
||||
module wreduce_sub_test(input [3:0] i, input [7:0] j, output [8:0] o);
|
||||
assign o = (j >> 4) - i;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
proc
|
||||
design -save gold
|
||||
|
||||
opt_expr
|
||||
wreduce
|
||||
|
||||
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
|
||||
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
##########
|
||||
|
||||
read_verilog <<EOT
|
||||
module wreduce_sub_signed_test(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
|
||||
assign o = (j >>> 4) - i;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
proc
|
||||
design -save gold
|
||||
|
||||
opt_expr
|
||||
wreduce
|
||||
|
||||
dump
|
||||
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
|
||||
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
|
@ -0,0 +1,16 @@
|
|||
read -vlog2k <<EOT
|
||||
module top(input a, output y);
|
||||
assign y = !a;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
prep -top top
|
||||
write_verilog write_gzip.v.gz
|
||||
design -reset
|
||||
|
||||
! rm -f write_gzip.v
|
||||
! gunzip write_gzip.v.gz
|
||||
read -vlog2k write_gzip.v
|
||||
! rm -f write_gzip.v
|
||||
hierarchy -top top
|
||||
select -assert-any top
|
Loading…
Reference in New Issue