Merge remote-tracking branch 'origin/master' into eddie/wreduce_add

This commit is contained in:
Eddie Hung 2019-08-06 14:50:00 -07:00
commit 26cb3e7afc
56 changed files with 763 additions and 172 deletions

View File

@ -36,6 +36,7 @@ matrix:
- libboost-system-dev - libboost-system-dev
- libboost-python-dev - libboost-python-dev
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev
env: env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8" - MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8"
@ -64,6 +65,7 @@ matrix:
- libboost-system-dev - libboost-system-dev
- libboost-python-dev - libboost-python-dev
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev
env: env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-6 && CXX=g++-6" - MATRIX_EVAL="CONFIG=gcc && CC=gcc-6 && CXX=g++-6"
@ -92,6 +94,7 @@ matrix:
- libboost-system-dev - libboost-system-dev
- libboost-python-dev - libboost-python-dev
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev
env: env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7" - MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7"
@ -121,6 +124,7 @@ matrix:
- libboost-system-dev - libboost-system-dev
- libboost-python-dev - libboost-python-dev
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev
env: env:
- MATRIX_EVAL="CONFIG=clang && CC=clang-3.8 && CXX=clang++-3.8" - MATRIX_EVAL="CONFIG=clang && CC=clang-3.8 && CXX=clang++-3.8"
@ -149,6 +153,7 @@ matrix:
- libboost-system-dev - libboost-system-dev
- libboost-python-dev - libboost-python-dev
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev
env: env:
- MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0" - MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"

View File

@ -14,7 +14,9 @@ Yosys 0.9 .. Yosys 0.9-dev
- Added "synth -abc9" (experimental) - Added "synth -abc9" (experimental)
- Added "script -scriptwire - Added "script -scriptwire
- "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable) - "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
Yosys 0.8 .. Yosys 0.8-dev Yosys 0.8 .. Yosys 0.8-dev
-------------------------- --------------------------

View File

@ -19,6 +19,7 @@ ENABLE_VERIFIC := 0
ENABLE_COVER := 1 ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0 ENABLE_LIBYOSYS := 0
ENABLE_PROTOBUF := 0 ENABLE_PROTOBUF := 0
ENABLE_ZLIB := 1
# python wrappers # python wrappers
ENABLE_PYOSYS := 0 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' # 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 # will remove the 'abc' directory and you do not want to accidentally
# delete your work on ABC.. # delete your work on ABC..
ABCREV = 62487de ABCREV = 5776ad0
ABCPULL = 1 ABCPULL = 1
ABCURL ?= https://github.com/berkeley-abc/abc ABCURL ?= https://github.com/berkeley-abc/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
@ -260,7 +261,8 @@ CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS)) LDLIBS := $(filter-out -lrt,$(LDLIBS))
ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w" 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 EXE = .exe
else ifeq ($(CONFIG),msys2) else ifeq ($(CONFIG),msys2)
@ -384,6 +386,12 @@ ifeq ($(ENABLE_GLOB),1)
CXXFLAGS += -DYOSYS_ENABLE_GLOB CXXFLAGS += -DYOSYS_ENABLE_GLOB
endif endif
ifeq ($(ENABLE_ZLIB),1)
CXXFLAGS += -DYOSYS_ENABLE_ZLIB
LDLIBS += -lz
endif
ifeq ($(ENABLE_TCL),1) ifeq ($(ENABLE_TCL),1)
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')") TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
ifeq ($(OS), FreeBSD) ifeq ($(OS), FreeBSD)
@ -394,7 +402,7 @@ endif
ifeq ($(CONFIG),mxe) ifeq ($(CONFIG),mxe)
CXXFLAGS += -DYOSYS_ENABLE_TCL CXXFLAGS += -DYOSYS_ENABLE_TCL
LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz -luserenv
else else
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
ifeq ($(OS), FreeBSD) ifeq ($(OS), FreeBSD)
@ -862,9 +870,11 @@ config-mxe: clean
config-msys2: clean config-msys2: clean
echo 'CONFIG := msys2' > Makefile.conf echo 'CONFIG := msys2' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-msys2-64: clean config-msys2-64: clean
echo 'CONFIG := msys2-64' > Makefile.conf echo 'CONFIG := msys2-64' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-cygwin: clean config-cygwin: clean
echo 'CONFIG := cygwin' > Makefile.conf echo 'CONFIG := cygwin' > Makefile.conf

View File

@ -67,13 +67,13 @@ prerequisites for building yosys:
$ sudo apt-get install build-essential clang bison flex \ $ sudo apt-get install build-essential clang bison flex \
libreadline-dev gawk tcl-dev libffi-dev git \ libreadline-dev gawk tcl-dev libffi-dev git \
graphviz xdot pkg-config python3 libboost-system-dev \ 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: Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies:
$ brew tap Homebrew/bundle && brew bundle $ brew tap Homebrew/bundle && brew bundle
$ sudo port install bison flex readline gawk libffi \ $ 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: 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: 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 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 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 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: writing the design to the console in Yosys's internal format:
yosys> write_ilang yosys> write_ilang
elaborate design hierarchy:
yosys> hierarchy
convert processes (``always`` blocks) to netlist elements and perform convert processes (``always`` blocks) to netlist elements and perform
some simple optimizations: some simple optimizations:
@ -163,51 +160,26 @@ write design netlist to a new Verilog file:
yosys> write_verilog synth.v 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: or using a simple synthesis script:
$ cat synth.ys $ cat synth.ys
read_verilog tests/simple/fiedler-cooley.v read -sv tests/simple/fiedler-cooley.v
hierarchy; proc; opt; techmap; opt hierarchy -top up3down5
proc; opt; techmap; opt
write_verilog synth.v write_verilog synth.v
$ ./yosys synth.ys $ ./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 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 in the liberty file ``mycells.lib``, the following synthesis script will
synthesize for the given cell library: synthesize for the given cell library:
# read design
read -sv tests/simple/fiedler-cooley.v
hierarchy -top up3down5
# the high-level stuff # the high-level stuff
hierarchy; proc; fsm; opt; memory; opt proc; fsm; opt; memory; opt
# mapping to internal cell library # mapping to internal cell library
techmap; opt techmap; opt
@ -222,7 +194,8 @@ synthesize for the given cell library:
clean clean
If you do not have a liberty file but want to test this synthesis script, 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 Liberty file downloads for and information about free and open ASIC standard
cell libraries can be found here: cell libraries can be found here:
@ -231,20 +204,18 @@ cell libraries can be found here:
- http://www.vlsitechnology.org/synopsys/vsclib013.lib - http://www.vlsitechnology.org/synopsys/vsclib013.lib
The command ``synth`` provides a good default synthesis script (see The command ``synth`` provides a good default synthesis script (see
``help synth``). If possible a synthesis script should borrow from ``synth``. ``help synth``):
For example:
# the high-level stuff read -sv tests/simple/fiedler-cooley.v
hierarchy synth -top up3down5
synth -run coarse
# mapping to internal cells # mapping to target cells
techmap; opt -fast
dfflibmap -liberty mycells.lib dfflibmap -liberty mycells.lib
abc -liberty mycells.lib abc -liberty mycells.lib
clean 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 Unsupported Verilog-2005 Features

View File

@ -53,7 +53,7 @@ PRIVATE_NAMESPACE_BEGIN
inline int32_t to_big_endian(int32_t i32) { inline int32_t to_big_endian(int32_t i32) {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return __builtin_bswap32(i32); return bswap32(i32);
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
return i32; return i32;
#else #else
@ -610,15 +610,15 @@ struct XAigerWriter
std::stringstream h_buffer; std::stringstream h_buffer;
auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1);
write_h_buffer(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()); 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()); 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()); 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()); 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()); write_h_buffer(box_list.size());
RTLIL::Module *holes_module = nullptr; RTLIL::Module *holes_module = nullptr;
@ -772,7 +772,7 @@ struct XAigerWriter
if (output_bits.count(b)) { if (output_bits.count(b)) {
int o = ordered_outputs.at(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; continue;
} }

View File

@ -327,6 +327,13 @@ struct BlifDumper
goto internal_cell; 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_") { if (!config->icells_mode && cell->type == "$_FF_") {
f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr_init(cell->getPort("\\Q"))); cstr_init(cell->getPort("\\Q")));

View File

@ -496,7 +496,7 @@ struct BtorWorker
goto okay; goto okay;
} }
if (cell->type.in("$mux", "$_MUX_")) if (cell->type.in("$mux", "$_MUX_", "$_NMUX_"))
{ {
SigSpec sig_a = sigmap(cell->getPort("\\A")); SigSpec sig_a = sigmap(cell->getPort("\\A"));
SigSpec sig_b = sigmap(cell->getPort("\\B")); SigSpec sig_b = sigmap(cell->getPort("\\B"));
@ -511,6 +511,12 @@ struct BtorWorker
int nid = next_nid++; int nid = next_nid++;
btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a); 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); add_nid_sig(nid, sig_y);
goto okay; goto okay;
} }

View File

@ -472,7 +472,7 @@ struct SimplecWorker
return; return;
} }
if (cell->type == "$_MUX_") if (cell->type.in("$_MUX_", "$_NMUX_"))
{ {
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); 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"; 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) // 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); log_assert(y.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +

View File

@ -510,6 +510,7 @@ struct Smt2Worker
if (cell->type == "$_ANDNOT_") return export_gate(cell, "(and A (not B))"); 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 == "$_ORNOT_") return export_gate(cell, "(or A (not B))");
if (cell->type == "$_MUX_") return export_gate(cell, "(ite S B A)"); 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 == "$_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 == "$_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)))"); if (cell->type == "$_AOI4_") return export_gate(cell, "(not (or (and A B) (and C D)))");

View File

@ -537,6 +537,13 @@ struct SmvWorker
continue; 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_") if (cell->type == "$_AOI3_")
{ {
definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")),

View File

@ -558,6 +558,20 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true; 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_")) { if (cell->type.in("$_AOI3_", "$_OAI3_")) {
f << stringf("%s" "assign ", indent.c_str()); f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, cell->getPort("\\Y")); dump_sigspec(f, cell->getPort("\\Y"));

8
examples/mimas2/README Normal file
View File

@ -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

View File

@ -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 ;

14
examples/mimas2/example.v Normal file
View File

@ -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

8
examples/mimas2/run.sh Normal file
View File

@ -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

View File

@ -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

View File

@ -301,7 +301,11 @@ static uint32_t parse_xaiger_literal(std::istream &f)
uint32_t l; uint32_t l;
f.read(reinterpret_cast<char*>(&l), sizeof(l)); f.read(reinterpret_cast<char*>(&l), sizeof(l));
if (f.gcount() != 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())); log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast<int64_t>(f.tellg()));
#endif
return from_big_endian(l); return from_big_endian(l);
} }

View File

@ -1551,7 +1551,9 @@ RTLIL::Module *AstModule::clone() const
new_mod->nomeminit = nomeminit; new_mod->nomeminit = nomeminit;
new_mod->nomem2reg = nomem2reg; new_mod->nomem2reg = nomem2reg;
new_mod->mem2reg = mem2reg; new_mod->mem2reg = mem2reg;
new_mod->noblackbox = noblackbox;
new_mod->lib = lib; new_mod->lib = lib;
new_mod->nowb = nowb;
new_mod->noopt = noopt; new_mod->noopt = noopt;
new_mod->icells = icells; new_mod->icells = icells;
new_mod->pwires = pwires; new_mod->pwires = pwires;

View File

@ -2484,7 +2484,7 @@ struct ReadPass : public Pass {
args[0] = "verific"; args[0] = "verific";
} else { } else {
args[0] = "read_verilog"; args[0] = "read_verilog";
args.erase(args.begin()+1, args.begin()+2); args[1] = "-defer";
} }
Pass::call(design, args); Pass::call(design, args);
return; return;
@ -2498,6 +2498,7 @@ struct ReadPass : public Pass {
if (args[1] == "-formal") if (args[1] == "-formal")
args.insert(args.begin()+1, std::string()); args.insert(args.begin()+1, std::string());
args[1] = "-sv"; args[1] = "-sv";
args.insert(args.begin()+1, "-defer");
} }
Pass::call(design, args); Pass::call(design, args);
return; return;

View File

@ -70,6 +70,9 @@ YOSYS_NAMESPACE_END
#define YY_INPUT(buf,result,max_size) \ #define YY_INPUT(buf,result,max_size) \
result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size) result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
#undef YY_BUF_SIZE
#define YY_BUF_SIZE 65536
%} %}
%option yylineno %option yylineno

View File

@ -325,6 +325,8 @@ Aig::Aig(Cell *cell)
int A = mk.inport("\\A", i); int A = mk.inport("\\A", i);
int B = mk.inport("\\B", i); int B = mk.inport("\\B", i);
int Y = mk.mux_gate(A, B, S); int Y = mk.mux_gate(A, B, S);
if (cell->type == "$_NMUX_")
Y = mk.not_gate(Y);
mk.outport(Y, "\\Y", i); mk.outport(Y, "\\Y", i);
} }
goto optimize; goto optimize;

View File

@ -193,6 +193,7 @@ struct CellTypes
setup_type("$_ANDNOT_", {A, B}, {Y}, true); setup_type("$_ANDNOT_", {A, B}, {Y}, true);
setup_type("$_ORNOT_", {A, B}, {Y}, true); setup_type("$_ORNOT_", {A, B}, {Y}, true);
setup_type("$_MUX_", {A, B, S}, {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("$_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("$_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); 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);

View File

@ -145,7 +145,7 @@ struct ConstEval
if (cell->hasPort("\\B")) if (cell->hasPort("\\B"))
sig_b = cell->getPort("\\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; std::vector<RTLIL::SigSpec> y_candidates;
int count_maybe_set_s_bits = 0; int count_maybe_set_s_bits = 0;
@ -175,7 +175,10 @@ struct ConstEval
for (auto &yc : y_candidates) { for (auto &yc : y_candidates) {
if (!eval(yc, undef, cell)) if (!eval(yc, undef, cell))
return false; 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) if (y_values.size() > 1)

View File

@ -24,10 +24,10 @@
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr); int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false);
inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const> &parameters = dict<RTLIL::IdString, RTLIL::Const>(), inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const> &parameters = dict<RTLIL::IdString, RTLIL::Const>(),
RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr) RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false)
{ {
static dict<RTLIL::IdString, int> gate_cost = { static dict<RTLIL::IdString, int> gate_cost = {
{ "$_BUF_", 1 }, { "$_BUF_", 1 },
@ -44,9 +44,33 @@ inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL
{ "$_OAI3_", 6 }, { "$_OAI3_", 6 },
{ "$_AOI4_", 8 }, { "$_AOI4_", 8 },
{ "$_OAI4_", 8 }, { "$_OAI4_", 8 },
{ "$_MUX_", 4 } { "$_MUX_", 4 },
{ "$_NMUX_", 4 }
}; };
// match costs in "stat -tech cmos"
static dict<RTLIL::IdString, int> cmos_gate_cost = {
{ "$_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 }
};
if (cmos_cost && cmos_gate_cost.count(type))
return cmos_gate_cost.at(type);
if (gate_cost.count(type)) if (gate_cost.count(type))
return gate_cost.at(type); return gate_cost.at(type);
@ -76,9 +100,9 @@ inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL
return 1; return 1;
} }
inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache) inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache, bool cmos_cost)
{ {
return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache); return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache, cmos_cost);
} }
YOSYS_NAMESPACE_END YOSYS_NAMESPACE_END

View File

@ -25,6 +25,65 @@
#include <stdio.h> #include <stdio.h>
#include <errno.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 YOSYS_NAMESPACE_BEGIN
#define MAX_REG_COUNT 1000 #define MAX_REG_COUNT 1000
@ -436,6 +495,28 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
delete ff; delete ff;
else else
f = ff; 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) if (f == NULL)
log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno)); log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
@ -546,14 +627,28 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
filename = arg; filename = arg;
rewrite_filename(filename); rewrite_filename(filename);
std::ofstream *ff = new std::ofstream; if (filename.size() > 3 && filename.substr(filename.size()-3) == ".gz") {
ff->open(filename.c_str(), std::ofstream::trunc); #ifdef YOSYS_ENABLE_ZLIB
yosys_output_files.insert(filename); gzip_ostream *gf = new gzip_ostream;
if (ff->fail()) { if (!gf->open(filename)) {
delete ff; delete gf;
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno)); 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) if (called_with_fp)

View File

@ -1249,6 +1249,7 @@ namespace {
if (cell->type == "$_ANDNOT_") { check_gate("ABY"); return; } if (cell->type == "$_ANDNOT_") { check_gate("ABY"); return; }
if (cell->type == "$_ORNOT_") { check_gate("ABY"); return; } if (cell->type == "$_ORNOT_") { check_gate("ABY"); return; }
if (cell->type == "$_MUX_") { check_gate("ABSY"); 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 == "$_AOI3_") { check_gate("ABCY"); return; }
if (cell->type == "$_OAI3_") { check_gate("ABCY"); return; } if (cell->type == "$_OAI3_") { check_gate("ABCY"); return; }
if (cell->type == "$_AOI4_") { check_gate("ABCDY"); 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(AndnotGate, "$_ANDNOT_", A, B, Y)
DEF_METHOD_3(OrnotGate, "$_ORNOT_", A, B, Y) DEF_METHOD_3(OrnotGate, "$_ORNOT_", A, B, Y)
DEF_METHOD_4(MuxGate, "$_MUX_", A, B, S, 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(Aoi3Gate, "$_AOI3_", A, B, C, Y)
DEF_METHOD_4(Oai3Gate, "$_OAI3_", A, B, C, Y) DEF_METHOD_4(Oai3Gate, "$_OAI3_", A, B, C, Y)
DEF_METHOD_5(Aoi4Gate, "$_AOI4_", A, B, C, D, Y) DEF_METHOD_5(Aoi4Gate, "$_AOI4_", A, B, C, D, Y)

View File

@ -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. // It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
template<typename T> 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; typename dict<RTLIL::IdString, T>::iterator it;
dict<RTLIL::IdString, T> *list_p; dict<RTLIL::IdString, T> *list_p;
int *refcount_p; int *refcount_p;
@ -474,13 +478,25 @@ namespace RTLIL
return it != other.it; 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); log_assert(list_p != nullptr);
if (++it == list_p->end()) { if (++it == list_p->end()) {
(*refcount_p)--; (*refcount_p)--;
list_p = nullptr; list_p = nullptr;
refcount_p = nullptr; refcount_p = nullptr;
} }
return *this;
}
inline const ObjIterator<T> operator++(int) {
ObjIterator<T> result(*this);
++(*this);
return result;
} }
}; };
@ -1139,6 +1155,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* 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* 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* 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* 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* 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 = ""); 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 = "");
@ -1214,6 +1231,7 @@ public:
RTLIL::SigBit AndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); 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 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 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 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 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 = ""); 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 = "");

View File

@ -475,7 +475,7 @@ struct SatGen
return true; 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> a = importDefSigSpec(cell->getPort("\\A"), timestep);
std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), 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> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y; 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) if (model_undef)
{ {

View File

@ -894,23 +894,26 @@ void run_frontend(std::string filename, std::string command, std::string *backen
design = yosys_design; design = yosys_design;
if (command == "auto") { 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"; 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"; 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"; 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"; 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"; 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"; 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"; 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"; 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"; command = "tcl";
else if (filename == "-") else if (filename == "-")
command = "script"; command = "script";

View File

@ -52,6 +52,7 @@
#include <stdexcept> #include <stdexcept>
#include <memory> #include <memory>
#include <cmath> #include <cmath>
#include <cstddef>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
@ -87,6 +88,10 @@ extern int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName);
extern void Tcl_Finalize(void); extern void Tcl_Finalize(void);
extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr); extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr);
extern const char *Tcl_GetStringResult(Tcl_Interp *interp); 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
#endif #endif

View File

@ -494,6 +494,6 @@ Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLA
\end{fixme} \end{fixme}
\begin{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} \end{fixme}

View File

@ -61,6 +61,7 @@ SOFTWARE. */
#include <windows.h> #include <windows.h>
#include <tchar.h> #include <tchar.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h>
int child_pid=0; int child_pid=0;
@ -338,7 +339,7 @@ int run(int argc, char **argv, int is_gui) {
if (is_gui) { if (is_gui) {
/* Use exec, we don't need to wait for the GUI to finish */ /* 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! */ return fail("Could not exec %s", ptr); /* shouldn't get here! */
} }

View File

@ -223,6 +223,37 @@ struct statdata_t
log("\n"); log("\n");
log(" Estimated number of LCs: %10d\n", lc_cnt); log(" Estimated number of LCs: %10d\n", lc_cnt);
} }
if (tech == "cmos")
{
int tran_cnt = 0;
bool tran_cnt_exact = true;
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;
else if (ctype.in("$_NMUX_"))
tran_cnt += 10*cnum;
else if (ctype.in("$_MUX_", "$_XOR_", "$_XNOR_"))
tran_cnt += 12*cnum;
else if (ctype.in("$_DFF_P_", "$_DFF_N_"))
tran_cnt += 16*cnum;
else
tran_cnt_exact = false;
}
log("\n");
log(" Estimated number of transistors: %10d%s\n", tran_cnt, tran_cnt_exact ? "" : "+");
}
} }
}; };
@ -286,7 +317,7 @@ struct StatPass : public Pass {
log("\n"); log("\n");
log(" -tech <technology>\n"); log(" -tech <technology>\n");
log(" print area estemate for the specified technology. Currently supported\n"); log(" print area estemate for the specified technology. Currently supported\n");
log(" values for <technology>: xilinx\n"); log(" values for <technology>: xilinx, cmos\n");
log("\n"); log("\n");
log(" -width\n"); log(" -width\n");
log(" annotate internal cell types with their word width.\n"); log(" annotate internal cell types with their word width.\n");
@ -330,7 +361,7 @@ struct StatPass : public Pass {
} }
extra_args(args, argidx, design); extra_args(args, argidx, design);
if (techname != "" && techname != "xilinx") if (techname != "" && techname != "xilinx" && techname != "cmos")
log_cmd_error("Unsupported technology: '%s'\n", techname.c_str()); log_cmd_error("Unsupported technology: '%s'\n", techname.c_str());
for (auto mod : design->selected_modules()) for (auto mod : design->selected_modules())

View File

@ -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++) for (int arity = 1; arity <= max_arity; arity++)
{ {
if (arity_counts[arity]) if (arity_counts[arity])
@ -351,14 +351,14 @@ struct OptLutWorker
int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size();
if (lutA_dlogic_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 else
log_debug(" Cell A is a %d-LUT. ", lutA_arity); log_debug(" Cell A is a %d-LUT. ", lutA_arity);
if (lutB_dlogic_inputs.size()) 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 else
log_debug("Cell B is a %d-LUT.\n", lutB_arity); 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; const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B;
int combine_mask = 0; int combine_mask = 0;

View File

@ -171,7 +171,7 @@ struct RmportsPassPass : public Pass {
wire->port_output = false; wire->port_output = false;
wire->port_id = 0; 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 // Re-number all of the wires that DO have ports still on them
for(size_t i=0; i<module->ports.size(); i++) for(size_t i=0; i<module->ports.size(); i++)

View File

@ -82,14 +82,23 @@ struct PruneWorker
if (root) { if (root) {
bool promotable = true; bool promotable = true;
for (auto &bit : lhs) { for (auto &bit : lhs) {
if (bit.wire && affected[bit]) { if (bit.wire && affected[bit] && !assigned[bit]) {
promotable = false; promotable = false;
break; break;
} }
} }
if (promotable) { 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++; promoted_count++;
module->connect(*it); module->connect(conn);
remove.insert(*it); remove.insert(*it);
} }
} }

View File

@ -49,6 +49,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <cctype>
#include <cerrno> #include <cerrno>
#include <sstream> #include <sstream>
#include <climits> #include <climits>
@ -81,6 +82,7 @@ enum class gate_type_t {
G_ANDNOT, G_ANDNOT,
G_ORNOT, G_ORNOT,
G_MUX, G_MUX,
G_NMUX,
G_AOI3, G_AOI3,
G_OAI3, G_OAI3,
G_AOI4, G_AOI4,
@ -111,7 +113,7 @@ std::vector<gate_t> signal_list;
std::map<RTLIL::SigBit, int> signal_map; std::map<RTLIL::SigBit, int> signal_map;
std::map<RTLIL::SigBit, RTLIL::State> signal_init; std::map<RTLIL::SigBit, RTLIL::State> signal_init;
pool<std::string> enabled_gates; pool<std::string> enabled_gates;
bool recover_init; bool recover_init, cmos_cost;
bool clk_polarity, en_polarity; bool clk_polarity, en_polarity;
RTLIL::SigSpec clk_sig, en_sig; RTLIL::SigSpec clk_sig, en_sig;
@ -257,7 +259,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
return; return;
} }
if (cell->type == "$_MUX_") if (cell->type.in("$_MUX_", "$_NMUX_"))
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_b = cell->getPort("\\B"); 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_b = map_signal(sig_b);
int mapped_s = map_signal(sig_s); 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); module->remove(cell);
return; 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, ".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, "1-0 1\n");
fprintf(f, "-11 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)) { } 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, ".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"); fprintf(f, "-00 1\n");
@ -925,46 +931,52 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
{ {
log_header(design, "Executing ABC.\n"); log_header(design, "Executing ABC.\n");
auto cell_cost = [](IdString cell_type) {
return get_cell_cost(cell_type, dict<RTLIL::IdString, RTLIL::Const>(), nullptr, nullptr, cmos_cost);
};
buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
f = fopen(buffer.c_str(), "wt"); f = fopen(buffer.c_str(), "wt");
if (f == NULL) if (f == NULL)
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); 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 ZERO 1 Y=CONST0;\n");
fprintf(f, "GATE ONE 1 Y=CONST1;\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 BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", 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 NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost("$_NOT_"));
if (enabled_gates.empty() || enabled_gates.count("AND")) 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("$_AND_"));
if (enabled_gates.empty() || enabled_gates.count("NAND")) 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("$_NAND_"));
if (enabled_gates.empty() || enabled_gates.count("OR")) 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("$_OR_"));
if (enabled_gates.empty() || enabled_gates.count("NOR")) 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("$_NOR_"));
if (enabled_gates.empty() || enabled_gates.count("XOR")) 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("$_XOR_"));
if (enabled_gates.empty() || enabled_gates.count("XNOR")) 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("$_XNOR_"));
if (enabled_gates.empty() || enabled_gates.count("ANDNOT")) 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("$_ANDNOT_"));
if (enabled_gates.empty() || enabled_gates.count("ORNOT")) 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("$_ORNOT_"));
if (enabled_gates.empty() || enabled_gates.count("AOI3")) 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("$_AOI3_"));
if (enabled_gates.empty() || enabled_gates.count("OAI3")) 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("$_OAI3_"));
if (enabled_gates.empty() || enabled_gates.count("AOI4")) 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("$_AOI4_"));
if (enabled_gates.empty() || enabled_gates.count("OAI4")) 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("$_OAI4_"));
if (enabled_gates.empty() || enabled_gates.count("MUX")) 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("$_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("$_NMUX_"));
if (map_mux4) 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("$_MUX_"));
if (map_mux8) 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("$_MUX_"));
if (map_mux16) 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("$_MUX_"));
fclose(f); fclose(f);
if (!lut_costs.empty()) { if (!lut_costs.empty()) {
@ -1065,8 +1077,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
design->select(module, cell); design->select(module, cell);
continue; continue;
} }
if (c->type == "\\MUX") { if (c->type == "\\MUX" || c->type == "\\NMUX") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_"); RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); 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)])); cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
@ -1406,11 +1418,12 @@ struct AbcPass : public Pass {
log("\n"); log("\n");
log(" The following aliases can be used to reference common sets of gate types:\n"); log(" The following aliases can be used to reference common sets of gate types:\n");
log(" simple: AND OR XOR MUX\n"); log(" simple: AND OR XOR MUX\n");
log(" cmos2: NAND NOR\n"); log(" cmos2: NAND NOR\n");
log(" cmos3: NAND NOR AOI3 OAI3\n"); log(" cmos3: NAND NOR AOI3 OAI3\n");
log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n"); log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n");
log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n"); log(" cmos: NAND NOR AOI3 OAI3 AOI4 OAI4 NMUX MUX XOR XNOR\n");
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n"); log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n");
log("\n"); log("\n");
log(" Prefix a gate type with a '-' to remove it from the list. For example\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"); log(" the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent.\n");
@ -1488,6 +1501,7 @@ struct AbcPass : public Pass {
map_mux8 = false; map_mux8 = false;
map_mux16 = false; map_mux16 = false;
enabled_gates.clear(); enabled_gates.clear();
cmos_cost = false;
#ifdef _WIN32 #ifdef _WIN32
#ifndef ABCEXTERNAL #ifndef ABCEXTERNAL
@ -1628,11 +1642,15 @@ struct AbcPass : public Pass {
goto ok_alias; goto ok_alias;
} }
if (g == "cmos2") { if (g == "cmos2") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND"); gate_list.push_back("NAND");
gate_list.push_back("NOR"); gate_list.push_back("NOR");
goto ok_alias; goto ok_alias;
} }
if (g == "cmos3") { if (g == "cmos3") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND"); gate_list.push_back("NAND");
gate_list.push_back("NOR"); gate_list.push_back("NOR");
gate_list.push_back("AOI3"); gate_list.push_back("AOI3");
@ -1640,6 +1658,8 @@ struct AbcPass : public Pass {
goto ok_alias; goto ok_alias;
} }
if (g == "cmos4") { if (g == "cmos4") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND"); gate_list.push_back("NAND");
gate_list.push_back("NOR"); gate_list.push_back("NOR");
gate_list.push_back("AOI3"); gate_list.push_back("AOI3");
@ -1648,6 +1668,21 @@ struct AbcPass : public Pass {
gate_list.push_back("OAI4"); gate_list.push_back("OAI4");
goto ok_alias; 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") { if (g == "gates") {
gate_list.push_back("AND"); gate_list.push_back("AND");
gate_list.push_back("NAND"); gate_list.push_back("NAND");

View File

@ -86,7 +86,7 @@ struct ExtractFaWorker
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type.in( "$_BUF_", "$_NOT_", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", 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_")) "$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_"))
{ {
SigBit y = sigmap(SigBit(cell->getPort("\\Y"))); SigBit y = sigmap(SigBit(cell->getPort("\\Y")));

View File

@ -783,7 +783,7 @@ struct FlowmapWorker
int depth = 0; int depth = 0;
for (auto label : labels) for (auto label : labels)
depth = max(depth, label.second); 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) 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) 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) for (auto node : lut_nodes)
{ {
@ -1215,7 +1215,7 @@ struct FlowmapWorker
if (potentials.empty()) 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) if (!first && break_num == 1)
{ {
log(" Design fully relaxed.\n"); log(" Design fully relaxed.\n");
@ -1419,9 +1419,9 @@ struct FlowmapWorker
lut_area += lut_table.size(); lut_area += lut_table.size();
if ((int)input_nodes.size() >= minlut) 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 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) for (auto node : mapped_nodes)

View File

@ -50,7 +50,7 @@ struct AnlogicDetermineInitPass : public Pass {
extra_args(args, args.size(), design); extra_args(args, args.size(), design);
size_t cnt = 0; int cnt = 0;
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
{ {
for (auto cell : module->selected_cells()) 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; } AnlogicDetermineInitPass;

View File

@ -69,7 +69,7 @@ struct AnlogicEqnPass : public Pass {
extra_args(args, args.size(), design); extra_args(args, args.size(), design);
size_t cnt = 0; int cnt = 0;
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
{ {
for (auto cell : module->selected_cells()) 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; } AnlogicEqnPass;

View File

@ -228,6 +228,25 @@ output Y;
assign Y = S ? B : A; assign Y = S ? B : A;
endmodule 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---| // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//- //-
//- $_MUX4_ (A, B, C, D, S, T, Y) //- $_MUX4_ (A, B, C, D, S, T, Y)

View File

@ -50,7 +50,7 @@ struct DetermineInitPass : public Pass {
extra_args(args, args.size(), design); extra_args(args, args.size(), design);
size_t cnt = 0; int cnt = 0;
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
{ {
for (auto cell : module->selected_cells()) 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; } DetermineInitPass;

View File

@ -1363,13 +1363,13 @@ module SB_MAC16 (
wire [15:0] p_Ah_Bh, p_Al_Bh, p_Ah_Bl, p_Al_Bl; wire [15:0] p_Ah_Bh, p_Al_Bh, p_Ah_Bl, p_Al_Bl;
wire [15:0] Ah, Al, Bh, Bl; wire [15:0] Ah, Al, Bh, Bl;
assign Ah = {A_SIGNED ? {8{iA[15]}} : 8'b0, iA[15: 8]}; assign Ah = {A_SIGNED ? {8{iA[15]}} : 8'b0, iA[15: 8]};
assign Al = {A_SIGNED ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]}; assign Al = {A_SIGNED && MODE_8x8 ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]};
assign Bh = {B_SIGNED ? {8{iB[15]}} : 8'b0, iB[15: 8]}; assign Bh = {B_SIGNED ? {8{iB[15]}} : 8'b0, iB[15: 8]};
assign Bl = {B_SIGNED ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]}; assign Bl = {B_SIGNED && MODE_8x8 ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]};
assign p_Ah_Bh = Ah * Bh; assign p_Ah_Bh = Ah * Bh; // F
assign p_Al_Bh = Al * Bh; assign p_Al_Bh = {8'b0, Al[7:0]} * Bh; // J
assign p_Ah_Bl = Ah * Bl; assign p_Ah_Bl = Ah * {8'b0, Bl[7:0]}; // K
assign p_Al_Bl = Al * Bl; assign p_Al_Bl = Al * Bl; // G
// Regs F and J // Regs F and J
reg [15:0] rF, rJ; reg [15:0] rF, rJ;
@ -1400,7 +1400,9 @@ module SB_MAC16 (
assign iG = BOT_8x8_MULT_REG ? rG : p_Al_Bl; assign iG = BOT_8x8_MULT_REG ? rG : p_Al_Bl;
// Adder Stage // Adder Stage
assign iL = iG + (iK << 8) + (iJ << 8) + (iF << 16); wire [23:0] iK_e = {A_SIGNED ? {8{iK[15]}} : 8'b0, iK};
wire [23:0] iJ_e = {B_SIGNED ? {8{iJ[15]}} : 8'b0, iJ};
assign iL = iG + (iK_e << 8) + (iJ_e << 8) + (iF << 16);
// Reg H // Reg H
reg [31:0] rH; reg [31:0] rH;

View File

@ -1,10 +1,15 @@
#!/bin/bash #!/bin/bash
set -ex set -ex
sed 's/SB_MAC16/SB_MAC16_UUT/; /SB_MAC16_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.v sed 's/SB_MAC16/SB_MAC16_UUT/; /SB_MAC16_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.v
cat /opt/lscc/iCEcube2.2017.01/verilog/sb_ice_syn.v > test_dsp_model_ref.v if [ ! -f "test_dsp_model_ref.v" ]; then
cat /opt/lscc/iCEcube2.2017.01/verilog/sb_ice_syn.v > test_dsp_model_ref.v
fi
for tb in testbench \ for tb in testbench \
testbench_comb_8x8_A testbench_comb_8x8_B testbench_comb_16x16 \ testbench_comb_8x8_A testbench_comb_8x8_B testbench_comb_16x16 \
testbench_seq_16x16_A testbench_seq_16x16_B testbench_seq_16x16_A testbench_seq_16x16_B \
testbench_comb_8x8_A_signedA testbench_comb_8x8_A_signedB testbench_comb_8x8_A_signedAB \
testbench_comb_8x8_B_signedA testbench_comb_8x8_B_signedB testbench_comb_8x8_B_signedAB \
testbench_comb_16x16_signedA testbench_comb_16x16_signedB testbench_comb_16x16_signedAB
do do
iverilog -s $tb -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v iverilog -s $tb -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v
vvp -N ./test_dsp_model vvp -N ./test_dsp_model

View File

@ -241,6 +241,81 @@ module testbench_comb_8x8_A;
) testbench (); ) testbench ();
endmodule endmodule
module testbench_comb_8x8_A_signedA;
testbench #(
.NEG_TRIGGER (0),
.C_REG (0),
.A_REG (0),
.B_REG (0),
.D_REG (0),
.TOP_8x8_MULT_REG (0),
.BOT_8x8_MULT_REG (0),
.PIPELINE_16x16_MULT_REG1 (0),
.PIPELINE_16x16_MULT_REG2 (0),
.TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16
.TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
.TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C
.TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16
.BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
.BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D
.BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.MODE_8x8 (0),
.A_SIGNED (1),
.B_SIGNED (0)
) testbench ();
endmodule
module testbench_comb_8x8_A_signedB;
testbench #(
.NEG_TRIGGER (0),
.C_REG (0),
.A_REG (0),
.B_REG (0),
.D_REG (0),
.TOP_8x8_MULT_REG (0),
.BOT_8x8_MULT_REG (0),
.PIPELINE_16x16_MULT_REG1 (0),
.PIPELINE_16x16_MULT_REG2 (0),
.TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16
.TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
.TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C
.TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16
.BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
.BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D
.BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.MODE_8x8 (0),
.A_SIGNED (0),
.B_SIGNED (1)
) testbench ();
endmodule
module testbench_comb_8x8_A_signedAB;
testbench #(
.NEG_TRIGGER (0),
.C_REG (0),
.A_REG (0),
.B_REG (0),
.D_REG (0),
.TOP_8x8_MULT_REG (0),
.BOT_8x8_MULT_REG (0),
.PIPELINE_16x16_MULT_REG1 (0),
.PIPELINE_16x16_MULT_REG2 (0),
.TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16
.TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
.TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C
.TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16
.BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
.BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D
.BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.MODE_8x8 (0),
.A_SIGNED (1),
.B_SIGNED (1)
) testbench ();
endmodule
module testbench_comb_8x8_B; module testbench_comb_8x8_B;
testbench #( testbench #(
.NEG_TRIGGER (0), .NEG_TRIGGER (0),
@ -266,6 +341,81 @@ module testbench_comb_8x8_B;
) testbench (); ) testbench ();
endmodule endmodule
module testbench_comb_8x8_B_signedA;
testbench #(
.NEG_TRIGGER (0),
.C_REG (0),
.A_REG (0),
.B_REG (0),
.D_REG (0),
.TOP_8x8_MULT_REG (0),
.BOT_8x8_MULT_REG (0),
.PIPELINE_16x16_MULT_REG1 (0),
.PIPELINE_16x16_MULT_REG2 (0),
.TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
.TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
.TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
.TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
.BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
.BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
.BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.MODE_8x8 (0),
.A_SIGNED (1),
.B_SIGNED (0)
) testbench ();
endmodule
module testbench_comb_8x8_B_signedB;
testbench #(
.NEG_TRIGGER (0),
.C_REG (0),
.A_REG (0),
.B_REG (0),
.D_REG (0),
.TOP_8x8_MULT_REG (0),
.BOT_8x8_MULT_REG (0),
.PIPELINE_16x16_MULT_REG1 (0),
.PIPELINE_16x16_MULT_REG2 (0),
.TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
.TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
.TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
.TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
.BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
.BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
.BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.MODE_8x8 (0),
.A_SIGNED (0),
.B_SIGNED (1)
) testbench ();
endmodule
module testbench_comb_8x8_B_signedAB;
testbench #(
.NEG_TRIGGER (0),
.C_REG (0),
.A_REG (0),
.B_REG (0),
.D_REG (0),
.TOP_8x8_MULT_REG (0),
.BOT_8x8_MULT_REG (0),
.PIPELINE_16x16_MULT_REG1 (0),
.PIPELINE_16x16_MULT_REG2 (0),
.TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
.TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
.TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
.TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
.BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
.BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
.BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
.MODE_8x8 (0),
.A_SIGNED (1),
.B_SIGNED (1)
) testbench ();
endmodule
module testbench_comb_16x16; module testbench_comb_16x16;
testbench #( testbench #(
.NEG_TRIGGER (0), .NEG_TRIGGER (0),
@ -291,6 +441,81 @@ module testbench_comb_16x16;
) testbench (); ) testbench ();
endmodule endmodule
module testbench_comb_16x16_signedA;
testbench #(
.NEG_TRIGGER (0),
.C_REG (0),
.A_REG (0),
.B_REG (0),
.D_REG (0),
.TOP_8x8_MULT_REG (0),
.BOT_8x8_MULT_REG (0),
.PIPELINE_16x16_MULT_REG1 (0),
.PIPELINE_16x16_MULT_REG2 (0),
.TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
.TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
.TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
.TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
.BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
.BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
.BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
.BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
.MODE_8x8 (0),
.A_SIGNED (1),
.B_SIGNED (0)
) testbench ();
endmodule
module testbench_comb_16x16_signedB;
testbench #(
.NEG_TRIGGER (0),
.C_REG (0),
.A_REG (0),
.B_REG (0),
.D_REG (0),
.TOP_8x8_MULT_REG (0),
.BOT_8x8_MULT_REG (0),
.PIPELINE_16x16_MULT_REG1 (0),
.PIPELINE_16x16_MULT_REG2 (0),
.TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
.TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
.TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
.TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
.BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
.BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
.BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
.BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
.MODE_8x8 (0),
.A_SIGNED (0),
.B_SIGNED (1)
) testbench ();
endmodule
module testbench_comb_16x16_signedAB;
testbench #(
.NEG_TRIGGER (0),
.C_REG (0),
.A_REG (0),
.B_REG (0),
.D_REG (0),
.TOP_8x8_MULT_REG (0),
.BOT_8x8_MULT_REG (0),
.PIPELINE_16x16_MULT_REG1 (0),
.PIPELINE_16x16_MULT_REG2 (0),
.TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
.TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
.TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
.TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
.BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
.BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
.BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
.BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
.MODE_8x8 (0),
.A_SIGNED (1),
.B_SIGNED (1)
) testbench ();
endmodule
module testbench_seq_16x16_A; module testbench_seq_16x16_A;
testbench #( testbench #(
.NEG_TRIGGER (0), .NEG_TRIGGER (0),

View File

@ -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/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/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_m9k.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_map_m9k.v))
$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/cells_sim.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/a10gx,techlibs/intel/a10gx/cells_sim.v))
$(eval $(call add_share_file,share/intel/cyclonev,techlibs/intel/cyclonev/cells_sim.v)) $(eval $(call add_share_file,share/intel/cyclonev,techlibs/intel/cyclonev/cells_sim.v))

View File

@ -61,8 +61,8 @@ struct SynthIntelPass : public ScriptPass {
log(" from label is synonymous to 'begin', and empty to label is\n"); log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n"); log(" synonymous to the end of the command list.\n");
log("\n"); log("\n");
log(" -noiopads\n"); log(" -iopads\n");
log(" do not use IO pad cells in output netlist\n"); log(" use IO pad cells in output netlist\n");
log("\n"); log("\n");
log(" -nobram\n"); log(" -nobram\n");
log(" do not use block RAM cells in output netlist\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; string top_opt, family_opt, vout_file, blif_file;
bool retime, flatten, nobram, noiopads; bool retime, flatten, nobram, iopads;
void clear_flags() YS_OVERRIDE void clear_flags() YS_OVERRIDE
{ {
@ -90,7 +90,7 @@ struct SynthIntelPass : public ScriptPass {
retime = false; retime = false;
flatten = true; flatten = true;
nobram = false; nobram = false;
noiopads = false; iopads = false;
} }
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE 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); run_to = args[argidx].substr(pos + 1);
continue; continue;
} }
if (args[argidx] == "-noiopads") { if (args[argidx] == "-iopads") {
noiopads = true; iopads = true;
continue; continue;
} }
if (args[argidx] == "-nobram") { if (args[argidx] == "-nobram") {
@ -187,8 +187,15 @@ struct SynthIntelPass : public ScriptPass {
} }
if (!nobram && check_label("map_bram", "(skip if -nobram)")) { if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
run("memory_bram -rules +/intel/common/brams.txt"); if (family_opt == "cycloneiv" ||
run("techmap -map +/intel/common/brams_map.v"); 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")) { if (check_label("map_ffram")) {
@ -215,10 +222,9 @@ struct SynthIntelPass : public ScriptPass {
} }
if (check_label("map_cells")) { if (check_label("map_cells")) {
if (!noiopads) if (iopads || help_mode)
run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(unless -noiopads)"); 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(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str()));
run("dffinit -highlow -ff dffeas q power_up"); run("dffinit -highlow -ff dffeas q power_up");
run("clean -purge"); run("clean -purge");
} }

View File

@ -24,9 +24,9 @@ module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLA
(* techmap_celltype = "$_DFF_PN0_" *) (* 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 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_" *) (* 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_" *) (* 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); module \$__SHREG_ (input C, input D, input E, output Q);
parameter DEPTH = 0; parameter DEPTH = 0;

View File

@ -52,7 +52,7 @@ module \$__XILINX_RAMB8BWER_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DAT
.CLKBRDCLK(CLK2 ^ !CLKPOL2), .CLKBRDCLK(CLK2 ^ !CLKPOL2),
.ENBRDEN(A1EN), .ENBRDEN(A1EN),
.REGCEBREGCE(|1), .REGCEBREGCE(|1),
.RSTB(|0) .RSTBRST(|0)
); );
endmodule endmodule
@ -217,7 +217,7 @@ module \$__XILINX_RAMB8BWER_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DAT
.CLKBRDCLK(CLK3 ^ !CLKPOL3), .CLKBRDCLK(CLK3 ^ !CLKPOL3),
.ENBRDEN(|1), .ENBRDEN(|1),
.REGCEBREGCE(|0), .REGCEBREGCE(|0),
.RSTB(|0), .RSTBRST(|0),
.WEBWEU(B1EN_2) .WEBWEU(B1EN_2)
); );
end else begin end else begin
@ -248,7 +248,7 @@ module \$__XILINX_RAMB8BWER_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DAT
.CLKBRDCLK(CLK3 ^ !CLKPOL3), .CLKBRDCLK(CLK3 ^ !CLKPOL3),
.ENBRDEN(|1), .ENBRDEN(|1),
.REGCEBREGCE(|0), .REGCEBREGCE(|0),
.RSTB(|0), .RSTBRST(|0),
.WEBWEU(B1EN_2) .WEBWEU(B1EN_2)
); );
end endgenerate end endgenerate

View File

@ -1,2 +1,4 @@
/*.log /*.log
/*.out /*.out
/write_gzip.v
/write_gzip.v.gz

Binary file not shown.

View File

@ -0,0 +1,2 @@
read_verilog gzip_verilog.v.gz
select -assert-any top

View File

@ -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