aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG1
-rw-r--r--Makefile76
-rw-r--r--README.md4
-rw-r--r--backends/aiger/xaiger.cc4
-rw-r--r--backends/cxxrtl/cxxrtl.cc97
-rw-r--r--backends/json/json.cc44
-rw-r--r--backends/smt2/Makefile.inc14
-rw-r--r--backends/smt2/smtbmc.py21
-rw-r--r--backends/verilog/verilog_backend.cc2
-rw-r--r--frontends/ast/genrtlil.cc20
-rw-r--r--frontends/ast/simplify.cc36
-rw-r--r--frontends/ilang/ilang_parser.y8
-rw-r--r--frontends/verilog/verilog_parser.y4
-rw-r--r--kernel/log.h7
-rw-r--r--kernel/rtlil.cc2
-rw-r--r--kernel/yosys.cc11
-rw-r--r--kernel/yosys.h1
-rw-r--r--manual/command-reference-manual.tex2498
-rw-r--r--misc/yosys-config.in8
-rw-r--r--passes/cmds/setundef.cc22
-rw-r--r--passes/memory/memory_bram.cc48
-rw-r--r--passes/memory/memory_map.cc119
-rw-r--r--passes/opt/opt_clean.cc6
-rw-r--r--passes/opt/opt_expr.cc162
-rw-r--r--passes/sat/Makefile.inc1
-rw-r--r--passes/sat/qbfsat.cc550
-rw-r--r--passes/techmap/Makefile.inc7
-rw-r--r--passes/techmap/abc.cc10
-rw-r--r--passes/techmap/abc9.cc4
-rw-r--r--passes/techmap/abc9_exe.cc12
-rw-r--r--passes/techmap/abc9_ops.cc3
-rw-r--r--passes/techmap/dffinit.cc8
-rw-r--r--passes/techmap/dffsr2dff.cc213
-rw-r--r--passes/techmap/techmap.cc2
-rw-r--r--passes/techmap/zinit.cc72
-rw-r--r--techlibs/achronix/synth_achronix.cc1
-rw-r--r--techlibs/anlogic/synth_anlogic.cc1
-rw-r--r--techlibs/common/gen_fine_ffs.py9
-rw-r--r--techlibs/common/simcells.v36
-rw-r--r--techlibs/common/simlib.v2
-rw-r--r--techlibs/ecp5/brams.txt62
-rw-r--r--techlibs/ecp5/lutrams.txt9
-rw-r--r--techlibs/ecp5/synth_ecp5.cc5
-rw-r--r--techlibs/efinix/synth_efinix.cc1
-rw-r--r--techlibs/gowin/synth_gowin.cc1
-rw-r--r--techlibs/ice40/brams.txt60
-rw-r--r--techlibs/ice40/synth_ice40.cc5
-rw-r--r--techlibs/intel/Makefile.inc1
-rw-r--r--techlibs/intel/synth_intel.cc1
-rw-r--r--techlibs/intel_alm/Makefile.inc23
-rw-r--r--techlibs/intel_alm/common/alm_map.v56
-rw-r--r--techlibs/intel_alm/common/alm_sim.v482
-rw-r--r--techlibs/intel_alm/common/arith_alm_map.v64
-rw-r--r--techlibs/intel_alm/common/bram_m10k.txt33
-rw-r--r--techlibs/intel_alm/common/bram_m10k_map.v31
-rw-r--r--techlibs/intel_alm/common/bram_m20k.txt33
-rw-r--r--techlibs/intel_alm/common/bram_m20k_map.v31
-rw-r--r--techlibs/intel_alm/common/dff_map.v124
-rw-r--r--techlibs/intel_alm/common/dff_sim.v48
-rw-r--r--techlibs/intel_alm/common/lutram_mlab.txt20
-rw-r--r--techlibs/intel_alm/common/lutram_mlab_map.v29
-rw-r--r--techlibs/intel_alm/common/megafunction_bb.v108
-rw-r--r--techlibs/intel_alm/common/quartus_rename.v19
-rw-r--r--techlibs/intel_alm/cyclone10gx/quartus_rename.v54
-rw-r--r--techlibs/intel_alm/cyclonev/quartus_rename.v54
-rw-r--r--techlibs/intel_alm/synth_intel_alm.cc241
-rw-r--r--techlibs/sf2/synth_sf2.cc1
-rw-r--r--techlibs/xilinx/synth_xilinx.cc3
-rw-r--r--tests/arch/common/blockram.v42
-rw-r--r--tests/arch/common/blockrom.v31
-rw-r--r--tests/arch/ecp5/memories.ys330
-rw-r--r--tests/arch/ice40/lutram.ys15
-rw-r--r--tests/arch/ice40/memories.ys168
-rw-r--r--tests/arch/intel_alm/add_sub.ys8
-rw-r--r--tests/arch/intel_alm/adffs.ys48
-rw-r--r--tests/arch/intel_alm/counter.ys13
-rw-r--r--tests/arch/intel_alm/dffs.ys22
-rw-r--r--tests/arch/intel_alm/fsm.ys18
-rw-r--r--tests/arch/intel_alm/logic.ys11
-rw-r--r--tests/arch/intel_alm/mux.ys45
-rwxr-xr-xtests/arch/intel_alm/run-test.sh20
-rw-r--r--tests/arch/intel_alm/shifter.ys10
-rw-r--r--tests/arch/intel_alm/tribuf.ys13
-rw-r--r--tests/opt/opt_expr.ys28
-rw-r--r--tests/opt/opt_expr_alu.ys56
-rw-r--r--tests/select/.gitignore1
-rw-r--r--tests/svtypes/typedef_package.sv11
-rw-r--r--tests/techmap/dffinit.ys25
-rw-r--r--tests/techmap/zinit.ys151
-rw-r--r--tests/various/bug1876.ys60
90 files changed, 6195 insertions, 676 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 18f82bdd1..5fd82fccf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -63,6 +63,7 @@ Yosys 0.9 .. Yosys 0.9-dev
- Improved support of $readmem[hb] Memory Content File inclusion
- Added "opt_lut_ins" pass
- Added "logger" pass
+ - Removed "dffsr2dff" (use opt_rmdff instead)
Yosys 0.8 .. Yosys 0.9
----------------------
diff --git a/Makefile b/Makefile
index d1c4a2030..fc417ab9d 100644
--- a/Makefile
+++ b/Makefile
@@ -42,6 +42,7 @@ SANITIZER =
# SANITIZER = undefined
# SANITIZER = cfi
+PROGRAM_PREFIX :=
OS := $(shell uname -s)
PREFIX ?= /usr/local
@@ -56,15 +57,15 @@ ENABLE_LIBYOSYS := 1
endif
BINDIR := $(PREFIX)/bin
-LIBDIR := $(PREFIX)/lib
-DATDIR := $(PREFIX)/share/yosys
+LIBDIR := $(PREFIX)/lib/$(PROGRAM_PREFIX)yosys
+DATDIR := $(PREFIX)/share/$(PROGRAM_PREFIX)yosys
EXE =
OBJS =
GENFILES =
EXTRA_OBJS =
EXTRA_TARGETS =
-TARGETS = yosys$(EXE) yosys-config
+TARGETS = $(PROGRAM_PREFIX)yosys$(EXE) $(PROGRAM_PREFIX)yosys-config
PRETTY = 1
SMALL = 0
@@ -249,7 +250,7 @@ LDFLAGS += $(EMCCFLAGS)
LDLIBS =
EXE = .js
-TARGETS := $(filter-out yosys-config,$(TARGETS))
+TARGETS := $(filter-out $(PROGRAM_PREFIX)yosys-config,$(TARGETS))
EXTRA_TARGETS += yosysjs-$(YOSYS_VER).zip
ifeq ($(ENABLE_ABC),1)
@@ -463,7 +464,7 @@ LDLIBS += -lpthread
endif
else
ifeq ($(ABCEXTERNAL),)
-TARGETS += yosys-abc$(EXE)
+TARGETS += $(PROGRAM_PREFIX)yosys-abc$(EXE)
endif
endif
endif
@@ -513,8 +514,8 @@ endef
ifeq ($(PRETTY), 1)
P_STATUS = 0
P_OFFSET = 0
-P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) yosys$(EXE) | $(AWK) 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }'))
-P_SHOW = [$(shell $(AWK) "BEGIN { N=$(words $(OBJS) yosys$(EXE)); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%]
+P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) $(PROGRAM_PREFIX)yosys$(EXE) | $(AWK) 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }'))
+P_SHOW = [$(shell $(AWK) "BEGIN { N=$(words $(OBJS) $(PROGRAM_PREFIX)yosys$(EXE)); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%]
P = @echo "$(if $(findstring $@,$(TARGETS) $(EXTRA_TARGETS)),$(eval P_OFFSET = 10))$(call P_UPDATE)$(call P_SHOW) Building $@";
Q = @
S = -s
@@ -552,7 +553,7 @@ OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/cal
OBJS += kernel/cellaigs.o kernel/celledges.o
kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"'
-kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"'
+kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"'
OBJS += libs/bigint/BigIntegerAlgorithms.o libs/bigint/BigInteger.o libs/bigint/BigIntegerUtils.o
OBJS += libs/bigint/BigUnsigned.o libs/bigint/BigUnsignedInABase.o
@@ -605,7 +606,7 @@ include techlibs/common/Makefile.inc
endif
ifeq ($(LINK_ABC),1)
-OBJS += yosys-libabc.a
+OBJS += $(PROGRAM_PREFIX)yosys-libabc.a
endif
top-all: $(TARGETS) $(EXTRA_TARGETS)
@@ -617,14 +618,14 @@ ifeq ($(CONFIG),emcc)
yosys.js: $(filter-out yosysjs-$(YOSYS_VER).zip,$(EXTRA_TARGETS))
endif
-yosys$(EXE): $(OBJS)
- $(P) $(LD) -o yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS)
+$(PROGRAM_PREFIX)yosys$(EXE): $(OBJS)
+ $(P) $(LD) -o $(PROGRAM_PREFIX)yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS)
libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
ifeq ($(OS), Darwin)
- $(P) $(LD) -o libyosys.so -shared -Wl,-install_name,libyosys.so $(LDFLAGS) $^ $(LDLIBS)
+ $(P) $(LD) -o libyosys.so -shared -Wl,-install_name,$(DESTDIR)$(LIBDIR)/libyosys.so $(LDFLAGS) $^ $(LDLIBS)
else
- $(P) $(LD) -o libyosys.so -shared -Wl,-soname,libyosys.so $(LDFLAGS) $^ $(LDLIBS)
+ $(P) $(LD) -o libyosys.so -shared -Wl,-soname,$(DESTDIR)$(LIBDIR)/libyosys.so $(LDFLAGS) $^ $(LDLIBS)
endif
%.o: %.cc
@@ -660,11 +661,11 @@ CXXFLAGS_NOVERIFIC = $(CXXFLAGS)
LDLIBS_NOVERIFIC = $(LDLIBS)
endif
-yosys-config: misc/yosys-config.in
+$(PROGRAM_PREFIX)yosys-config: misc/yosys-config.in
$(P) $(SED) -e 's#@CXXFLAGS@#$(subst -I. -I"$(YOSYS_SRC)",-I"$(DATDIR)/include",$(strip $(CXXFLAGS_NOVERIFIC)))#;' \
-e 's#@CXX@#$(strip $(CXX))#;' -e 's#@LDFLAGS@#$(strip $(LDFLAGS) $(PLUGIN_LDFLAGS))#;' -e 's#@LDLIBS@#$(strip $(LDLIBS_NOVERIFIC))#;' \
- -e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > yosys-config
- $(Q) chmod +x yosys-config
+ -e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > $(PROGRAM_PREFIX)yosys-config
+ $(Q) chmod +x $(PROGRAM_PREFIX)yosys-config
abc/abc-$(ABCREV)$(EXE) abc/libabc-$(ABCREV).a:
$(P)
@@ -691,11 +692,11 @@ ifeq ($(ABCREV),default)
.PHONY: abc/libabc-$(ABCREV).a
endif
-yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE)
- $(P) cp abc/abc-$(ABCREV)$(EXE) yosys-abc$(EXE)
+$(PROGRAM_PREFIX)yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE)
+ $(P) cp abc/abc-$(ABCREV)$(EXE) $(PROGRAM_PREFIX)yosys-abc$(EXE)
-yosys-libabc.a: abc/libabc-$(ABCREV).a
- $(P) cp abc/libabc-$(ABCREV).a yosys-libabc.a
+$(PROGRAM_PREFIX)yosys-libabc.a: abc/libabc-$(ABCREV).a
+ $(P) cp abc/libabc-$(ABCREV).a $(PROGRAM_PREFIX)yosys-libabc.a
ifneq ($(SEED),)
SEEDOPT="-S $(SEED)"
@@ -736,6 +737,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/arch/efinix && bash run-test.sh $(SEEDOPT)
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
+ +cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT)
+cd tests/rpc && bash run-test.sh
+cd tests/memfile && bash run-test.sh
@echo ""
@@ -775,14 +777,14 @@ clean-unit-test:
install: $(TARGETS) $(EXTRA_TARGETS)
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
$(INSTALL_SUDO) cp $(filter-out libyosys.so,$(TARGETS)) $(DESTDIR)$(BINDIR)
-ifneq ($(filter yosys,$(TARGETS)),)
- $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/yosys
+ifneq ($(filter $(PROGRAM_PREFIX)yosys,$(TARGETS)),)
+ $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys
endif
-ifneq ($(filter yosys-abc,$(TARGETS)),)
- $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/yosys-abc
+ifneq ($(filter $(PROGRAM_PREFIX)yosys-abc,$(TARGETS)),)
+ $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc
endif
-ifneq ($(filter yosys-filterlib,$(TARGETS)),)
- $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/yosys-filterlib
+ifneq ($(filter $(PROGRAM_PREFIX)yosys-filterlib,$(TARGETS)),)
+ $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib
endif
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR)
$(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/.
@@ -791,9 +793,9 @@ ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(LIBDIR)/
$(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so
ifeq ($(ENABLE_PYOSYS),1)
- $(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/pyosys
- $(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/pyosys/
- $(INSTALL_SUDO) cp misc/__init__.py $(PYTHON_DESTDIR)/pyosys/
+ $(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
+ $(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
+ $(INSTALL_SUDO) cp misc/__init__.py $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/
endif
endif
@@ -803,14 +805,14 @@ uninstall:
ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) rm -vf $(DESTDIR)$(LIBDIR)/libyosys.so
ifeq ($(ENABLE_PYOSYS),1)
- $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/pyosys/libyosys.so
- $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/pyosys/__init__.py
- $(INSTALL_SUDO) rmdir $(PYTHON_DESTDIR)/pyosys
+ $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
+ $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/__init__.py
+ $(INSTALL_SUDO) rmdir $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
endif
endif
update-manual: $(TARGETS) $(EXTRA_TARGETS)
- cd manual && ../yosys -p 'help -write-tex-command-reference-manual'
+ cd manual && ../$(PROGRAM_PREFIX)yosys -p 'help -write-tex-command-reference-manual'
manual: $(TARGETS) $(EXTRA_TARGETS)
cd manual && bash appnotes.sh
@@ -836,13 +838,13 @@ clean:
clean-abc:
$(MAKE) -C abc DEP= clean
- rm -f yosys-abc$(EXE) yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
+ rm -f $(PROGRAM_PREFIX)yosys-abc$(EXE) $(PROGRAM_PREFIX)yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
mrproper: clean
git clean -xdf
coverage:
- ./yosys -qp 'help; help -all'
+ ./$(PROGRAM_PREFIX)yosys -qp 'help; help -all'
rm -rf coverage.info coverage_html
lcov --capture -d . --no-external -o coverage.info
genhtml coverage.info --output-directory coverage_html
@@ -868,9 +870,9 @@ ifeq ($(CONFIG),mxe)
mxebin: $(TARGETS) $(EXTRA_TARGETS)
rm -rf yosys-win32-mxebin-$(YOSYS_VER){,.zip}
mkdir -p yosys-win32-mxebin-$(YOSYS_VER)
- cp -r yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/
+ cp -r $(PROGRAM_PREFIX)yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/
ifeq ($(ENABLE_ABC),1)
- cp -r yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/
+ cp -r $(PROGRAM_PREFIX)yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/
endif
echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-mxebin-$(YOSYS_VER)/readme.txt
echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt
diff --git a/README.md b/README.md
index ce7b26411..0a81d8bb9 100644
--- a/README.md
+++ b/README.md
@@ -443,8 +443,8 @@ Verilog Attributes and non-standard features
- The ``wiretype`` attribute is added by the verilog parser for wires of a
typedef'd type to indicate the type identifier.
-- Various ``enum_{width}_{value}`` attributes are added to wires of an
- enumerated type to give a map of possible enum items to their values.
+- Various ``enum_value_{value}`` attributes are added to wires of an enumerated type
+ to give a map of possible enum items to their values.
- The ``enum_base_type`` attribute is added to enum items to indicate which
enum they belong to (enums -- anonymous and otherwise -- are
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index 3b51d8685..3c7c745fe 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -280,6 +280,10 @@ struct XAigerWriter
if (abc9_flop)
continue;
}
+ else {
+ if (cell->type == ID($__ABC9_DELAY))
+ log_error("Cell type '%s' not recognised. Check that '+/abc9_model.v' has been read.\n", cell->type.c_str());
+ }
bool cell_known = inst_module || cell->known();
for (const auto &c : cell->connections()) {
diff --git a/backends/cxxrtl/cxxrtl.cc b/backends/cxxrtl/cxxrtl.cc
index 465882858..d1a855bf0 100644
--- a/backends/cxxrtl/cxxrtl.cc
+++ b/backends/cxxrtl/cxxrtl.cc
@@ -357,13 +357,19 @@ struct FlowGraph {
};
struct CxxrtlWorker {
+ bool split_intf = false;
+ std::string intf_filename;
+ std::string design_ns = "cxxrtl_design";
+ std::ostream *impl_f = nullptr;
+ std::ostream *intf_f = nullptr;
+
bool elide_internal = false;
bool elide_public = false;
bool localize_internal = false;
bool localize_public = false;
bool run_splitnets = false;
- std::ostream &f;
+ std::ostringstream f;
std::string indent;
int temporary = 0;
@@ -377,8 +383,6 @@ struct CxxrtlWorker {
dict<const RTLIL::Module*, std::vector<FlowGraph::Node>> schedule;
pool<const RTLIL::Wire*> localized_wires;
- CxxrtlWorker(std::ostream &f) : f(f) {}
-
void inc_indent() {
indent += "\t";
}
@@ -867,7 +871,8 @@ struct CxxrtlWorker {
dump_sigspec_rhs(cell->getPort(ID(ADDR)));
f << ", " << memory->start_offset << ", " << memory->size << ");\n";
if (cell->type == ID($memrd)) {
- if (!cell->getPort(ID(EN)).is_fully_ones()) {
+ bool has_enable = cell->getParam(ID(CLK_ENABLE)).as_bool() && !cell->getPort(ID(EN)).is_fully_ones();
+ if (has_enable) {
f << indent << "if (";
dump_sigspec_rhs(cell->getPort(ID(EN)));
f << ") {\n";
@@ -926,7 +931,7 @@ struct CxxrtlWorker {
f << " = value<" << memory->width << "> {};\n";
dec_indent();
f << indent << "}\n";
- if (!cell->getPort(ID(EN)).is_fully_ones()) {
+ if (has_enable) {
dec_indent();
f << indent << "}\n";
}
@@ -970,6 +975,8 @@ struct CxxrtlWorker {
continue;
}
if (cell->output(conn.first)) {
+ if (conn.second.empty())
+ continue; // ignore disconnected ports
f << indent;
dump_sigspec_lhs(conn.second);
f << " = " << mangle(cell) << "." << mangle_wire_name(conn.first) << ".curr;\n";
@@ -1191,7 +1198,7 @@ struct CxxrtlWorker {
}
}
- void dump_module(RTLIL::Module *module)
+ void dump_module_intf(RTLIL::Module *module)
{
dump_attrs(module);
f << "struct " << mangle(module) << " : public module {\n";
@@ -1220,7 +1227,10 @@ struct CxxrtlWorker {
dec_indent();
f << "}; // struct " << mangle(module) << "\n";
f << "\n";
+ }
+ void dump_module_impl(RTLIL::Module *module)
+ {
f << "void " << mangle(module) << "::eval() {\n";
inc_indent();
for (auto wire : module->wires())
@@ -1323,18 +1333,49 @@ struct CxxrtlWorker {
}
log_assert(topo_design.sort());
- f << "#include <cxxrtl.h>\n";
+ if (split_intf) {
+ // The only thing more depraved than include guards, is mangling filenames to turn them into include guards.
+ std::string include_guard = design_ns + "_header";
+ std::transform(include_guard.begin(), include_guard.end(), include_guard.begin(), ::toupper);
+
+ f << "#ifndef " << include_guard << "\n";
+ f << "#define " << include_guard << "\n";
+ f << "\n";
+ f << "#include <backends/cxxrtl/cxxrtl.h>\n";
+ f << "\n";
+ f << "using namespace cxxrtl;\n";
+ f << "\n";
+ f << "namespace " << design_ns << " {\n";
+ f << "\n";
+ for (auto module : topo_design.sorted) {
+ if (!design->selected_module(module))
+ continue;
+ dump_module_intf(module);
+ }
+ f << "} // namespace " << design_ns << "\n";
+ f << "\n";
+ f << "#endif\n";
+ *intf_f << f.str(); f.str("");
+ }
+
+ if (split_intf)
+ f << "#include \"" << intf_filename << "\"\n";
+ else
+ f << "#include <backends/cxxrtl/cxxrtl.h>\n";
f << "\n";
f << "using namespace cxxrtl_yosys;\n";
f << "\n";
- f << "namespace cxxrtl_design {\n";
+ f << "namespace " << design_ns << " {\n";
f << "\n";
for (auto module : topo_design.sorted) {
if (!design->selected_module(module))
continue;
- dump_module(module);
+ if (!split_intf)
+ dump_module_intf(module);
+ dump_module_impl(module);
}
- f << "} // namespace cxxrtl_design\n";
+ f << "} // namespace " << design_ns << "\n";
+ *impl_f << f.str(); f.str("");
}
// Edge-type sync rules require us to emit edge detectors, which require coordination between
@@ -1618,6 +1659,16 @@ struct CxxrtlBackend : public Backend {
log("\n");
log("The following options are supported by this backend:\n");
log("\n");
+ log(" -header\n");
+ log(" generate separate interface (.h) and implementation (.cc) files.\n");
+ log(" if specified, the backend must be called with a filename, and filename\n");
+ log(" of the interface is derived from filename of the implementation.\n");
+ log(" otherwise, interface and implementation are generated together.\n");
+ log("\n");
+ log(" -namespace <ns-name>\n");
+ log(" place the generated code into namespace <ns-name>. if not specified,\n");
+ log(" \"cxxrtl_design\" is used.\n");
+ log("\n");
log(" -O <level>\n");
log(" set the optimization level. the default is -O%d. higher optimization\n", DEFAULT_OPT_LEVEL);
log(" levels dramatically decrease compile and run time, and highest level\n");
@@ -1645,6 +1696,7 @@ struct CxxrtlBackend : public Backend {
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
int opt_level = DEFAULT_OPT_LEVEL;
+ CxxrtlWorker worker;
log_header(design, "Executing CXXRTL backend.\n");
@@ -1659,11 +1711,18 @@ struct CxxrtlBackend : public Backend {
opt_level = std::stoi(args[argidx].substr(2));
continue;
}
+ if (args[argidx] == "-header") {
+ worker.split_intf = true;
+ continue;
+ }
+ if (args[argidx] == "-namespace" && argidx+1 < args.size()) {
+ worker.design_ns = args[++argidx];
+ continue;
+ }
break;
}
extra_args(f, filename, args, argidx);
- CxxrtlWorker worker(*f);
switch (opt_level) {
case 5:
worker.run_splitnets = true;
@@ -1680,6 +1739,22 @@ struct CxxrtlBackend : public Backend {
default:
log_cmd_error("Invalid optimization level %d.\n", opt_level);
}
+
+ std::ofstream intf_f;
+ if (worker.split_intf) {
+ if (filename == "<stdout>")
+ log_cmd_error("Option -header must be used with a filename.\n");
+
+ worker.intf_filename = filename.substr(0, filename.rfind('.')) + ".h";
+ intf_f.open(worker.intf_filename, std::ofstream::trunc);
+ if (intf_f.fail())
+ log_cmd_error("Can't open file `%s' for writing: %s\n",
+ worker.intf_filename.c_str(), strerror(errno));
+
+ worker.intf_f = &intf_f;
+ }
+ worker.impl_f = f;
+
worker.prepare_design(design);
worker.dump_design(design);
}
diff --git a/backends/json/json.cc b/backends/json/json.cc
index 6c924ff99..1da23bb7d 100644
--- a/backends/json/json.cc
+++ b/backends/json/json.cc
@@ -303,8 +303,13 @@ struct JsonBackend : public Backend {
log("The general syntax of the JSON output created by this command is as follows:\n");
log("\n");
log(" {\n");
+ log(" \"creator\": \"Yosys <version info>\",\n");
log(" \"modules\": {\n");
log(" <module_name>: {\n");
+ log(" \"attributes\": {\n");
+ log(" <attribute_name>: <attribute_value>,\n");
+ log(" ...\n");
+ log(" },\n");
log(" \"ports\": {\n");
log(" <port_name>: <port_details>,\n");
log(" ...\n");
@@ -329,13 +334,19 @@ struct JsonBackend : public Backend {
log(" {\n");
log(" \"direction\": <\"input\" | \"output\" | \"inout\">,\n");
log(" \"bits\": <bit_vector>\n");
+ log(" \"offset\": <the lowest bit index in use, if non-0>\n");
+ log(" \"upto\": <1 if the port bit indexing is MSB-first>\n");
log(" }\n");
log("\n");
+ log("The \"offset\" and \"upto\" fields are skipped if their value would be 0.");
+ log("They don't affect connection semantics, and are only used to preserve original");
+ log("HDL bit indexing.");
log("And <cell_details> is:\n");
log("\n");
log(" {\n");
log(" \"hide_name\": <1 | 0>,\n");
log(" \"type\": <cell_type>,\n");
+ log(" \"model\": <AIG model name, if -aig option used>,\n");
log(" \"parameters\": {\n");
log(" <parameter_name>: <parameter_value>,\n");
log(" ...\n");
@@ -359,6 +370,8 @@ struct JsonBackend : public Backend {
log(" {\n");
log(" \"hide_name\": <1 | 0>,\n");
log(" \"bits\": <bit_vector>\n");
+ log(" \"offset\": <the lowest bit index in use, if non-0>\n");
+ log(" \"upto\": <1 if the port bit indexing is MSB-first>\n");
log(" }\n");
log("\n");
log("The \"hide_name\" fields are set to 1 when the name of this cell or net is\n");
@@ -386,9 +399,15 @@ struct JsonBackend : public Backend {
log("\n");
log("Translates to the following JSON output:\n");
log("\n");
+
log(" {\n");
+ log(" \"creator\": \"Yosys 0.9+2406 (git sha1 fb1168d8, clang 9.0.1 -fPIC -Os)\",\n");
log(" \"modules\": {\n");
log(" \"test\": {\n");
+ log(" \"attributes\": {\n");
+ log(" \"cells_not_processed\": \"00000000000000000000000000000001\",\n");
+ log(" \"src\": \"test.v:1.1-4.10\"\n");
+ log(" },\n");
log(" \"ports\": {\n");
log(" \"x\": {\n");
log(" \"direction\": \"input\",\n");
@@ -404,33 +423,34 @@ struct JsonBackend : public Backend {
log(" \"hide_name\": 0,\n");
log(" \"type\": \"foo\",\n");
log(" \"parameters\": {\n");
- log(" \"Q\": 1337,\n");
- log(" \"P\": 42\n");
+ log(" \"P\": \"00000000000000000000000000101010\",\n");
+ log(" \"Q\": \"00000000000000000000010100111001\"\n");
log(" },\n");
log(" \"attributes\": {\n");
- log(" \"keep\": 1,\n");
- log(" \"src\": \"test.v:2\"\n");
+ log(" \"keep\": \"00000000000000000000000000000001\",\n");
+ log(" \"module_not_derived\": \"00000000000000000000000000000001\",\n");
+ log(" \"src\": \"test.v:3.1-3.55\"\n");
log(" },\n");
log(" \"connections\": {\n");
- log(" \"C\": [ 2, 2, 2, 2, \"0\", \"1\", \"0\", \"1\" ],\n");
+ log(" \"A\": [ 3, 2 ],\n");
log(" \"B\": [ 2, 3 ],\n");
- log(" \"A\": [ 3, 2 ]\n");
+ log(" \"C\": [ 2, 2, 2, 2, \"0\", \"1\", \"0\", \"1\" ]\n");
log(" }\n");
log(" }\n");
log(" },\n");
log(" \"netnames\": {\n");
- log(" \"y\": {\n");
+ log(" \"x\": {\n");
log(" \"hide_name\": 0,\n");
- log(" \"bits\": [ 3 ],\n");
+ log(" \"bits\": [ 2 ],\n");
log(" \"attributes\": {\n");
- log(" \"src\": \"test.v:1\"\n");
+ log(" \"src\": \"test.v:1.19-1.20\"\n");
log(" }\n");
log(" },\n");
- log(" \"x\": {\n");
+ log(" \"y\": {\n");
log(" \"hide_name\": 0,\n");
- log(" \"bits\": [ 2 ],\n");
+ log(" \"bits\": [ 3 ],\n");
log(" \"attributes\": {\n");
- log(" \"src\": \"test.v:1\"\n");
+ log(" \"src\": \"test.v:1.22-1.23\"\n");
log(" }\n");
log(" }\n");
log(" }\n");
diff --git a/backends/smt2/Makefile.inc b/backends/smt2/Makefile.inc
index 68394a909..fb01308bd 100644
--- a/backends/smt2/Makefile.inc
+++ b/backends/smt2/Makefile.inc
@@ -6,23 +6,23 @@ ifneq ($(CONFIG),emcc)
# MSYS targets support yosys-smtbmc, but require a launcher script
ifeq ($(CONFIG),$(filter $(CONFIG),msys2 msys2-64))
-TARGETS += yosys-smtbmc.exe yosys-smtbmc-script.py
+TARGETS += $(PROGRAM_PREFIX)yosys-smtbmc.exe $(PROGRAM_PREFIX)yosys-smtbmc-script.py
# Needed to find the Python interpreter for yosys-smtbmc scripts.
# Override if necessary, it is only used for msys2 targets.
PYTHON := $(shell cygpath -w -m $(PREFIX)/bin/python3)
-yosys-smtbmc-script.py: backends/smt2/smtbmc.py
- $(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' \
+$(PROGRAM_PREFIX)yosys-smtbmc-script.py: backends/smt2/smtbmc.py
+ $(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' \
-e "s|#!/usr/bin/env python3|#!$(PYTHON)|" < $< > $@
-yosys-smtbmc.exe: misc/launcher.c yosys-smtbmc-script.py
+$(PROGRAM_PREFIX)yosys-smtbmc.exe: misc/launcher.c $(PROGRAM_PREFIX)yosys-smtbmc-script.py
$(P) $(CXX) -DGUI=0 -O -s -o $@ $<
# Other targets
else
-TARGETS += yosys-smtbmc
+TARGETS += $(PROGRAM_PREFIX)yosys-smtbmc
-yosys-smtbmc: backends/smt2/smtbmc.py
- $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new
+$(PROGRAM_PREFIX)yosys-smtbmc: backends/smt2/smtbmc.py
+ $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' < $< > $@.new
$(Q) chmod +x $@.new
$(Q) mv $@.new $@
endif
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py
index 630464419..d3015b066 100644
--- a/backends/smt2/smtbmc.py
+++ b/backends/smt2/smtbmc.py
@@ -49,12 +49,12 @@ presat = False
smtcinit = False
smtctop = None
noinit = False
+binarymode = False
so = SmtOpts()
def usage():
- print("""
-yosys-smtbmc [options] <yosys_smt2_output>
+ print(os.path.basename(sys.argv[0]) + """ [options] <yosys_smt2_output>
-t <num_steps>
-t <skip_steps>:<num_steps>
@@ -150,6 +150,9 @@ yosys-smtbmc [options] <yosys_smt2_output>
add <num_steps> time steps at the end of the trace
when creating a counter example (this additional time
steps will still be constrained by assumptions)
+
+ --binary
+ dump anyconst values as raw bit strings
""" + so.helpmsg())
sys.exit(1)
@@ -158,7 +161,7 @@ try:
opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:igcm:", so.longopts +
["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "btorwit=", "presat",
"dump-vcd=", "dump-vlogtb=", "vlogtb-top=", "dump-smtc=", "dump-all", "noinfo", "append=",
- "smtc-init", "smtc-top=", "noinit"])
+ "smtc-init", "smtc-top=", "noinit", "binary"])
except:
usage()
@@ -229,6 +232,8 @@ for o, a in opts:
covermode = True
elif o == "-m":
topmod = a
+ elif o == "--binary":
+ binarymode = True
elif so.handle(o, a):
pass
else:
@@ -1089,9 +1094,15 @@ def print_anyconsts_worker(mod, state, path):
for fun, info in smt.modinfo[mod].anyconsts.items():
if info[1] is None:
- print_msg("Value for anyconst in %s (%s): %d" % (path, info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state)))))
+ if not binarymode:
+ print_msg("Value for anyconst in %s (%s): %d" % (path, info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state)))))
+ else:
+ print_msg("Value for anyconst in %s (%s): %s" % (path, info[0], smt.bv2bin(smt.get("(|%s| %s)" % (fun, state)))))
else:
- print_msg("Value for anyconst %s.%s (%s): %d" % (path, info[1], info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state)))))
+ if not binarymode:
+ print_msg("Value for anyconst %s.%s (%s): %d" % (path, info[1], info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state)))))
+ else:
+ print_msg("Value for anyconst %s.%s (%s): %s" % (path, info[1], info[0], smt.bv2bin(smt.get("(|%s| %s)" % (fun, state)))))
def print_anyconsts(state):
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index 5467e250b..11b2ae10f 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -1984,7 +1984,7 @@ struct VerilogBackend : public Backend {
extra_args(f, filename, args, argidx);
if (extmem)
{
- if (filename.empty())
+ if (filename == "<stdout>")
log_cmd_error("Option -extmem must be used with a filename.\n");
extmem_prefix = filename.substr(0, filename.rfind('.'));
}
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index c0539252c..ab368fdb0 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -1326,20 +1326,25 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
{
if (width_hint < 0)
detectSignWidth(width_hint, sign_hint);
+ is_signed = sign_hint;
RTLIL::SigSpec cond = children[0]->genRTLIL();
RTLIL::SigSpec sig;
- if (cond.is_fully_const()) {
+
+ if (cond.is_fully_def())
+ {
if (cond.as_bool()) {
sig = children[1]->genRTLIL(width_hint, sign_hint);
- widthExtend(this, sig, sig.size(), children[1]->is_signed);
- }
- else {
+ log_assert(is_signed == children[1]->is_signed);
+ } else {
sig = children[2]->genRTLIL(width_hint, sign_hint);
- widthExtend(this, sig, sig.size(), children[2]->is_signed);
+ log_assert(is_signed == children[2]->is_signed);
}
+
+ widthExtend(this, sig, sig.size(), is_signed);
}
- else {
+ else
+ {
RTLIL::SigSpec val1 = children[1]->genRTLIL(width_hint, sign_hint);
RTLIL::SigSpec val2 = children[2]->genRTLIL(width_hint, sign_hint);
@@ -1347,7 +1352,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
cond = uniop2rtlil(this, ID($reduce_bool), 1, cond, false);
int width = max(val1.size(), val2.size());
- is_signed = children[1]->is_signed && children[2]->is_signed;
+ log_assert(is_signed == children[1]->is_signed);
+ log_assert(is_signed == children[2]->is_signed);
widthExtend(this, val1, width, is_signed);
widthExtend(this, val2, width, is_signed);
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index b87af0f8c..cb89f58ba 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -420,9 +420,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
current_scope[node->str] = node;
for (auto enode : node->children) {
log_assert(enode->type==AST_ENUM_ITEM);
- if (current_scope.count(enode->str) == 0) {
+ if (current_scope.count(enode->str) == 0)
current_scope[enode->str] = enode;
- }
+ else
+ log_file_error(filename, location.first_line, "enum item %s already exists\n", enode->str.c_str());
}
}
}
@@ -441,6 +442,29 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
}
+ // create name resolution entries for all objects with names
+ if (type == AST_PACKAGE) {
+ //add names to package scope
+ for (size_t i = 0; i < children.size(); i++) {
+ AstNode *node = children[i];
+ // these nodes appear at the top level in a package and can define names
+ if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_TYPEDEF) {
+ current_scope[node->str] = node;
+ }
+ if (node->type == AST_ENUM) {
+ current_scope[node->str] = node;
+ for (auto enode : node->children) {
+ log_assert(enode->type==AST_ENUM_ITEM);
+ if (current_scope.count(enode->str) == 0)
+ current_scope[enode->str] = enode;
+ else
+ log_file_error(filename, location.first_line, "enum item %s already exists in package\n", enode->str.c_str());
+ }
+ }
+ }
+ }
+
+
auto backup_current_block = current_block;
auto backup_current_block_child = current_block_child;
auto backup_current_top_block = current_top_block;
@@ -907,9 +931,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
);
}
//start building attribute string
- std::string enum_item_str = "\\enum_";
- enum_item_str.append(std::to_string(width));
- enum_item_str.append("_");
+ std::string enum_item_str = "\\enum_value_";
//get enum item value
if(enum_item->children[0]->type != AST_CONSTANT){
log_error("expected const, got %s for %s (%s)\n",
@@ -917,8 +939,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
enum_item->str.c_str(), enum_node->str.c_str()
);
}
- int val = enum_item->children[0]->asInt(is_signed);
- enum_item_str.append(std::to_string(val));
+ RTLIL::Const val = enum_item->children[0]->bitsAsConst(width, is_signed);
+ enum_item_str.append(val.as_string());
//set attribute for available val to enum item name mappings
attributes[enum_item_str.c_str()] = mkconst_str(enum_item->str);
}
diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y
index 91adc0cc9..0522fa72a 100644
--- a/frontends/ilang/ilang_parser.y
+++ b/frontends/ilang/ilang_parser.y
@@ -169,7 +169,7 @@ wire_stmt:
current_wire->attributes = attrbuf;
attrbuf.clear();
} wire_options TOK_ID EOL {
- if (current_module->wires_.count($4) != 0)
+ if (current_module->wire($4) != nullptr)
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of wire %s.", $4).c_str());
current_module->rename(current_wire, $4);
free($4);
@@ -232,7 +232,7 @@ memory_options:
cell_stmt:
TOK_CELL TOK_ID TOK_ID EOL {
- if (current_module->cells_.count($3) != 0)
+ if (current_module->cell($3) != nullptr)
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell %s.", $3).c_str());
current_cell = current_module->addCell($3, $2);
current_cell->attributes = attrbuf;
@@ -427,9 +427,9 @@ sigspec:
delete $1;
} |
TOK_ID {
- if (current_module->wires_.count($1) == 0)
+ if (current_module->wire($1) == nullptr)
rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str());
- $$ = new RTLIL::SigSpec(current_module->wires_[$1]);
+ $$ = new RTLIL::SigSpec(current_module->wire($1));
free($1);
} |
sigspec '[' TOK_INT ']' {
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 3bffa3986..76373c2e4 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -521,7 +521,8 @@ package_body:
package_body_stmt:
typedef_decl |
- localparam_decl;
+ localparam_decl |
+ param_decl;
interface:
TOK_INTERFACE {
@@ -1735,7 +1736,6 @@ single_cell:
ast_stack.back()->children.push_back(new AstNode(AST_CELLARRAY, $2, astbuf2));
} '(' cell_port_list ')'{
SET_AST_NODE_LOC(astbuf2, @1, @$);
- SET_AST_NODE_LOC(astbuf3, @1, @$);
};
prim_list:
diff --git a/kernel/log.h b/kernel/log.h
index cd0e8185c..5478482ac 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -29,18 +29,25 @@
#if defined(__GNUC__) && !defined( __clang__) && ( __GNUC__ == 4 && __GNUC_MINOR__ <= 8)
#include <boost/xpressive/xpressive.hpp>
#define YS_REGEX_TYPE boost::xpressive::sregex
+ #define YS_REGEX_MATCH_TYPE boost::xpressive::smatch
#define YS_REGEX_NS boost::xpressive
#define YS_REGEX_COMPILE(param) boost::xpressive::sregex::compile(param, \
boost::xpressive::regex_constants::nosubs | \
boost::xpressive::regex_constants::optimize)
+ #define YS_REGEX_COMPILE_WITH_SUBS(param) boost::xpressive::sregex::compile(param, \
+ boost::xpressive::regex_constants::optimize)
# else
#include <regex>
#define YS_REGEX_TYPE std::regex
+ #define YS_REGEX_MATCH_TYPE std::smatch
#define YS_REGEX_NS std
#define YS_REGEX_COMPILE(param) std::regex(param, \
std::regex_constants::nosubs | \
std::regex_constants::optimize | \
std::regex_constants::egrep)
+ #define YS_REGEX_COMPILE_WITH_SUBS(param) std::regex(param, \
+ std::regex_constants::optimize | \
+ std::regex_constants::egrep)
#endif
#ifndef _WIN32
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index d9003f28c..dc368ead5 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -767,6 +767,8 @@ void RTLIL::Module::makeblackbox()
delete it->second;
processes.clear();
+ connections_.clear();
+
remove(delwires);
set_bool_attribute(ID::blackbox);
}
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index b416c2b74..01131601f 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -835,7 +835,7 @@ std::string proc_share_dirname()
std::string proc_share_path = proc_self_path + "share/";
if (check_file_exists(proc_share_path, true))
return proc_share_path;
- proc_share_path = proc_self_path + "../share/yosys/";
+ proc_share_path = proc_self_path + "../share/" + proc_program_prefix()+ "yosys/";
if (check_file_exists(proc_share_path, true))
return proc_share_path;
# ifdef YOSYS_DATDIR
@@ -848,6 +848,15 @@ std::string proc_share_dirname()
}
#endif
+std::string proc_program_prefix()
+{
+ std::string program_prefix;
+#ifdef YOSYS_PROGRAM_PREFIX
+ program_prefix = YOSYS_PROGRAM_PREFIX;
+#endif
+ return program_prefix;
+}
+
bool fgetline(FILE *f, std::string &buffer)
{
buffer = "";
diff --git a/kernel/yosys.h b/kernel/yosys.h
index 859d5d333..ed48eec09 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -328,6 +328,7 @@ namespace ID = RTLIL::ID;
RTLIL::Design *yosys_get_design();
std::string proc_self_dirname();
std::string proc_share_dirname();
+std::string proc_program_prefix();
const char *create_prompt(RTLIL::Design *design, int recursion_counter);
std::vector<std::string> glob_filename(const std::string &filename_pattern);
void rewrite_filename(std::string &filename);
diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex
index 4925defe3..988f034b4 100644
--- a/manual/command-reference-manual.tex
+++ b/manual/command-reference-manual.tex
@@ -116,20 +116,26 @@ library to a target architecture.
-g type1,type2,...
Map to the specified list of gate types. Supported gates types are:
- AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4.
+ AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX,
+ NMUX, AOI3, OAI3, AOI4, OAI4.
(The NOT gate is always added to this list automatically.)
The following aliases can be used to reference common sets of gate types:
simple: AND OR XOR MUX
- cmos2: NAND NOR
- cmos3: NAND NOR AOI3 OAI3
- cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4
- gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT
- aig: AND NAND OR NOR ANDNOT ORNOT
+ cmos2: NAND NOR
+ cmos3: NAND NOR AOI3 OAI3
+ cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4
+ cmos: NAND NOR AOI3 OAI3 AOI4 OAI4 NMUX MUX XOR XNOR
+ gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT
+ aig: AND NAND OR NOR ANDNOT ORNOT
+
+ The alias 'all' represent the full set of all gate types.
Prefix a gate type with a '-' to remove it from the list. For example
the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent.
+ The default is 'all,-NMUX,-AOI3,-OAI3,-AOI4,-OAI4'.
+
-dff
also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many
clock domains are automatically partitioned in clock domains and each
@@ -156,6 +162,11 @@ library to a target architecture.
this attribute is a unique integer for each ABC process started. This
is useful for debugging the partitioning of clock domains.
+ -dress
+ run the 'dress' command after all other ABC commands. This aims to
+ preserve naming by an equivalence check between the original and post-ABC
+ netlists (experimental).
+
When neither -liberty nor -lut is used, the Yosys standard cell library is
loaded into ABC before the ABC script is executed.
@@ -163,12 +174,251 @@ Note that this is a logic optimization pass within Yosys that is calling ABC
internally. This is not going to "run ABC on your design". It will instead run
ABC on logic snippets extracted from your design. You will not get any useful
output when passing an ABC script that writes a file. Instead write your full
-design as BLIF file with write_blif and the load that into ABC externally if
+design as BLIF file with write_blif and then load that into ABC externally if
+you want to use ABC to convert your design into another format.
+
+[1] http://www.eecs.berkeley.edu/~alanmi/abc/
+\end{lstlisting}
+
+\section{abc9 -- use ABC9 for technology mapping}
+\label{cmd:abc9}
+\begin{lstlisting}[numbers=left,frame=single]
+ abc9 [options] [selection]
+
+This script pass performs a sequence of commands to facilitate the use of the ABC
+tool [1] for technology mapping of the current design to a target FPGA
+architecture. Only fully-selected modules are supported.
+
+ -run <from_label>:<to_label>
+ only run the commands between the labels (see below). an empty
+ from label is synonymous to 'begin', and empty to label is
+ synonymous to the end of the command list.
+
+ -exe <command>
+ use the specified command instead of "<yosys-bindir>/yosys-abc" to execute ABC.
+ This can e.g. be used to call a specific version of ABC or a wrapper.
+
+ -script <file>
+ use the specified ABC script file instead of the default script.
+
+ if <file> starts with a plus sign (+), then the rest of the filename
+ string is interpreted as the command string to be passed to ABC. The
+ leading plus sign is removed and all commas (,) in the string are
+ replaced with blanks before the string is passed to ABC.
+
+ if no -script parameter is given, the following scripts are used:
+ &scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -v; &mfs
+
+ -fast
+ use different default scripts that are slightly faster (at the cost
+ of output quality):
+ &if {C} {W} {D} {R} -v
+
+ -D <picoseconds>
+ set delay target. the string {D} in the default scripts above is
+ replaced by this option when used, and an empty string otherwise
+ (indicating best possible delay).
+
+ -lut <width>
+ generate netlist using luts of (max) the specified width.
+
+ -lut <w1>:<w2>
+ generate netlist using luts of (max) the specified width <w2>. All
+ luts with width <= <w1> have constant cost. for luts larger than <w1>
+ the area cost doubles with each additional input bit. the delay cost
+ is still constant for all lut widths.
+
+ -lut <file>
+ pass this file with lut library to ABC.
+
+ -luts <cost1>,<cost2>,<cost3>,<sizeN>:<cost4-N>,..
+ generate netlist using luts. Use the specified costs for luts with 1,
+ 2, 3, .. inputs.
+
+ -maxlut <width>
+ when auto-generating the lut library, discard all luts equal to or
+ greater than this size (applicable when neither -lut nor -luts is
+ specified).
+
+ -dff
+ also pass $_ABC9_FF_ cells through to ABC. modules with many clock
+ domains are marked as such and automatically partitioned by ABC.
+
+ -nocleanup
+ when this option is used, the temporary files created by this pass
+ are not removed. this is useful for debugging.
+
+ -showtmp
+ print the temp dir name in log. usually this is suppressed so that the
+ command output is identical across runs.
+
+ -box <file>
+ pass this file with box library to ABC.
+
+Note that this is a logic optimization pass within Yosys that is calling ABC
+internally. This is not going to "run ABC on your design". It will instead run
+ABC on logic snippets extracted from your design. You will not get any useful
+output when passing an ABC script that writes a file. Instead write your full
+design as an XAIGER file with `write_xaiger' and then load that into ABC
+externally if you want to use ABC to convert your design into another format.
+
+[1] http://www.eecs.berkeley.edu/~alanmi/abc/
+
+
+ pre:
+ abc9_ops -check
+ scc -set_attr abc9_scc_id {}
+ abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff] (option for -dff)
+ abc9_ops -prep_lut <maxlut> (skip if -lut or -luts)
+ abc9_ops -prep_box [-dff] (skip if -box)
+ select -set abc9_holes A:abc9_holes
+ flatten -wb @abc9_holes
+ techmap @abc9_holes
+ abc9_ops -prep_dff (only if -dff)
+ opt -purge @abc9_holes
+ aigmap
+ wbflip @abc9_holes
+
+ map:
+ foreach module in selection
+ abc9_ops -write_lut <abc-temp-dir>/input.lut (skip if '-lut' or '-luts')
+ abc9_ops -write_box <abc-temp-dir>/input.box
+ write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig
+ abc9_exe [options] -cwd <abc-temp-dir> [-lut <abc-temp-dir>/input.lut] -box <abc-temp-dir>/input.box
+ read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig
+ abc9_ops -reintegrate
+\end{lstlisting}
+
+\section{abc9\_exe -- use ABC9 for technology mapping}
+\label{cmd:abc9_exe}
+\begin{lstlisting}[numbers=left,frame=single]
+ abc9_exe [options]
+
+
+This pass uses the ABC tool [1] for technology mapping of the top module
+(according to the (* top *) attribute or if only one module is currently selected)
+to a target FPGA architecture.
+
+ -exe <command>
+ use the specified command instead of "<yosys-bindir>/yosys-abc" to execute ABC.
+ This can e.g. be used to call a specific version of ABC or a wrapper.
+
+ -script <file>
+ use the specified ABC script file instead of the default script.
+
+ if <file> starts with a plus sign (+), then the rest of the filename
+ string is interpreted as the command string to be passed to ABC. The
+ leading plus sign is removed and all commas (,) in the string are
+ replaced with blanks before the string is passed to ABC.
+
+ if no -script parameter is given, the following scripts are used:
+ &scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -v; &mfs
+
+ -fast
+ use different default scripts that are slightly faster (at the cost
+ of output quality):
+ &if {C} {W} {D} {R} -v
+
+ -D <picoseconds>
+ set delay target. the string {D} in the default scripts above is
+ replaced by this option when used, and an empty string otherwise
+ (indicating best possible delay).
+
+ -lut <width>
+ generate netlist using luts of (max) the specified width.
+
+ -lut <w1>:<w2>
+ generate netlist using luts of (max) the specified width <w2>. All
+ luts with width <= <w1> have constant cost. for luts larger than <w1>
+ the area cost doubles with each additional input bit. the delay cost
+ is still constant for all lut widths.
+
+ -lut <file>
+ pass this file with lut library to ABC.
+
+ -luts <cost1>,<cost2>,<cost3>,<sizeN>:<cost4-N>,..
+ generate netlist using luts. Use the specified costs for luts with 1,
+ 2, 3, .. inputs.
+
+ -showtmp
+ print the temp dir name in log. usually this is suppressed so that the
+ command output is identical across runs.
+
+ -box <file>
+ pass this file with box library to ABC.
+
+ -cwd <dir>
+ use this as the current working directory, inside which the 'input.xaig'
+ file is expected. temporary files will be created in this directory, and
+ the mapped result will be written to 'output.aig'.
+
+Note that this is a logic optimization pass within Yosys that is calling ABC
+internally. This is not going to "run ABC on your design". It will instead run
+ABC on logic snippets extracted from your design. You will not get any useful
+output when passing an ABC script that writes a file. Instead write your full
+design as BLIF file with write_blif and then load that into ABC externally if
you want to use ABC to convert your design into another format.
[1] http://www.eecs.berkeley.edu/~alanmi/abc/
\end{lstlisting}
+\section{abc9\_ops -- helper functions for ABC9}
+\label{cmd:abc9_ops}
+\begin{lstlisting}[numbers=left,frame=single]
+ abc9_ops [options] [selection]
+
+This pass contains a set of supporting operations for use during ABC technology
+mapping, and is expected to be called in conjunction with other operations from
+the `abc9' script pass. Only fully-selected modules are supported.
+
+ -check
+ check that the design is valid, e.g. (* abc9_box_id *) values are unique,
+ (* abc9_carry *) is only given for one input/output port, etc.
+
+ -prep_delays
+ insert `$__ABC9_DELAY' blackbox cells into the design to account for
+ certain required times.
+
+ -mark_scc
+ for an arbitrarily chosen cell in each unique SCC of each selected module
+ (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all
+ wires driven by this cell's outputs with a (* keep *) attribute in order
+ to break the SCC. this temporary attribute will be removed on -reintegrate.
+
+ -prep_xaiger
+ prepare the design for XAIGER output. this includes computing the
+ topological ordering of ABC9 boxes, as well as preparing the
+ '<module-name>$holes' module that contains the logic behaviour of ABC9
+ whiteboxes.
+
+ -dff
+ consider flop cells (those instantiating modules marked with (* abc9_flop *))
+ during -prep_{delays,xaiger,box}.
+
+ -prep_dff
+ compute the clock domain and initial value of each flop in the design.
+ process the '$holes' module to support clock-enable functionality.
+
+ -prep_lut <maxlut>
+ pre-compute the lut library by analysing all modules marked with
+ (* abc9_lut=<area> *).
+
+ -write_lut <dst>
+ write the pre-computed lut library to <dst>.
+
+ -prep_box
+ pre-compute the box library by analysing all modules marked with
+ (* abc9_box *).
+
+ -write_box <dst>
+ write the pre-computed box library to <dst>.
+
+ -reintegrate
+ for each selected module, re-intergrate the module '<module-name>$abc9'
+ by first recovering ABC9 boxes, and then stitching in the remaining primary
+ inputs and outputs.
+\end{lstlisting}
+
\section{add -- add objects to the design}
\label{cmd:add}
\begin{lstlisting}[numbers=left,frame=single]
@@ -189,6 +439,17 @@ than the object to be created.
Like 'add -input', but also connect the signal between instances of the
selected modules.
+
+
+ add {-assert|-assume|-live|-fair|-cover} <name1> [-if <name2>]
+
+Add an $assert, $assume, etc. cell connected to a wire named name1, with its
+enable signal optionally connected to a wire named name2 (default: 1'b1).
+
+
+ add -mod <name[s]>
+
+Add module[s] with the specified name[s].
\end{lstlisting}
\section{aigmap -- map logic to and-inverter-graph circuit}
@@ -201,6 +462,10 @@ $_NOT_ cells.
-nand
Enable creation of $_NAND_ cells
+
+ -select
+ Overwrite replaced cells in the current selection with new $_AND_,
+ $_NOT_, and $_NAND_, cells
\end{lstlisting}
\section{alumacc -- extract ALU and MACC cells}
@@ -212,7 +477,23 @@ This pass translates arithmetic operations like $add, $mul, $lt, etc. to $alu
and $macc cells.
\end{lstlisting}
-\section{assertpmux -- convert internal signals to module ports}
+\section{anlogic\_eqn -- Anlogic: Calculate equations for luts}
+\label{cmd:anlogic_eqn}
+\begin{lstlisting}[numbers=left,frame=single]
+ anlogic_eqn [selection]
+
+Calculate equations for luts since bitstream generator depends on it.
+\end{lstlisting}
+
+\section{anlogic\_fixcarry -- Anlogic: fix carry chain}
+\label{cmd:anlogic_fixcarry}
+\begin{lstlisting}[numbers=left,frame=single]
+ anlogic_fixcarry [options] [selection]
+
+Add Anlogic adders to fix carry chain if needed.
+\end{lstlisting}
+
+\section{assertpmux -- adds asserts for parallel muxes}
\label{cmd:assertpmux}
\begin{lstlisting}[numbers=left,frame=single]
assertpmux [options] [selection]
@@ -225,8 +506,8 @@ This command adds asserts to the design that assert that all parallel muxes
-always
usually the $pmux condition is only checked when the $pmux output
- is used be the mux tree it drives. this option will deactivate this
- additional constrained and check the $pmux condition always.
+ is used by the mux tree it drives. this option will deactivate this
+ additional constraint and check the $pmux condition always.
\end{lstlisting}
\section{async2sync -- convert async FF inputs to sync circuits}
@@ -242,7 +523,7 @@ a reset deasserts with the clock edge, then the FF output will still drive the
reset value in the next cycle regardless of the data-in value at the time of
the clock edge.
-Currently only $adff cells are supported by this pass.
+Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.
\end{lstlisting}
\section{attrmap -- renaming attributes}
@@ -250,7 +531,7 @@ Currently only $adff cells are supported by this pass.
\begin{lstlisting}[numbers=left,frame=single]
attrmap [options] [selection]
-This command renames attributes and/or mapps key/value pairs to
+This command renames attributes and/or maps key/value pairs to
other key/value pairs.
-tocase <name>
@@ -307,7 +588,16 @@ Move or copy attributes on wires to the cells driving them.
multiple times.
\end{lstlisting}
-\section{blackbox -- change type of cells in the design}
+\section{autoname -- automatically assign names to objects}
+\label{cmd:autoname}
+\begin{lstlisting}[numbers=left,frame=single]
+ autoname [selection]
+
+Assign auto-generated public names to objects with private names (the ones
+with $-prefix).
+\end{lstlisting}
+
+\section{blackbox -- convert modules into blackbox modules}
\label{cmd:blackbox}
\begin{lstlisting}[numbers=left,frame=single]
blackbox [options] [selection]
@@ -316,6 +606,58 @@ Convert modules into blackbox modules (remove contents and set the blackbox
module attribute).
\end{lstlisting}
+\section{bugpoint -- minimize testcases}
+\label{cmd:bugpoint}
+\begin{lstlisting}[numbers=left,frame=single]
+ bugpoint [options]
+
+This command minimizes testcases that crash Yosys. It removes an arbitrary part
+of the design and recursively invokes Yosys with a given script, repeating these
+steps while it can find a smaller design that still causes a crash. Once this
+command finishes, it replaces the current design with the smallest testcase it
+was able to produce.
+
+It is possible to specify the kinds of design part that will be removed. If none
+are specified, all parts of design will be removed.
+
+ -yosys <filename>
+ use this Yosys binary. if not specified, `yosys` is used.
+
+ -script <filename>
+ use this script to crash Yosys. required.
+
+ -grep <string>
+ only consider crashes that place this string in the log file.
+
+ -fast
+ run `proc_clean; clean -purge` after each minimization step. converges
+ faster, but produces larger testcases, and may fail to produce any
+ testcase at all if the crash is related to dangling wires.
+
+ -clean
+ run `proc_clean; clean -purge` before checking testcase and after
+ finishing. produces smaller and more useful testcases, but may fail to
+ produce any testcase at all if the crash is related to dangling wires.
+
+ -modules
+ try to remove modules.
+
+ -ports
+ try to remove module ports.
+
+ -cells
+ try to remove cells.
+
+ -connections
+ try to reconnect ports to 'x.
+
+ -assigns
+ try to remove process assigns from cases.
+
+ -updates
+ try to remove process updates from syncs.
+\end{lstlisting}
+
\section{cd -- a shortcut for 'select -module <name>'}
\label{cmd:cd}
\begin{lstlisting}[numbers=left,frame=single]
@@ -354,14 +696,24 @@ This pass identifies the following problems in the current design:
- used wires that do not have a driver
-When called with -noinit then this command also checks for wires which have
-the 'init' attribute set.
+Options:
+
+ -noinit
+ Also check for wires which have the 'init' attribute set.
-When called with -initdrv then this command also checks for wires which have
-the 'init' attribute set and aren't driven by a FF cell type.
+ -initdrv
+ Also check for wires that have the 'init' attribute set and are not
+ driven by an FF cell type.
-When called with -assert then the command will produce an error if any
-problems are found in the current design.
+ -mapped
+ Also check for internal cells that have not been mapped to cells of the
+ target architecture.
+
+ -allow-tbuf
+ Modify the -mapped behavior to still allow $_TBUF_ cells.
+
+ -assert
+ Produce a runtime error if any problems are found in the current design.
\end{lstlisting}
\section{chformal -- change formal constraints of the design}
@@ -370,7 +722,7 @@ problems are found in the current design.
chformal [types] [mode] [options] [selection]
Make changes to the formal constraints of the design. The [types] options
-the type of constraint to operate on. If none of the folling options is given,
+the type of constraint to operate on. If none of the following options are given,
the command will operate on all constraint types:
-assert $assert cells, representing assert(...) constraints
@@ -397,7 +749,7 @@ Exactly one of the following modes must be specified:
-assume2assert
-live2fair
-fair2live
- change the roles of cells as indicated. this options can be combined
+ change the roles of cells as indicated. these options can be combined
\end{lstlisting}
\section{chparam -- re-evaluate modules with new parameters}
@@ -452,6 +804,32 @@ implicit global clock. This is useful for formal verification of designs with
multiple clocks.
\end{lstlisting}
+\section{clkbufmap -- insert global buffers on clock networks}
+\label{cmd:clkbufmap}
+\begin{lstlisting}[numbers=left,frame=single]
+ clkbufmap [options] [selection]
+
+Inserts global buffers between nets connected to clock inputs and their drivers.
+
+In the absence of any selection, all wires without the 'clkbuf_inhibit'
+attribute will be considered for global buffer insertion.
+Alternatively, to consider all wires without the 'buffer_type' attribute set to
+'none' or 'bufr' one would specify:
+ 'w:* a:buffer_type=none a:buffer_type=bufr %u %d'
+as the selection.
+
+ -buf <celltype> <portname_out>:<portname_in>
+ Specifies the cell type to use for the global buffers
+ and its port names. The first port will be connected to
+ the clock network sinks, and the second will be connected
+ to the actual clock source. This option is required.
+
+ -inpad <celltype> <portname_out>:<portname_in>
+ If specified, a PAD cell of the given type is inserted on
+ clock nets that are also top module's inputs (in addition
+ to the global buffer).
+\end{lstlisting}
+
\section{connect -- create or remove connections}
\label{cmd:connect}
\begin{lstlisting}[numbers=left,frame=single]
@@ -483,6 +861,50 @@ be selected or an active module must be set using the 'cd' command.
This command does not operate on module with processes.
\end{lstlisting}
+\section{connect\_rpc -- connect to RPC frontend}
+\label{cmd:connect_rpc}
+\begin{lstlisting}[numbers=left,frame=single]
+ connect_rpc -exec <command> [args...]
+ connect_rpc -path <path>
+
+Load modules using an out-of-process frontend.
+
+ -exec <command> [args...]
+ run <command> with arguments [args...]. send requests on stdin, read
+ responses from stdout.
+
+ -path <path>
+ connect to Unix domain socket at <path>. (Unix)
+ connect to bidirectional byte-type named pipe at <path>. (Windows)
+
+A simple JSON-based, newline-delimited protocol is used for communicating with
+the frontend. Yosys requests data from the frontend by sending exactly 1 line
+of JSON. Frontend responds with data or error message by replying with exactly
+1 line of JSON as well.
+
+ -> {"method": "modules"}
+ <- {"modules": ["<module-name>", ...]}
+ <- {"error": "<error-message>"}
+ request for the list of modules that can be derived by this frontend.
+ the 'hierarchy' command will call back into this frontend if a cell
+ with type <module-name> is instantiated in the design.
+
+ -> {"method": "derive", "module": "<module-name">, "parameters": {
+ "<param-name>": {"type": "[unsigned|signed|string|real]",
+ "value": "<param-value>"}, ...}}
+ <- {"frontend": "[ilang|verilog|...]","source": "<source>"}}
+ <- {"error": "<error-message>"}
+ request for the module <module-name> to be derived for a specific set of
+ parameters. <param-name> starts with \ for named parameters, and with $
+ for unnamed parameters, which are numbered starting at 1.<param-value>
+ for integer parameters is always specified as a binary string of unlimited
+ precision. the <source> returned by the frontend is hygienically parsed
+ by a built-in Yosys <frontend>, allowing the RPC frontend to return any
+ convenient representation of the module. the derived module is cached,
+ so the response should be the same whenever the same set of parameters
+ is provided.
+\end{lstlisting}
+
\section{connwrappers -- match width of input-output port pairs}
\label{cmd:connwrappers}
\begin{lstlisting}[numbers=left,frame=single]
@@ -504,6 +926,14 @@ the driving cell.
The options -signed, -unsigned, and -port can be specified multiple times.
\end{lstlisting}
+\section{coolrunner2\_fixup -- insert necessary buffer cells for CoolRunner-II architecture}
+\label{cmd:coolrunner2_fixup}
+\begin{lstlisting}[numbers=left,frame=single]
+ coolrunner2_fixup [options] [selection]
+
+Insert necessary buffer cells for CoolRunner-II architecture.
+\end{lstlisting}
+
\section{coolrunner2\_sop -- break \$sop cells into ANDTERM/ORTERM cells}
\label{cmd:coolrunner2_sop}
\begin{lstlisting}[numbers=left,frame=single]
@@ -568,6 +998,26 @@ Hint: Use the following AWK command to consolidate Yosys coverage files:
Coverage counters are only available in Yosys for Linux.
\end{lstlisting}
+\section{cutpoint -- adds formal cut points to the design}
+\label{cmd:cutpoint}
+\begin{lstlisting}[numbers=left,frame=single]
+ cutpoint [options] [selection]
+
+This command adds formal cut points to the design.
+
+ -undef
+ set cupoint nets to undef (x). the default behavior is to create a
+ $anyseq cell and drive the cutpoint net from that
+\end{lstlisting}
+
+\section{debug -- run command with debug log messages enabled}
+\label{cmd:debug}
+\begin{lstlisting}[numbers=left,frame=single]
+ debug cmd
+
+Execute the specified command with debug log messages enabled
+\end{lstlisting}
+
\section{delete -- delete objects in the design}
\label{cmd:delete}
\begin{lstlisting}[numbers=left,frame=single]
@@ -614,6 +1064,11 @@ Save the current design under the given name and then clear the current design.
Push the current design to the stack and then clear the current design.
+ design -push-copy
+
+Push the current design to the stack without clearing the current design.
+
+
design -pop
Reset the current design and pop the last design from the stack.
@@ -649,6 +1104,14 @@ The Verilog front-end remembers defined macros and top-level declarations
between calls to 'read_verilog'. This command resets this memory.
\end{lstlisting}
+\section{determine\_init -- Determine the init value of cells}
+\label{cmd:determine_init}
+\begin{lstlisting}[numbers=left,frame=single]
+ determine_init [selection]
+
+Determine the init value of cells that doesn't allow unknown init value.
+\end{lstlisting}
+
\section{dff2dffe -- transform \$dff cells to \$dffe cells}
\label{cmd:dff2dffe}
\begin{lstlisting}[numbers=left,frame=single]
@@ -660,7 +1123,11 @@ $_DFF_P_, $_DFF_N_ and $_MUX_.
-unmap
operate in the opposite direction: replace $dffe cells with combinations
- of $dff and $mux cells. the options below are ignore in unmap mode.
+ of $dff and $mux cells. the options below are ignored in unmap mode.
+
+ -unmap-mince N
+ Same as -unmap but only unmap $dffe where the clock enable port
+ signal is used by less $dffe than the specified number
-direct <internal_gate_type> <external_gate_type>
map directly to external gate type. <internal_gate_type> can
@@ -686,6 +1153,10 @@ $_DFF_P_, $_DFF_N_ and $_MUX_.
Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before
dff2dffe for SR over CE priority.
+
+ -match-init
+ Disallow merging synchronous set/reset that has polarity opposite of the
+ output wire's init attribute (if any).
\end{lstlisting}
\section{dffinit -- set INIT param on FF cells}
@@ -704,6 +1175,16 @@ drives. (This is primarily used in FPGA flows.)
use the string values "high" and "low" to represent a single-bit
initial value of 1 or 0. (multi-bit values are not supported in this
mode.)
+
+ -strinit <string for high> <string for low>
+ use string values in the command line to represent a single-bit
+ initial value of 1 or 0. (multi-bit values are not supported in this
+ mode.)
+
+ -noreinit
+ fail if the FF cell has already a defined initial value set in other
+ passes and the initial value of the net it drives is not equal to
+ the already defined initial value.
\end{lstlisting}
\section{dfflibmap -- technology mapping of flip-flops}
@@ -722,15 +1203,6 @@ to the internal cell types that best match the cells found in the given
liberty file.
\end{lstlisting}
-\section{dffsr2dff -- convert DFFSR cells to simpler FF cell types}
-\label{cmd:dffsr2dff}
-\begin{lstlisting}[numbers=left,frame=single]
- dffsr2dff [options] [selection]
-
-This pass converts DFFSR cells ($dffsr, $_DFFSR_???_) and ADFF cells ($adff,
-$_DFF_???_) to simpler FF cell types when any of the set/reset inputs is unused.
-\end{lstlisting}
-
\section{dump -- print parts of the design in ilang format}
\label{cmd:dump}
\begin{lstlisting}[numbers=left,frame=single]
@@ -766,6 +1238,29 @@ Print all commands to log before executing them.
Do not print all commands to log before executing them. (default)
\end{lstlisting}
+\section{ecp5\_ffinit -- ECP5: handle FF init values}
+\label{cmd:ecp5_ffinit}
+\begin{lstlisting}[numbers=left,frame=single]
+ ecp5_ffinit [options] [selection]
+
+Remove init values for FF output signals when equal to reset value.
+If reset is not used, set the reset value to the init value, otherwise
+unmap out the reset (if not an async reset).
+\end{lstlisting}
+
+\section{ecp5\_gsr -- ECP5: handle GSR}
+\label{cmd:ecp5_gsr}
+\begin{lstlisting}[numbers=left,frame=single]
+ ecp5_gsr [options] [selection]
+
+Trim active low async resets connected to GSR and resolve GSR parameter,
+if a GSR or SGSR primitive is used in the design.
+
+If any cell has the GSR parameter set to "AUTO", this will be resolved
+to "ENABLED" if a GSR primitive is present and the (* nogsr *) attribute
+is not set, otherwise it will be resolved to "DISABLED".
+\end{lstlisting}
+
\section{edgetypes -- list all types of edges in selection}
\label{cmd:edgetypes}
\begin{lstlisting}[numbers=left,frame=single]
@@ -775,6 +1270,22 @@ This command lists all unique types of 'edges' found in the selection. An 'edge'
is a 4-tuple of source and sink cell type and port name.
\end{lstlisting}
+\section{efinix\_fixcarry -- Efinix: fix carry chain}
+\label{cmd:efinix_fixcarry}
+\begin{lstlisting}[numbers=left,frame=single]
+ efinix_fixcarry [options] [selection]
+
+Add Efinix adders to fix carry chain if needed.
+\end{lstlisting}
+
+\section{efinix\_gbuf -- Efinix: insert global clock buffers}
+\label{cmd:efinix_gbuf}
+\begin{lstlisting}[numbers=left,frame=single]
+ efinix_gbuf [options] [selection]
+
+Add Efinix global clock buffers to top module as needed.
+\end{lstlisting}
+
\section{equiv\_add -- add a \$equiv cell}
\label{cmd:equiv_add}
\begin{lstlisting}[numbers=left,frame=single]
@@ -872,6 +1383,65 @@ This creates a miter module for further analysis of the selected $equiv cells.
Create compare logic that handles undefs correctly
\end{lstlisting}
+\section{equiv\_opt -- prove equivalence for optimized circuit}
+\label{cmd:equiv_opt}
+\begin{lstlisting}[numbers=left,frame=single]
+ equiv_opt [options] [command]
+
+This command uses temporal induction to check circuit equivalence before and
+after an optimization pass.
+
+ -run <from_label>:<to_label>
+ only run the commands between the labels (see below). an empty
+ from label is synonymous to the start of the command list, and empty to
+ label is synonymous to the end of the command list.
+
+ -map <filename>
+ expand the modules in this file before proving equivalence. this is
+ useful for handling architecture-specific primitives.
+
+ -blacklist <file>
+ Do not match cells or signals that match the names in the file
+ (passed to equiv_make).
+
+ -assert
+ produce an error if the circuits are not equivalent.
+
+ -multiclock
+ run clk2fflogic before equivalence checking.
+
+ -async2sync
+ run async2sync before equivalence checking.
+
+ -undef
+ enable modelling of undef states during equiv_induct.
+
+The following commands are executed by this verification command:
+
+ run_pass:
+ hierarchy -auto-top
+ design -save preopt
+ [command]
+ design -stash postopt
+
+ prepare:
+ design -copy-from preopt -as gold A:top
+ design -copy-from postopt -as gate A:top
+
+ techmap: (only with -map)
+ techmap -wb -D EQUIV -autoproc -map <filename> ...
+
+ prove:
+ clk2fflogic (only with -multiclock)
+ async2sync (only with -async2sync)
+ equiv_make -blacklist <filename> ... gold gate equiv
+ equiv_induct [-undef] equiv
+ equiv_status [-assert] equiv
+
+ restore:
+ design -load preopt
+\end{lstlisting}
+
\section{equiv\_purge -- purge equivalence checking module}
\label{cmd:equiv_purge}
\begin{lstlisting}[numbers=left,frame=single]
@@ -984,6 +1554,37 @@ inputs.
then all output ports of the current module are used.
\end{lstlisting}
+\section{exec -- execute commands in the operating system shell}
+\label{cmd:exec}
+\begin{lstlisting}[numbers=left,frame=single]
+ exec [options] -- [command]
+
+Execute a command in the operating system shell. All supplied arguments are
+concatenated and passed as a command to popen(3). Whitespace is not guaranteed
+to be preserved, even if quoted. stdin and stderr are not connected, while stdout is
+logged unless the "-q" option is specified.
+
+
+ -q
+ Suppress stdout and stderr from subprocess
+
+ -expect-return <int>
+ Generate an error if popen() does not return specified value.
+ May only be specified once; the final specified value is controlling
+ if specified multiple times.
+
+ -expect-stdout <regex>
+ Generate an error if the specified regex does not match any line
+ in subprocess's stdout. May be specified multiple times.
+
+ -not-expect-stdout <regex>
+ Generate an error if the specified regex matches any line
+ in subprocess's stdout. May be specified multiple times.
+
+
+ Example: exec -q -expect-return 0 -- echo "bananapie" | grep "nana"
+\end{lstlisting}
+
\section{expose -- convert internal signals to module ports}
\label{cmd:expose}
\begin{lstlisting}[numbers=left,frame=single]
@@ -1117,7 +1718,16 @@ counter cells. Use a target-specific 'techmap' map file to convert those cells
to the actual target cells.
-maxwidth N
- Only extract counters up to N bits wide
+ Only extract counters up to N bits wide (default 64)
+
+ -minwidth N
+ Only extract counters at least N bits wide (default 2)
+
+ -allow_arst yes|no
+ Allow counters to have async reset (default yes)
+
+ -dir up|down|both
+ Look for up-counters, down-counters, or both (default down)
-pout X,Y,...
Only allow parallel output from the counter to the listed cell types
@@ -1165,10 +1775,30 @@ parts of the design to AND/OR/XOR cells, and run extract_reduce a second time.
cell will remain, driving its original loads.
\end{lstlisting}
+\section{extractinv -- extract explicit inverter cells for invertible cell pins}
+\label{cmd:extractinv}
+\begin{lstlisting}[numbers=left,frame=single]
+ extractinv [options] [selection]
+
+Searches the design for all cells with invertible pins controlled by a cell
+parameter (eg. IS_CLK_INVERTED on many Xilinx cells) and removes the parameter.
+If the parameter was set to 1, inserts an explicit inverter cell in front of
+the pin instead. Normally used for output to ISE, which does not support the
+inversion parameters.
+
+To mark a cell port as invertible, use (* invertible_pin = "param_name" *)
+on the wire in the blackbox module. The parameter value should have
+the same width as the port, and will be effectively XORed with it.
+
+ -inv <celltype> <portname_out>:<portname_in>
+ Specifies the cell type to use for the inverters and its port names.
+ This option is required.
+\end{lstlisting}
+
\section{flatten -- flatten design}
\label{cmd:flatten}
\begin{lstlisting}[numbers=left,frame=single]
- flatten [selection]
+ flatten [options] [selection]
This pass flattens the design by replacing cells by their implementation. This
pass is very similar to the 'techmap' pass. The only difference is that this
@@ -1176,6 +1806,105 @@ pass is using the current design as mapping library.
Cells and/or modules with the 'keep_hierarchy' attribute set will not be
flattened by this command.
+
+ -wb
+ Ignore the 'whitebox' attribute on cell implementations.
+\end{lstlisting}
+
+\section{flowmap -- pack LUTs with FlowMap}
+\label{cmd:flowmap}
+\begin{lstlisting}[numbers=left,frame=single]
+ flowmap [options] [selection]
+
+This pass uses the FlowMap technology mapping algorithm to pack logic gates
+into k-LUTs with optimal depth. It allows mapping any circuit elements that can
+be evaluated with the `eval` pass, including cells with multiple output ports
+and multi-bit input and output ports.
+
+ -maxlut k
+ perform technology mapping for a k-LUT architecture. if not specified,
+ defaults to 3.
+
+ -minlut n
+ only produce n-input or larger LUTs. if not specified, defaults to 1.
+
+ -cells <cell>[,<cell>,...]
+ map specified cells. if not specified, maps $_NOT_, $_AND_, $_OR_,
+ $_XOR_ and $_MUX_, which are the outputs of the `simplemap` pass.
+
+ -relax
+ perform depth relaxation and area minimization.
+
+ -r-alpha n, -r-beta n, -r-gamma n
+ parameters of depth relaxation heuristic potential function.
+ if not specified, alpha=8, beta=2, gamma=1.
+
+ -optarea n
+ optimize for area by trading off at most n logic levels for fewer LUTs.
+ n may be zero, to optimize for area without increasing depth.
+ implies -relax.
+
+ -debug
+ dump intermediate graphs.
+
+ -debug-relax
+ explain decisions performed during depth relaxation.
+\end{lstlisting}
+
+\section{fmcombine -- combine two instances of a cell into one}
+\label{cmd:fmcombine}
+\begin{lstlisting}[numbers=left,frame=single]
+ fmcombine [options] module_name gold_cell gate_cell
+
+This pass takes two cells, which are instances of the same module, and replaces
+them with one instance of a special 'combined' module, that effectively
+contains two copies of the original module, plus some formal properties.
+
+This is useful for formal test benches that check what differences in behavior
+a slight difference in input causes in a module.
+
+ -initeq
+ Insert assumptions that initially all FFs in both circuits have the
+ same initial values.
+
+ -anyeq
+ Do not duplicate $anyseq/$anyconst cells.
+
+ -fwd
+ Insert forward hint assumptions into the combined module.
+
+ -bwd
+ Insert backward hint assumptions into the combined module.
+ (Backward hints are logically equivalend to fordward hits, but
+ some solvers are faster with bwd hints, or even both -bwd and -fwd.)
+
+ -nop
+ Don't insert hint assumptions into the combined module.
+ (This should not provide any speedup over the original design, but
+ strangely sometimes it does.)
+
+If none of -fwd, -bwd, and -nop is given, then -fwd is used as default.
+\end{lstlisting}
+
+\section{fminit -- set init values/sequences for formal}
+\label{cmd:fminit}
+\begin{lstlisting}[numbers=left,frame=single]
+ fminit [options] <selection>
+
+This pass creates init constraints (for example for reset sequences) in a formal
+model.
+
+ -seq <signal> <sequence>
+ Set sequence using comma-separated list of values, use 'z for
+ unconstrained bits. The last value is used for the remainder of the
+ trace.
+
+ -set <signal> <value>
+ Add constant value constraint
+
+ -posedge <signal>
+ -negedge <signal>
+ Set clock for init sequences
\end{lstlisting}
\section{freduce -- perform functional reduction}
@@ -1393,15 +2122,16 @@ Merge GP_INV cells with GP_DFF* and GP_DLATCH* cells.
In parametric designs, a module might exists in several variations with
different parameter values. This pass looks at all modules in the current
design an re-runs the language frontends for the parametric modules as
-needed.
+needed. It also resolves assignments to wired logic data types (wand/wor),
+resolves positional module parameters, unroll array instances, and more.
-check
also check the design hierarchy. this generates an error when
an unknown module is used as cell type.
-simcheck
- like -check, but also thow an error if blackbox modules are
- instantiated, and throw an error if the design has no top module
+ like -check, but also throw an error if blackbox modules are
+ instantiated, and throw an error if the design has no top module.
-purge_lib
by default the hierarchy command will not remove library (blackbox)
@@ -1414,20 +2144,23 @@ needed.
-keep_positionals
per default this pass also converts positional arguments in cells
- to arguments using port names. this option disables this behavior.
+ to arguments using port names. This option disables this behavior.
-keep_portwidths
per default this pass adjusts the port width on cells that are
- module instances when the width does not match the module port. this
+ module instances when the width does not match the module port. This
option disables this behavior.
+ -nodefaults
+ do not resolve input port default values
+
-nokeep_asserts
per default this pass sets the "keep" attribute on all modules
- that directly or indirectly contain one or more $assert cells. this
- option disables this behavior.
+ that directly or indirectly contain one or more formal properties.
+ This option disables this behavior.
-top <module>
- use the specified top module to built a design hierarchy. modules
+ use the specified top module to build the design hierarchy. Modules
outside this tree (unused modules) are removed.
when the -top option is used, the 'top' attribute will be set on the
@@ -1437,6 +2170,12 @@ needed.
-auto-top
automatically determine the top of the design hierarchy and mark it.
+ -chparam name value
+ elaborate the top module using this parameter value. Modules on which
+ this parameter does not exist may cause a warning message to be output.
+ This option can be specified multiple times to override multiple
+ parameters. String values must be passed in double quotes (").
+
In -generate mode this pass generates blackbox modules for the given cell
types (wildcards supported). For this the design is searched for cells that
match the given types and then the given port declarations are used to
@@ -1483,6 +2222,33 @@ all commands executed in an interactive session, but not the commands
from executed scripts.
\end{lstlisting}
+\section{ice40\_braminit -- iCE40: perform SB\_RAM40\_4K initialization from file}
+\label{cmd:ice40_braminit}
+\begin{lstlisting}[numbers=left,frame=single]
+ ice40_braminit
+
+This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE
+parameter and converts it into the required INIT_x attributes
+\end{lstlisting}
+
+\section{ice40\_dsp -- iCE40: map multipliers}
+\label{cmd:ice40_dsp}
+\begin{lstlisting}[numbers=left,frame=single]
+ ice40_dsp [options] [selection]
+
+Map multipliers ($mul/SB_MAC16) and multiply-accumulate ($mul/SB_MAC16 + $add)
+cells into iCE40 DSP resources.
+Currently, only the 16x16 multiply mode is supported and not the 2 x 8x8 mode.
+
+Pack input registers (A, B, {C,D}; with optional hold), pipeline registers
+({F,J,K,G}, H), output registers (O -- full 32-bits or lower 16-bits only; with
+optional hold), and post-adder into into the SB_MAC16 resource.
+
+Multiply-accumulate operations using the post-adder with feedback on the {C,D}
+input will be folded into the DSP. In this scenario only, resetting the
+the accumulator to an arbitrary value can be inferred to use the {C,D} input.
+\end{lstlisting}
+
\section{ice40\_ffinit -- iCE40: handle FF init values}
\label{cmd:ice40_ffinit}
\begin{lstlisting}[numbers=left,frame=single]
@@ -1514,9 +2280,24 @@ This command executes the following script:
opt_rmdff
opt_clean
while <changed design>
+\end{lstlisting}
+
+\section{ice40\_wrapcarry -- iCE40: wrap carries}
+\label{cmd:ice40_wrapcarry}
+\begin{lstlisting}[numbers=left,frame=single]
+ ice40_wrapcarry [selection]
-When called with the option -unlut, this command will transform all already
-mapped SB_LUT4 cells back to logic.
+Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUT4s,
+into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology
+mapping.
+
+Attributes on both cells will have their names prefixed with 'SB_CARRY.' or
+'SB_LUT4.' and attached to the wrapping cell.
+A (* keep *) attribute on either cell will be logically OR-ed together.
+
+ -unwrap
+ unwrap $__ICE40_CARRY_WRAPPER cells back into SB_CARRYs and SB_LUT4s,
+ including restoring their attributes.
\end{lstlisting}
\section{insbuf -- insert buffer cells for connected wires}
@@ -1561,6 +2342,11 @@ the resulting cells to more sophisticated PAD cells.
of the tristate driver and the 2nd portname is the internal output
buffering the external signal.
+ -ignore <celltype> <portname>[:<portname>]*
+ Skips mapping inputs/outputs that are already connected to given
+ ports of the given cell. Can be used multiple times. This is in
+ addition to the cells specified as mapping targets.
+
-widthparam <param_name>
Use the specified parameter name to set the port width.
@@ -1588,6 +2374,10 @@ Write a JSON netlist of all selected objects.
-aig
also include AIG models for the different gate types
+ -compat-int
+ emit 32-bit or smaller fully-defined parameter values directly
+ as JSON numbers (for compatibility with old parsers)
+
See 'help write_json' for a description of the JSON format used.
\end{lstlisting}
@@ -1615,6 +2405,44 @@ logfiles.
do not append a newline
\end{lstlisting}
+\section{logger -- set logger properties}
+\label{cmd:logger}
+\begin{lstlisting}[numbers=left,frame=single]
+ logger [options]
+
+This command sets global logger properties, also available using command line
+options.
+
+ -[no]time
+ enable/disable display of timestamp in log output.
+
+ -[no]stderr
+ enable/disable logging errors to stderr.
+
+ -warn regex
+ print a warning for all log messages matching the regex.
+
+ -nowarn regex
+ if a warning message matches the regex, it is printed as regular
+ message instead.
+
+ -werror regex
+ if a warning message matches the regex, it is printed as error
+ message instead and the tool terminates with a nonzero return code.
+
+ -[no]debug
+ globally enable/disable debug log messages.
+
+ -experimental <feature>
+ do not print warnings for the specified experimental feature
+
+ -expect <type> <regex> <expected_count>
+ expect log,warning or error to appear. In case of error return code is 0.
+
+ -expect-no-warnings
+ gives error in case there is at least one warning that is not expected.
+\end{lstlisting}
+
\section{ls -- list modules or objects in modules}
\label{cmd:ls}
\begin{lstlisting}[numbers=left,frame=single]
@@ -1661,6 +2489,7 @@ is used then the $macc cell is mapped to $add, $sub, etc. cells instead.
This pass calls all the other memory_* passes in a useful order:
+ opt_mem
memory_dff [-nordff] (-memx implies -nordff)
opt_clean
memory_share
@@ -1683,8 +2512,13 @@ This pass converts the multi-port $mem memory cells into block ram instances.
The given rules file describes the available resources and how they should be
used.
-The rules file contains a set of block ram description and a sequence of match
-rules. A block ram description looks like this:
+The rules file contains configuration options, a set of block ram description
+and a sequence of match rules.
+
+The option 'attr_icase' configures how attribute values are matched. The value 0
+means case-sensitive, 1 means case-insensitive.
+
+A block ram description looks like this:
bram RAMB1024X32 # name of BRAM cell
init 1 # set to '1' if BRAM can be initialized
@@ -1745,6 +2579,13 @@ It is possible to match against the following values with min/max rules:
dcells ....... number of cells in 'data-direction'
cells ........ total number of cells (acells*dcells*dups)
+A match containing the command 'attribute' followed by a list of space
+separated 'name[=string_value]' values requires that the memory contains any
+one of the given attribute name and string values (where specified), or name
+and integer 1 value (if no string_value given, since Verilog will interpret
+'(* attr *)' as '(* attr=1 *)').
+A name prefixed with '!' indicates that the attribute must not exist.
+
The interface for the created bram instances is derived from the bram
description. Use 'techmap' to convert the created bram instances into
instances of the actual bram cells of your target architecture.
@@ -1788,10 +2629,22 @@ interface and yields a synchronous memory port.
\section{memory\_map -- translate multiport memories to basic cells}
\label{cmd:memory_map}
\begin{lstlisting}[numbers=left,frame=single]
- memory_map [selection]
+ memory_map [options] [selection]
This pass converts multiport memory cells as generated by the memory_collect
pass to word-wide DFFs and address decoders.
+
+ -attr !<name>
+ do not map memories that have attribute <name> set.
+
+ -attr <name>[=<value>]
+ for memories that have attribute <name> set, only map them if its value
+ is a string <value> (if specified), or an integer 1 (otherwise). if this
+ option is specified multiple times, map the memory if the attribute is
+ to any of the values.
+
+ -iattr
+ for -attr, ignore case of <value>.
\end{lstlisting}
\section{memory\_memx -- emulate vlog sim behavior for mem ports}
@@ -1872,7 +2725,7 @@ detected.
also create an 'assert' cell that checks if trigger is always low.
-flatten
- call 'flatten; opt_expr -keepdc -undriven;;' on the miter circuit.
+ call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.
miter -assert [options] module [miter_name]
@@ -1886,7 +2739,70 @@ module is modified.
keep module output ports.
-flatten
- call 'flatten; opt_expr -keepdc -undriven;;' on the miter circuit.
+ call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.
+\end{lstlisting}
+
+\section{mutate -- generate or apply design mutations}
+\label{cmd:mutate}
+\begin{lstlisting}[numbers=left,frame=single]
+ mutate -list N [options] [selection]
+
+Create a list of N mutations using an even sampling.
+
+ -o filename
+ Write list to this file instead of console output
+
+ -s filename
+ Write a list of all src tags found in the design to the specified file
+
+ -seed N
+ RNG seed for selecting mutations
+
+ -none
+ Include a "none" mutation in the output
+
+ -ctrl name width value
+ Add -ctrl options to the output. Use 'value' for first mutation, then
+ simply count up from there.
+
+ -mode name
+ -module name
+ -cell name
+ -port name
+ -portbit int
+ -ctrlbit int
+ -wire name
+ -wirebit int
+ -src string
+ Filter list of mutation candidates to those matching
+ the given parameters.
+
+ -cfg option int
+ Set a configuration option. Options available:
+ weight_pq_w weight_pq_b weight_pq_c weight_pq_s
+ weight_pq_mw weight_pq_mb weight_pq_mc weight_pq_ms
+ weight_cover pick_cover_prcnt
+
+
+ mutate -mode MODE [options]
+
+Apply the given mutation.
+
+ -ctrl name width value
+ Add a control signal with the given name and width. The mutation is
+ activated if the control signal equals the given value.
+
+ -module name
+ -cell name
+ -port name
+ -portbit int
+ -ctrlbit int
+ Mutation parameters, as generated by 'mutate -list N'.
+
+ -wire name
+ -wirebit int
+ -src string
+ Ignored. (They are generated by -list for documentation purposes.)
\end{lstlisting}
\section{muxcover -- cover trees of MUX cells with wider MUXes}
@@ -1896,14 +2812,43 @@ module is modified.
Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells
- -mux4, -mux8, -mux16
- Use the specified types of MUXes. If none of those options are used,
- the effect is the same as if all of them where used.
+ -mux4[=cost], -mux8[=cost], -mux16[=cost]
+ Cover $_MUX_ trees using the specified types of MUXes (with optional
+ integer costs). If none of these options are given, the effect is the
+ same as if all of them are.
+ Default costs: $_MUX4_ = 220, $_MUX8_ = 460,
+ $_MUX16_ = 940
+
+ -mux2=cost
+ Use the specified cost for $_MUX_ cells when making covering decisions.
+ Default cost: $_MUX_ = 100
+
+ -dmux=cost
+ Use the specified cost for $_MUX_ cells used in decoders.
+ Default cost: 90
-nodecode
Do not insert decoder logic. This reduces the number of possible
substitutions, but guarantees that the resulting circuit is not
less efficient than the original circuit.
+
+ -nopartial
+ Do not consider mappings that use $_MUX<N>_ to select from less
+ than <N> different signals.
+\end{lstlisting}
+
+\section{muxpack -- \$mux/\$pmux cascades to \$pmux}
+\label{cmd:muxpack}
+\begin{lstlisting}[numbers=left,frame=single]
+ muxpack [selection]
+
+This pass converts cascaded chains of $pmux cells (e.g. those create from case
+constructs) and $mux cells (e.g. those created by if-else constructs) into
+$pmux cells.
+
+This optimisation is conservative --- it will only pack $mux or $pmux cells
+whose select lines are driven by '$eq' cells with other such cells if it can be
+certain that their select inputs are mutually exclusive.
\end{lstlisting}
\section{nlutmap -- map to LUTs of different sizes}
@@ -1925,6 +2870,17 @@ Excess logic that does not fit into the specified LUTs is mapped back
to generic logic gates ($_AND_, etc.).
\end{lstlisting}
+\section{onehot -- optimize \$eq cells for onehot signals}
+\label{cmd:onehot}
+\begin{lstlisting}[numbers=left,frame=single]
+ onehot [options] [selection]
+
+This pass optimizes $eq cells that compare one-hot signals against constants
+
+ -v, -vv
+ verbose output
+\end{lstlisting}
+
\section{opt -- perform simple optimizations}
\label{cmd:opt}
\begin{lstlisting}[numbers=left,frame=single]
@@ -1941,7 +2897,8 @@ passes in the following order:
opt_muxtree
opt_reduce [-fine] [-full]
opt_merge [-share_all]
- opt_rmdff [-keepdc]
+ opt_share (-full only)
+ opt_rmdff [-keepdc] [-sat]
opt_clean [-purge]
opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]
while <changed design>
@@ -1951,7 +2908,7 @@ When called with -fast the following script is used instead:
do
opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]
opt_merge [-share_all]
- opt_rmdff [-keepdc]
+ opt_rmdff [-keepdc] [-sat]
opt_clean [-purge]
while <changed design in opt_rmdff>
@@ -1990,7 +2947,7 @@ overall gate count of the circuit
opt_expr [options] [selection]
This pass performs const folding on internal cell types with constant inputs.
-It also performs some simple expression rewritring.
+It also performs some simple expression rewriting.
-mux_undef
remove 'undef' inputs from $mux, $pmux and $_MUX_ cells
@@ -2017,6 +2974,47 @@ It also performs some simple expression rewritring.
replaced by 'a'. the -keepdc option disables all such optimizations.
\end{lstlisting}
+\section{opt\_lut -- optimize LUT cells}
+\label{cmd:opt_lut}
+\begin{lstlisting}[numbers=left,frame=single]
+ opt_lut [options] [selection]
+
+This pass combines cascaded $lut cells with unused inputs.
+
+ -dlogic <type>:<cell-port>=<LUT-input>[:<cell-port>=<LUT-input>...]
+ preserve connections to dedicated logic cell <type> that has ports
+ <cell-port> connected to LUT inputs <LUT-input>. this includes
+ the case where both LUT and dedicated logic input are connected to
+ the same constant.
+
+ -limit N
+ only perform the first N combines, then stop. useful for debugging.
+\end{lstlisting}
+
+\section{opt\_lut\_ins -- discard unused LUT inputs}
+\label{cmd:opt_lut_ins}
+\begin{lstlisting}[numbers=left,frame=single]
+ opt_lut_ins [options] [selection]
+
+This pass removes unused inputs from LUT cells (that is, inputs that can not
+influence the output signal given this LUT's value). While such LUTs cannot
+be directly emitted by ABC, they can be a result of various post-ABC
+transformations, such as mapping wide LUTs (not all sub-LUTs will use the
+full set of inputs) or optimizations such as xilinx_dffopt.
+
+ -tech <technology>
+ Instead of generic $lut cells, operate on LUT cells specific
+ to the given technology. Valid values are: xilinx, ecp5, gowin.
+\end{lstlisting}
+
+\section{opt\_mem -- optimize memories}
+\label{cmd:opt_mem}
+\begin{lstlisting}[numbers=left,frame=single]
+ opt_mem [options] [selection]
+
+This pass performs various optimizations on memories in the design.
+\end{lstlisting}
+
\section{opt\_merge -- consolidate identical cells}
\label{cmd:opt_merge}
\begin{lstlisting}[numbers=left,frame=single]
@@ -2067,10 +3065,65 @@ input with the original control signals OR'ed together.
\section{opt\_rmdff -- remove DFFs with constant inputs}
\label{cmd:opt_rmdff}
\begin{lstlisting}[numbers=left,frame=single]
- opt_rmdff [-keepdc] [selection]
+ opt_rmdff [-keepdc] [-sat] [selection]
This pass identifies flip-flops with constant inputs and replaces them with
a constant driver.
+
+ -sat
+ additionally invoke SAT solver to detect and remove flip-flops (with
+ non-constant inputs) that can also be replaced with a constant driver
+\end{lstlisting}
+
+\section{opt\_share -- merge mutually exclusive cells of the same type that share an input signal}
+\label{cmd:opt_share}
+\begin{lstlisting}[numbers=left,frame=single]
+ opt_share [selection]
+
+This pass identifies mutually exclusive cells of the same type that:
+ (a) share an input signal,
+ (b) drive the same $mux, $_MUX_, or $pmux multiplexing cell,
+
+allowing the cell to be merged and the multiplexer to be moved from
+multiplexing its output to multiplexing the non-shared input signals.
+\end{lstlisting}
+
+\section{paramap -- renaming cell parameters}
+\label{cmd:paramap}
+\begin{lstlisting}[numbers=left,frame=single]
+ paramap [options] [selection]
+
+This command renames cell parameters and/or maps key/value pairs to
+other key/value pairs.
+
+ -tocase <name>
+ Match attribute names case-insensitively and set it to the specified
+ name.
+
+ -rename <old_name> <new_name>
+ Rename attributes as specified
+
+ -map <old_name>=<old_value> <new_name>=<new_value>
+ Map key/value pairs as indicated.
+
+ -imap <old_name>=<old_value> <new_name>=<new_value>
+ Like -map, but use case-insensitive match for <old_value> when
+ it is a string value.
+
+ -remove <name>=<value>
+ Remove attributes matching this pattern.
+
+For example, mapping Diamond-style ECP5 "init" attributes to Yosys-style:
+
+ paramap -tocase INIT t:LUT4
+\end{lstlisting}
+
+\section{peepopt -- collection of peephole optimizers}
+\label{cmd:peepopt}
+\begin{lstlisting}[numbers=left,frame=single]
+ peepopt [options] [selection]
+
+This pass applies a collection of peephole optimizers to the current design.
\end{lstlisting}
\section{plugin -- load and list loaded plugins}
@@ -2090,12 +3143,51 @@ Load and list loaded plugins.
List loaded plugins
\end{lstlisting}
+\section{pmux2shiftx -- transform \$pmux cells to \$shiftx cells}
+\label{cmd:pmux2shiftx}
+\begin{lstlisting}[numbers=left,frame=single]
+ pmux2shiftx [options] [selection]
+
+This pass transforms $pmux cells to $shiftx cells.
+
+ -v, -vv
+ verbose output
+
+ -min_density <percentage>
+ specifies the minimum density for the shifter
+ default: 50
+
+ -min_choices <int>
+ specified the minimum number of choices for a control signal
+ default: 3
+
+ -onehot ignore|pmux|shiftx
+ select strategy for one-hot encoded control signals
+ default: pmux
+
+ -norange
+ disable $sub inference for "range decoders"
+\end{lstlisting}
+
\section{pmuxtree -- transform \$pmux cells to trees of \$mux cells}
\label{cmd:pmuxtree}
\begin{lstlisting}[numbers=left,frame=single]
- pmuxtree [options] [selection]
+ pmuxtree [selection]
+
+This pass transforms $pmux cells to trees of $mux cells.
+\end{lstlisting}
+
+\section{portlist -- list (top-level) ports}
+\label{cmd:portlist}
+\begin{lstlisting}[numbers=left,frame=single]
+ portlist [options] [selection]
+
+This command lists all module ports found in the selected modules.
-This pass transforms $pmux cells to a trees of $mux cells.
+If no selection is provided then it lists the ports on the top module.
+
+ -m
+ print verilog blackbox module definitions instead of port lists
\end{lstlisting}
\section{prep -- generic synthesis script}
@@ -2153,7 +3245,7 @@ The following commands are executed by this synthesis command:
opt_clean
check
opt -keepdc
- wreduce [-memx]
+ wreduce -keepdc [-memx]
memory_dff [-nordff]
memory_memx (if -memx)
opt_clean
@@ -2174,6 +3266,7 @@ This pass calls all the other proc_* passes in the most common order.
proc_clean
proc_rmdead
+ proc_prune
proc_init
proc_arst
proc_mux
@@ -2214,7 +3307,10 @@ flip-flop cells with asynchronous resets.
\section{proc\_clean -- remove empty parts of processes}
\label{cmd:proc_clean}
\begin{lstlisting}[numbers=left,frame=single]
- proc_clean [selection]
+ proc_clean [options] [selection]
+
+ -quiet
+ do not print any messages.
This pass removes empty parts of processes and ultimately removes a process
if it contains only empty structures.
@@ -2261,6 +3357,15 @@ and case statements) to trees of multiplexer cells.
'case' expressions and 'if' conditions.
\end{lstlisting}
+\section{proc\_prune -- remove redundant assignments}
+\label{cmd:proc_prune}
+\begin{lstlisting}[numbers=left,frame=single]
+ proc_prune [selection]
+
+This pass identifies assignments in processes that are always overwritten by
+a later assignment to the same signal and removes them.
+\end{lstlisting}
+
\section{proc\_rmdead -- eliminate dead trees in decision trees}
\label{cmd:proc_rmdead}
\begin{lstlisting}[numbers=left,frame=single]
@@ -2328,12 +3433,45 @@ Unset global Verilog/SystemVerilog defines.
read -incdir <directory>
Add directory to global Verilog/SystemVerilog include directories.
+
+
+ read -verific
+ read -noverific
+
+Subsequent calls to 'read' will either use or not use Verific. Calling 'read'
+with -verific will result in an error on Yosys binaries that are built without
+Verific support. The default is to use Verific if it is available.
+\end{lstlisting}
+
+\section{read\_aiger -- read AIGER file}
+\label{cmd:read_aiger}
+\begin{lstlisting}[numbers=left,frame=single]
+ read_aiger [options] [filename]
+
+Load module from an AIGER file into the current design.
+
+ -module_name <module_name>
+ name of module to be created (default: <filename>)
+
+ -clk_name <wire_name>
+ if specified, AIGER latches to be transformed into $_DFF_P_ cells
+ clocked by wire of this name. otherwise, $_FF_ cells will be used
+
+ -map <filename>
+ read file with port and latch symbols
+
+ -wideports
+ merge ports that match the pattern 'name[int]' into a single
+ multi-bit port 'name'
+
+ -xaiger
+ read XAIGER extensions
\end{lstlisting}
\section{read\_blif -- read BLIF file}
\label{cmd:read_blif}
\begin{lstlisting}[numbers=left,frame=single]
- read_blif [filename]
+ read_blif [options] [filename]
Load modules from a BLIF file into the current design.
@@ -2352,6 +3490,17 @@ Load modules from a BLIF file into the current design.
Load modules from an ilang file to the current design. (ilang is a text
representation of a design in yosys's internal format.)
+
+ -nooverwrite
+ ignore re-definitions of modules. (the default behavior is to
+ create an error message if the existing module is not a blackbox
+ module, and overwrite the existing module if it is a blackbox module.)
+
+ -overwrite
+ overwrite existing modules with the same name
+
+ -lib
+ only create empty blackbox modules
\end{lstlisting}
\section{read\_json -- read JSON file}
@@ -2411,12 +3560,24 @@ Verilog-2005 is supported.
enable support for SystemVerilog assertions and some Yosys extensions
replace the implicit -D SYNTHESIS with -D FORMAL
+ -noassert
+ ignore assert() statements
+
+ -noassume
+ ignore assume() statements
+
-norestrict
- ignore restrict() assertions
+ ignore restrict() statements
-assume-asserts
treat all assert() statements like assume() statements
+ -assert-assumes
+ treat all assume() statements like assert() statements
+
+ -debug
+ alias for -dump_ast1 -dump_ast2 -dump_vlog1 -dump_vlog2 -yydebug
+
-dump_ast1
dump abstract syntax tree (before simplification)
@@ -2426,7 +3587,10 @@ Verilog-2005 is supported.
-no_dump_ptr
do not include hex memory addresses in dump (easier to diff dumps)
- -dump_vlog
+ -dump_vlog1
+ dump ast as Verilog code (before simplification)
+
+ -dump_vlog2
dump ast as Verilog code (after simplification)
-dump_rtlil
@@ -2475,8 +3639,21 @@ Verilog-2005 is supported.
-nodpi
disable DPI-C support
+ -noblackbox
+ do not automatically add a (* blackbox *) attribute to an
+ empty module.
+
-lib
only create empty blackbox modules. This implies -DBLACKBOX.
+ modules with the (* whitebox *) attribute will be preserved.
+ (* lib_whitebox *) will be treated like (* whitebox *).
+
+ -nowb
+ delete (* whitebox *) and (* lib_whitebox *) attributes from
+ all modules.
+
+ -specify
+ parse and import specify blocks
-noopt
don't perform basic optimizations (such as const folding) in the
@@ -2485,6 +3662,9 @@ Verilog-2005 is supported.
-icells
interpret cell types starting with '$' as internal cell types
+ -pwires
+ add a wire for each module parameter
+
-nooverwrite
ignore re-definitions of modules. (the default behavior is to
create an error message if the existing module is not a black box
@@ -2537,6 +3717,25 @@ Rename the specified object. Note that selection patterns are not supported
by this command.
+
+ rename -output old_name new_name
+
+Like above, but also make the wire an output. This will fail if the object is
+not a wire.
+
+
+ rename -src [selection]
+
+Assign names auto-generated from the src attribute to all selected wires and
+cells with private names.
+
+
+ rename -wire [selection]
+
+Assign auto-generated names based on the wires they drive to all selected
+cells with private names. Ignores cells driving privatly named wires.
+
+
rename -enumerate [-pattern <pattern>] [selection]
Assign short auto-generated names to all selected wires and cells with private
@@ -2544,11 +3743,13 @@ names. The -pattern option can be used to set the pattern for the new names.
The character % in the pattern is replaced with a integer number. The default
pattern is '_%_'.
+
rename -hide [selection]
Assign private names (the ones with $-prefix) to all selected wires and cells
with public names. This ignores all selected ports.
+
rename -top new_name
Rename top module.
@@ -2778,20 +3979,61 @@ design.
that are part of a found logic loop
\end{lstlisting}
-\section{script -- execute commands from script file}
+\section{scratchpad -- get/set values in the scratchpad}
+\label{cmd:scratchpad}
+\begin{lstlisting}[numbers=left,frame=single]
+ scratchpad [options]
+
+This pass allows to read and modify values from the scratchpad of the current
+design. Options:
+
+ -get <identifier>
+ print the value saved in the scratchpad under the given identifier.
+
+ -set <identifier> <value>
+ save the given value in the scratchpad under the given identifier.
+
+ -unset <identifier>
+ remove the entry for the given identifier from the scratchpad.
+
+ -copy <identifier_from> <identifier_to>
+ copy the value of the first identifier to the second identifier.
+
+ -assert <identifier> <value>
+ assert that the entry for the given identifier is set to the given value.
+
+ -assert-set <identifier>
+ assert that the entry for the given identifier exists.
+
+ -assert-unset <identifier>
+ assert that the entry for the given identifier does not exist.
+
+The identifier may not contain whitespace. By convention, it is usually prefixed
+by the name of the pass that uses it, e.g. 'opt.did_something'. If the value
+contains whitespace, it must be enclosed in double quotes.
+\end{lstlisting}
+
+\section{script -- execute commands from file or wire}
\label{cmd:script}
\begin{lstlisting}[numbers=left,frame=single]
script <filename> [<from_label>:<to_label>]
+ script -scriptwire [selection]
-This command executes the yosys commands in the specified file.
+This command executes the yosys commands in the specified file (default
+behaviour), or commands embedded in the constant text value connected to the
+selected wires.
-The 2nd argument can be used to only execute the section of the
-file between the specified labels. An empty from label is synonymous
-for the beginning of the file and an empty to label is synonymous
-for the end of the file.
+In the default (file) case, the 2nd argument can be used to only execute the
+section of the file between the specified labels. An empty from label is
+synonymous with the beginning of the file and an empty to label is synonymous
+with the end of the file.
If only one label is specified (without ':') then only the block
marked with that label (until the next label) is executed.
+
+In "-scriptwire" mode, the commands on the selected wire(s) will be executed
+in the scope of (and thus, relative to) the wires' owning module(s). This
+'-module' mode can be exited by using the 'cd' command.
\end{lstlisting}
\section{select -- modify and view the list of selected objects}
@@ -2807,7 +4049,7 @@ of the design to operate on. This command can be used to modify and view this
list of selected objects.
Note that many commands support an optional [selection] argument that can be
-used to YS_OVERRIDE the global selection for the command. The syntax of this
+used to override the global selection for the command. The syntax of this
optional argument is identical to the syntax of the <selection> argument
described here.
@@ -2897,6 +4139,10 @@ matching module names, or one of the following:
all modules with an attribute matching the given pattern
in addition to = also <, <=, >=, and > are supported
+ N:<pattern>
+ all modules with a name matching the given pattern
+ (i.e. 'N:' is optional as it is the default matching rule)
+
An <obj_pattern> can be an object name, wildcard expression, or one of
the following:
@@ -3062,11 +4308,25 @@ This command replaces undef (x) constants with defined (0/1) constants.
replace with $anyconst drivers (for formal)
-random <seed>
- replace with random bits using the specified integer als seed
+ replace with random bits using the specified integer as seed
value for the random number generator.
-init
also create/update init values for flip-flops
+
+ -params
+ replace undef in cell parameters
+\end{lstlisting}
+
+\section{sf2\_iobs -- SF2: insert IO buffers}
+\label{cmd:sf2_iobs}
+\begin{lstlisting}[numbers=left,frame=single]
+ sf2_iobs [options] [selection]
+
+Add SF2 I/O buffers and global buffers to top module as needed.
+
+ -clkbuf
+ Insert PAD->global_net clock buffers
\end{lstlisting}
\section{share -- perform sat-based resource sharing}
@@ -3182,7 +4442,7 @@ to a graphics file (usually SVG or PostScript).
assigned to each unique value of this attribute.
-width
- annotate busses with a label indicating the width of the bus.
+ annotate buses with a label indicating the width of the bus.
-signed
mark ports (A, B) that are declared as signed (using the [AB]_SIGNED
@@ -3204,6 +4464,10 @@ to a graphics file (usually SVG or PostScript).
-notitle
do not add the module name as graph title to the dot file
+ -nobg
+ don't run viewer in the background, IE wait for the viewer tool to
+ exit before returning
+
When no <format> is specified, 'dot' is used. When no <format> and <viewer> is
specified, 'xdot' is used to display the schematic (POSIX systems only).
@@ -3404,6 +4668,10 @@ design.
-liberty <liberty_file>
use cell area information from the provided liberty file
+ -tech <technology>
+ print area estemate for the specified technology. Currently supported
+ values for <technology>: xilinx, cmos
+
-width
annotate internal cell types with their word width.
e.g. $add_8 for an 8 bit wide $add cell.
@@ -3412,7 +4680,7 @@ design.
\section{submod -- moving part of a module to a new submodule}
\label{cmd:submod}
\begin{lstlisting}[numbers=left,frame=single]
- submod [-copy] [selection]
+ submod [options] [selection]
This pass identifies all cells with the 'submod' attribute and moves them to
a newly created module. The value of the attribute is used as name for the
@@ -3424,16 +4692,29 @@ be useful for analyzing or reverse-engineering a design.
This pass only operates on completely selected modules with no processes
or memories.
+ -copy
+ by default the cells are 'moved' from the source module and the source
+ module will use an instance of the new module after this command is
+ finished. call with -copy to not modify the source module.
+
+ -name <name>
+ don't use the 'submod' attribute but instead use the selection. only
+ objects from one module might be selected. the value of the -name option
+ is used as the value of the 'submod' attribute instead.
- submod -name <name> [-copy] [selection]
+ -hidden
+ instead of creating submodule ports with public names, create ports with
+ private names so that a subsequent 'flatten; clean' call will restore the
+ original module with original public names.
+\end{lstlisting}
-As above, but don't use the 'submod' attribute but instead use the selection.
-Only objects from one module might be selected. The value of the -name option
-is used as the value of the 'submod' attribute above.
+\section{supercover -- add hi/lo cover cells for each wire bit}
+\label{cmd:supercover}
+\begin{lstlisting}[numbers=left,frame=single]
+ supercover [options] [selection]
-By default the cells are 'moved' from the source module and the source module
-will use an instance of the new module after this command is finished. Call
-with -copy to not modify the source module.
+This command adds two cover cells for each bit of each selected wire, one
+checking for a hi signal level and one checking for lo level.
\end{lstlisting}
\section{synth -- generic synthesis script}
@@ -3457,6 +4738,9 @@ on partly selected designs.
-encfile <file>
passed to 'fsm_recode' via 'fsm'
+ -lut <k>
+ perform synthesis for a k-LUT architecture.
+
-nofsm
do not run FSM optimization
@@ -3478,6 +4762,12 @@ on partly selected designs.
from label is synonymous to 'begin', and empty to label is
synonymous to the end of the command list.
+ -abc9
+ use new ABC9 flow (EXPERIMENTAL)
+
+ -flowmap
+ use FlowMap LUT techmapping instead of ABC
+
The following commands are executed by this synthesis command:
@@ -3486,16 +4776,19 @@ The following commands are executed by this synthesis command:
coarse:
proc
- flatten (if -flatten)
+ flatten (if -flatten)
opt_expr
opt_clean
check
opt
wreduce
- alumacc
- share
+ peepopt
+ opt_clean
+ techmap -map +/cmp2lut.v -map +/cmp2lcu.v (if -lut)
+ alumacc (unless -noalumacc)
+ share (unless -noshare)
opt
- fsm
+ fsm (unless -nofsm)
opt -fast
memory -nomap
opt_clean
@@ -3505,9 +4798,13 @@ The following commands are executed by this synthesis command:
memory_map
opt -full
techmap
+ techmap -map +/gate2lut.v (if -noabc and -lut)
+ clean; opt_lut (if -noabc and -lut)
+ flowmap -maxlut K (if -flowmap and -lut)
opt -fast
- abc -fast
- opt -fast
+ abc -fast (unless -noabc, unless -lut)
+ abc -fast -lut k (unless -noabc, if -lut)
+ opt -fast (unless -noabc)
check:
hierarchy -check
@@ -3538,7 +4835,7 @@ This command runs synthesis for Achronix Speedster eFPGAs. This work is still ex
do not flatten design before synthesis
-retime
- run 'abc' with -dff option
+ run 'abc' with '-dff -D 1' options
The following commands are executed by this synthesis command:
@@ -3560,14 +4857,13 @@ The following commands are executed by this synthesis command:
opt -fast -mux_undef -undriven -fine -full
memory_map
opt -undriven -fine
- dffsr2dff
dff2dffe -direct-match $_DFF_*
opt -fine
techmap -map +/techmap.v
opt -full
clean -purge
setundef -undriven -zero
- abc -markgroups -dff (only if -retime)
+ abc -markgroups -dff -D 1 (only if -retime)
map_luts:
abc -lut 4
@@ -3587,6 +4883,99 @@ The following commands are executed by this synthesis command:
write_verilog -nodec -attr2comment -defparam -renameprefix syn_ <file-name>
\end{lstlisting}
+\section{synth\_anlogic -- synthesis for Anlogic FPGAs}
+\label{cmd:synth_anlogic}
+\begin{lstlisting}[numbers=left,frame=single]
+ synth_anlogic [options]
+
+This command runs synthesis for Anlogic FPGAs.
+
+ -top <module>
+ use the specified module as top module
+
+ -edif <file>
+ write the design to the specified EDIF file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -json <file>
+ write the design to the specified JSON file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -run <from_label>:<to_label>
+ only run the commands between the labels (see below). an empty
+ from label is synonymous to 'begin', and empty to label is
+ synonymous to the end of the command list.
+
+ -noflatten
+ do not flatten design before synthesis
+
+ -retime
+ run 'abc' with '-dff -D 1' options
+
+ -nolutram
+ do not use EG_LOGIC_DRAM16X4 cells in output netlist
+
+
+The following commands are executed by this synthesis command:
+
+ begin:
+ read_verilog -lib +/anlogic/cells_sim.v +/anlogic/eagle_bb.v
+ hierarchy -check -top <top>
+
+ flatten: (unless -noflatten)
+ proc
+ flatten
+ tribuf -logic
+ deminout
+
+ coarse:
+ synth -run coarse
+
+ map_lutram: (skip if -nolutram)
+ memory_bram -rules +/anlogic/lutrams.txt
+ techmap -map +/anlogic/lutrams_map.v
+ setundef -zero -params t:EG_LOGIC_DRAM16X4
+
+ map_ffram:
+ opt -fast -mux_undef -undriven -fine
+ memory_map
+ opt -undriven -fine
+
+ map_gates:
+ techmap -map +/techmap.v -map +/anlogic/arith_map.v
+ opt -fast
+ abc -dff -D 1 (only if -retime)
+
+ map_ffs:
+ techmap -D NO_LUT -map +/anlogic/cells_map.v
+ dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit
+ opt_expr -mux_undef
+ simplemap
+
+ map_luts:
+ abc -lut 4:6
+ clean
+
+ map_cells:
+ techmap -map +/anlogic/cells_map.v
+ clean
+
+ map_anlogic:
+ anlogic_fixcarry
+ anlogic_eqn
+
+ check:
+ hierarchy -check
+ stat
+ check -noinit
+
+ edif:
+ write_edif <file-name>
+
+ json:
+ write_json <file-name>
+\end{lstlisting}
+
\section{synth\_coolrunner2 -- synthesis for Xilinx Coolrunner-II CPLDs}
\label{cmd:synth_coolrunner2}
\begin{lstlisting}[numbers=left,frame=single]
@@ -3612,7 +5001,7 @@ place-and-route.
do not flatten design before synthesis
-retime
- run 'abc' with -dff option
+ run 'abc' with '-dff -D 1' options
The following commands are executed by this synthesis command:
@@ -3630,9 +5019,12 @@ The following commands are executed by this synthesis command:
synth -run coarse
fine:
+ extract_counter -dir up -allow_arst no
+ techmap -map +/coolrunner2/cells_counter_map.v
+ clean
opt -fast -full
- techmap
- techmap -map +/coolrunner2/cells_latch.v
+ techmap -map +/techmap.v -map +/coolrunner2/cells_latch.v
+ opt -fast
dfflibmap -prepare -liberty +/coolrunner2/xc2_dff.lib
map_tff:
@@ -3653,9 +5045,11 @@ The following commands are executed by this synthesis command:
dffinit -ff LDCP Q INIT
dffinit -ff LDCP_N Q INIT
coolrunner2_sop
+ clean
iopadmap -bits -inpad IBUF O:I -outpad IOBUFE I:IO -inoutpad IOBUFE O:IO -toutpad IOBUFE E:I:IO -tinoutpad IOBUFE E:O:I:IO
attrmvcp -attr src -attr LOC t:IOBUFE n:*
attrmvcp -attr src -attr LOC -driven t:IBUF n:*
+ coolrunner2_fixup
splitnets
clean
@@ -3694,7 +5088,7 @@ This command runs synthesis for eASIC platform.
do not flatten design before synthesis
-retime
- run 'abc' with -dff option
+ run 'abc' with '-dff -D 1' options
The following commands are executed by this synthesis command:
@@ -3717,7 +5111,7 @@ The following commands are executed by this synthesis command:
opt -undriven -fine
techmap
opt -fast
- abc -dff (only if -retime)
+ abc -dff -D 1 (only if -retime)
opt_clean (only if -retime)
map:
@@ -3765,7 +5159,7 @@ This command runs synthesis for ECP5 FPGAs.
do not flatten design before synthesis
-retime
- run 'abc' with -dff option
+ run 'abc' with '-dff -D 1' options
-noccu2
do not use CCU2 cells in output netlist
@@ -3774,69 +5168,105 @@ This command runs synthesis for ECP5 FPGAs.
do not use flipflops with CE in output netlist
-nobram
- do not use BRAM cells in output netlist
+ do not use block RAM cells in output netlist
- -nodram
- do not use distributed RAM cells in output netlist
+ -nolutram
+ do not use LUT RAM cells in output netlist
- -nomux
+ -nowidelut
do not use PFU muxes to implement LUTs larger than LUT4s
+ -asyncprld
+ use async PRLD mode to implement DLATCH and DFFSR (EXPERIMENTAL)
+
-abc2
run two passes of 'abc' for slightly improved logic density
+ -abc9
+ use new ABC9 flow (EXPERIMENTAL)
+
-vpr
generate an output netlist (and BLIF file) suitable for VPR
(this feature is experimental and incomplete)
+ -nodsp
+ do not map multipliers to MULT18X18D
+
The following commands are executed by this synthesis command:
begin:
- read_verilog -lib +/ecp5/cells_sim.v
+ read_verilog -lib -specify +/ecp5/cells_sim.v +/ecp5/cells_bb.v
hierarchy -check -top <top>
- flatten: (unless -noflatten)
+ coarse:
proc
flatten
tribuf -logic
deminout
+ opt_expr
+ opt_clean
+ check
+ opt
+ wreduce
+ peepopt
+ opt_clean
+ share
+ techmap -map +/cmp2lut.v -D LUT_WIDTH=4
+ opt_expr
+ opt_clean
+ techmap -map +/mul2dsp.v -map +/ecp5/dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18 (unless -nodsp)
+ chtype -set $mul t:$__soft_mul (unless -nodsp)
+ alumacc
+ opt
+ fsm
+ opt -fast
+ memory -nomap
+ opt_clean
- coarse:
- synth -run coarse
-
- bram: (skip if -nobram)
+ map_bram: (skip if -nobram)
+ memory_bram -rules +/ecp5/brams.txt
+ techmap -map +/ecp5/brams_map.v
- dram: (skip if -nodram)
- memory_bram -rules +/ecp5/dram.txt
- techmap -map +/ecp5/drams_map.v
+ map_lutram: (skip if -nolutram)
+ memory_bram -rules +/ecp5/lutrams.txt
+ techmap -map +/ecp5/lutrams_map.v
- fine:
+ map_ffram:
opt -fast -mux_undef -undriven -fine
- memory_map
+ memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block -attr syn_ramstyle=auto -attr syn_ramstyle=registers -attr syn_romstyle=auto -attr syn_romstyle=logic
opt -undriven -fine
+
+ map_gates:
techmap -map +/techmap.v -map +/ecp5/arith_map.v
- abc -dff (only if -retime)
+ opt -fast
+ abc -dff -D 1 (only if -retime)
map_ffs:
- dffsr2dff
dff2dffs
opt_clean
dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*
- techmap -D NO_LUT -map +/ecp5/cells_map.v
- opt_expr -mux_undef
+ techmap -D NO_LUT [-D ASYNC_PRLD] -map +/ecp5/cells_map.v
+ opt_expr -undriven -mux_undef
simplemap
+ ecp5_ffinit
+ ecp5_gsr
+ attrmvcp -copy -attr syn_useioff
+ opt_clean
map_luts:
abc (only if -abc2)
- abc -lut 4:7
+ techmap -map +/ecp5/latches_map.v
+ abc -lut 4:7 -dress
clean
map_cells:
techmap -map +/ecp5/cells_map.v (with -D NO_LUT in vpr mode)
+ opt_lut_ins -tech ecp5
clean
check:
+ autoname
hierarchy -check
stat
check -noinit
@@ -3853,6 +5283,98 @@ The following commands are executed by this synthesis command:
write_json <file-name>
\end{lstlisting}
+\section{synth\_efinix -- synthesis for Efinix FPGAs}
+\label{cmd:synth_efinix}
+\begin{lstlisting}[numbers=left,frame=single]
+ synth_efinix [options]
+
+This command runs synthesis for Efinix FPGAs.
+
+ -top <module>
+ use the specified module as top module
+
+ -edif <file>
+ write the design to the specified EDIF file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -json <file>
+ write the design to the specified JSON file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -run <from_label>:<to_label>
+ only run the commands between the labels (see below). an empty
+ from label is synonymous to 'begin', and empty to label is
+ synonymous to the end of the command list.
+
+ -noflatten
+ do not flatten design before synthesis
+
+ -retime
+ run 'abc' with '-dff -D 1' options
+
+ -nobram
+ do not use EFX_RAM_5K cells in output netlist
+
+
+The following commands are executed by this synthesis command:
+
+ begin:
+ read_verilog -lib +/efinix/cells_sim.v
+ hierarchy -check -top <top>
+
+ flatten: (unless -noflatten)
+ proc
+ flatten
+ tribuf -logic
+ deminout
+
+ coarse:
+ synth -run coarse
+ memory_bram -rules +/efinix/brams.txt
+ techmap -map +/efinix/brams_map.v
+ setundef -zero -params t:EFX_RAM_5K
+
+ map_ffram:
+ opt -fast -mux_undef -undriven -fine
+ memory_map
+ opt -undriven -fine
+
+ map_gates:
+ techmap -map +/techmap.v -map +/efinix/arith_map.v
+ opt -fast
+ abc -dff -D 1 (only if -retime)
+
+ map_ffs:
+ techmap -D NO_LUT -map +/efinix/cells_map.v
+ dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit
+ opt_expr -mux_undef
+ simplemap
+
+ map_luts:
+ abc -lut 4
+ clean
+
+ map_cells:
+ techmap -map +/efinix/cells_map.v
+ clean
+
+ map_gbuf:
+ efinix_gbuf
+ efinix_fixcarry
+ clean
+
+ check:
+ hierarchy -check
+ stat
+ check -noinit
+
+ edif:
+ write_edif <file-name>
+
+ json:
+ write_json <file-name>
+\end{lstlisting}
+
\section{synth\_gowin -- synthesis for Gowin FPGAs}
\label{cmd:synth_gowin}
\begin{lstlisting}[numbers=left,frame=single]
@@ -3872,8 +5394,26 @@ This command runs synthesis for Gowin FPGAs. This work is experimental.
from label is synonymous to 'begin', and empty to label is
synonymous to the end of the command list.
+ -nodffe
+ do not use flipflops with CE in output netlist
+
+ -nobram
+ do not use BRAM cells in output netlist
+
+ -nolutram
+ do not use distributed RAM cells in output netlist
+
+ -noflatten
+ do not flatten design before synthesis
+
-retime
- run 'abc' with -dff option
+ run 'abc' with '-dff -D 1' options
+
+ -nowidelut
+ do not use muxes to implement LUTs larger than LUT4s
+
+ -noiopads
+ do not emit IOB at top level ports
The following commands are executed by this synthesis command:
@@ -3882,7 +5422,7 @@ The following commands are executed by this synthesis command:
read_verilog -lib +/gowin/cells_sim.v
hierarchy -check -top <top>
- flatten:
+ flatten: (unless -noflatten)
proc
flatten
tribuf -logic
@@ -3891,25 +5431,45 @@ The following commands are executed by this synthesis command:
coarse:
synth -run coarse
- fine:
+ map_bram: (skip if -nobram)
+ memory_bram -rules +/gowin/brams.txt
+ techmap -map +/gowin/brams_map.v
+
+ map_lutram: (skip if -nolutram)
+ memory_bram -rules +/gowin/lutrams.txt
+ techmap -map +/gowin/lutrams_map.v
+ determine_init
+
+ map_ffram:
opt -fast -mux_undef -undriven -fine
memory_map
opt -undriven -fine
- techmap
- clean -purge
- splitnets -ports
- setundef -undriven -zero
- abc -dff (only if -retime)
+
+ map_gates:
+ techmap -map +/techmap.v -map +/gowin/arith_map.v
+ opt -fast
+ abc -dff -D 1 (only if -retime)
+ splitnets
+
+ map_ffs:
+ dff2dffs -match-init
+ opt_clean
+ dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*
+ techmap -map +/gowin/cells_map.v
+ opt_expr -mux_undef
+ simplemap
map_luts:
- abc -lut 4
+ abc -lut 4:8
clean
map_cells:
techmap -map +/gowin/cells_map.v
- hilomap -hicell VCC V -locell GND G
- iopadmap -inpad IBUF O:I -outpad OBUF I:O
- clean -purge
+ opt_lut_ins -tech gowin
+ setundef -undriven -params -zero
+ hilomap -singleton -hicell VCC V -locell GND G
+ iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O -toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO (unless -noiopads)
+ clean
check:
hierarchy -check
@@ -3917,7 +5477,7 @@ The following commands are executed by this synthesis command:
check -noinit
vout:
- write_verilog -nodec -attr2comment -defparam -renameprefix gen <file-name>
+ write_verilog -decimal -attr2comment -defparam -renameprefix gen <file-name>
\end{lstlisting}
\section{synth\_greenpak4 -- synthesis for GreenPAK4 FPGAs}
@@ -3949,7 +5509,7 @@ place-and-route.
do not flatten design before synthesis
-retime
- run 'abc' with -dff option
+ run 'abc' with '-dff -D 1' options
The following commands are executed by this synthesis command:
@@ -3972,11 +5532,10 @@ The following commands are executed by this synthesis command:
opt -fast -mux_undef -undriven -fine
memory_map
opt -undriven -fine
- techmap
- techmap -map +/greenpak4/cells_latch.v
+ techmap -map +/techmap.v -map +/greenpak4/cells_latch.v
dfflibmap -prepare -liberty +/greenpak4/gp_dff.lib
opt -fast
- abc -dff (only if -retime)
+ abc -dff -D 1 (only if -retime)
map_luts:
nlutmap -assert -luts 0,6,8,2 (for -part SLG46140V)
@@ -4014,6 +5573,10 @@ The following commands are executed by this synthesis command:
This command runs synthesis for iCE40 FPGAs.
+ -device < hx | lp | u >
+ relevant only for '-abc9' flow, optimise timing for the specified device.
+ default: hx
+
-top <module>
use the specified module as top module
@@ -4038,7 +5601,7 @@ This command runs synthesis for iCE40 FPGAs.
do not flatten design before synthesis
-retime
- run 'abc' with -dff option
+ run 'abc' with '-dff -D 1' options
-nocarry
do not use SB_CARRY cells in output netlist
@@ -4046,9 +5609,19 @@ This command runs synthesis for iCE40 FPGAs.
-nodffe
do not use SB_DFFE* cells in output netlist
+ -dffe_min_ce_use <min_ce_use>
+ do not use SB_DFFE* cells if the resulting CE line would go to less
+ than min_ce_use SB_DFFE* in output netlist
+
-nobram
do not use SB_RAM40_4K* cells in output netlist
+ -dsp
+ use iCE40 UltraPlus DSP cells for large arithmetic
+
+ -noabc
+ use built-in Yosys LUT techmapping instead of abc
+
-abc2
run two passes of 'abc' for slightly improved logic density
@@ -4056,38 +5629,74 @@ This command runs synthesis for iCE40 FPGAs.
generate an output netlist (and BLIF file) suitable for VPR
(this feature is experimental and incomplete)
+ -abc9
+ use new ABC9 flow (EXPERIMENTAL)
+
+ -flowmap
+ use FlowMap LUT techmapping instead of abc (EXPERIMENTAL)
+
The following commands are executed by this synthesis command:
begin:
- read_verilog -lib +/ice40/cells_sim.v
+ read_verilog -D ICE40_HX -lib -specify +/ice40/cells_sim.v
hierarchy -check -top <top>
+ proc
flatten: (unless -noflatten)
- proc
flatten
tribuf -logic
deminout
coarse:
- synth -run coarse
+ opt_expr
+ opt_clean
+ check
+ opt
+ wreduce
+ peepopt
+ opt_clean
+ share
+ techmap -map +/cmp2lut.v -D LUT_WIDTH=4
+ opt_expr
+ opt_clean
+ memory_dff
+ wreduce t:$mul
+ techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D DSP_NAME=$__MUL16X16 (if -dsp)
+ select a:mul2dsp (if -dsp)
+ setattr -unset mul2dsp (if -dsp)
+ opt_expr -fine (if -dsp)
+ wreduce (if -dsp)
+ select -clear (if -dsp)
+ ice40_dsp (if -dsp)
+ chtype -set $mul t:$__soft_mul (if -dsp)
+ alumacc
+ opt
+ fsm
+ opt -fast
+ memory -nomap
+ opt_clean
- bram: (skip if -nobram)
+ map_bram: (skip if -nobram)
memory_bram -rules +/ice40/brams.txt
techmap -map +/ice40/brams_map.v
+ ice40_braminit
- fine:
+ map_ffram:
opt -fast -mux_undef -undriven -fine
- memory_map
+ memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block -attr syn_ramstyle=auto -attr syn_ramstyle=registers -attr syn_romstyle=auto -attr syn_romstyle=logic
opt -undriven -fine
+
+ map_gates:
+ ice40_wrapcarry
techmap -map +/techmap.v -map +/ice40/arith_map.v
- abc -dff (only if -retime)
+ opt -fast
+ abc -dff -D 1 (only if -retime)
ice40_opt
map_ffs:
- dffsr2dff
dff2dffe -direct-match $_DFF_*
- techmap -D NO_LUT -map +/ice40/cells_map.v
+ techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v
opt_expr -mux_undef
simplemap
ice40_ffinit
@@ -4098,14 +5707,21 @@ The following commands are executed by this synthesis command:
abc (only if -abc2)
ice40_opt (only if -abc2)
techmap -map +/ice40/latches_map.v
- abc -lut 4
+ simplemap (if -noabc or -flowmap)
+ techmap -map +/gate2lut.v -D LUT_WIDTH=4 (only if -noabc)
+ flowmap -maxlut 4 (only if -flowmap)
+ abc -dress -lut 4 (skip if -noabc)
+ ice40_wrapcarry -unwrap
+ techmap -D NO_LUT -map +/ice40/cells_map.v
clean
+ opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0
map_cells:
techmap -map +/ice40/cells_map.v (with -D NO_LUT in vpr mode)
clean
check:
+ autoname
hierarchy -check
stat
check -noinit
@@ -4129,11 +5745,11 @@ The following commands are executed by this synthesis command:
This command runs synthesis for Intel FPGAs.
- -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>
+ -family <max10 | arria10gx | cyclone10lp | cyclonev | cycloneiv | cycloneive>
generate the synthesis netlist for the specified family.
- MAX10 is the default target if not family argument specified.
- For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.
- Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.
+ MAX10 is the default target if no family argument specified.
+ For Cyclone IV GX devices, use cycloneiv argument; for Cyclone IV E, use cycloneive.
+ Cyclone V and Arria 10 GX devices are experimental.
-top <module>
use the specified module as top module (default='top')
@@ -4141,6 +5757,8 @@ This command runs synthesis for Intel FPGAs.
-vqm <file>
write the design to the specified Verilog Quartus Mapping File. Writing of an
output file is omitted if this parameter is not specified.
+ Note that this backend has not been tested and is likely incompatible
+ with recent versions of Quartus.
-vpr <file>
write BLIF files for VPR flow experiments. The synthesized BLIF output file is not
@@ -4152,17 +5770,17 @@ This command runs synthesis for Intel FPGAs.
from label is synonymous to 'begin', and empty to label is
synonymous to the end of the command list.
- -noiopads
- do not use altsyncram cells in output netlist
+ -iopads
+ use IO pad cells in output netlist
-nobram
- do not use altsyncram cells in output netlist
+ do not use block RAM cells in output netlist
-noflatten
do not flatten design before synthesis
-retime
- run 'abc' with -dff option
+ run 'abc' with '-dff -D 1' options
The following commands are executed by this synthesis command:
@@ -4183,29 +5801,28 @@ The following commands are executed by this synthesis command:
coarse:
synth -run coarse
- bram: (skip if -nobram)
- memory_bram -rules +/intel/common/brams.txt
- techmap -map +/intel/common/brams_map.v
+ map_bram: (skip if -nobram)
+ memory_bram -rules +/intel/common/brams_m9k.txt (if applicable for family)
+ techmap -map +/intel/common/brams_map_m9k.v (if applicable for family)
- fine:
+ map_ffram:
opt -fast -mux_undef -undriven -fine -full
memory_map
opt -undriven -fine
- dffsr2dff
dff2dffe -direct-match $_DFF_*
opt -fine
techmap -map +/techmap.v
opt -full
clean -purge
setundef -undriven -zero
- abc -markgroups -dff (only if -retime)
+ abc -markgroups -dff -D 1 (only if -retime)
map_luts:
abc -lut 4
clean
map_cells:
- iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I (unless -noiopads)
+ iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I (if -iopads)
techmap -map +/intel/max10/cells_map.v
dffinit -highlow -ff dffeas q power_up
clean -purge
@@ -4221,6 +5838,104 @@ The following commands are executed by this synthesis command:
vpr:
opt_clean -purge
write_blif <file-name>
+
+
+WARNING: THE 'synth_intel' COMMAND IS EXPERIMENTAL.
+\end{lstlisting}
+
+\section{synth\_sf2 -- synthesis for SmartFusion2 and IGLOO2 FPGAs}
+\label{cmd:synth_sf2}
+\begin{lstlisting}[numbers=left,frame=single]
+ synth_sf2 [options]
+
+This command runs synthesis for SmartFusion2 and IGLOO2 FPGAs.
+
+ -top <module>
+ use the specified module as top module
+
+ -edif <file>
+ write the design to the specified EDIF file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -vlog <file>
+ write the design to the specified Verilog file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -json <file>
+ write the design to the specified JSON file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -run <from_label>:<to_label>
+ only run the commands between the labels (see below). an empty
+ from label is synonymous to 'begin', and empty to label is
+ synonymous to the end of the command list.
+
+ -noflatten
+ do not flatten design before synthesis
+
+ -noiobs
+ run synthesis in "block mode", i.e. do not insert IO buffers
+
+ -clkbuf
+ insert direct PAD->global_net buffers
+
+ -retime
+ run 'abc' with '-dff -D 1' options
+
+
+The following commands are executed by this synthesis command:
+
+ begin:
+ read_verilog -lib +/sf2/cells_sim.v
+ hierarchy -check -top <top>
+
+ flatten: (unless -noflatten)
+ proc
+ flatten
+ tribuf -logic
+ deminout
+
+ coarse:
+ synth -run coarse
+
+ fine:
+ opt -fast -mux_undef -undriven -fine
+ memory_map
+ opt -undriven -fine
+ techmap -map +/techmap.v -map +/sf2/arith_map.v
+ opt -fast
+ abc -dff -D 1 (only if -retime)
+
+ map_ffs:
+ techmap -D NO_LUT -map +/sf2/cells_map.v
+ opt_expr -mux_undef
+ simplemap
+
+ map_luts:
+ abc -lut 4
+ clean
+
+ map_cells:
+ techmap -map +/sf2/cells_map.v
+ clean
+
+ map_iobs:
+ sf2_iobs [-clkbuf] (unless -noiobs)
+ clean
+
+ check:
+ hierarchy -check
+ stat
+ check -noinit
+
+ edif:
+ write_edif -gndvccy <file-name>
+
+ vlog:
+ write_verilog <file-name>
+
+ json:
+ write_json <file-name>
\end{lstlisting}
\section{synth\_xilinx -- synthesis for Xilinx FPGAs}
@@ -4235,6 +5950,26 @@ compatible with 7-Series Xilinx devices.
-top <module>
use the specified module as top module
+ -family <family>
+ run synthesis for the specified Xilinx architecture
+ generate the synthesis netlist for the specified family.
+ supported values:
+ - xcup: Ultrascale Plus
+ - xcu: Ultrascale
+ - xc7: Series 7 (default)
+ - xc6s: Spartan 6
+ - xc6v: Virtex 6
+ - xc5v: Virtex 5 (EXPERIMENTAL)
+ - xc4v: Virtex 4 (EXPERIMENTAL)
+ - xc3sda: Spartan 3A DSP (EXPERIMENTAL)
+ - xc3sa: Spartan 3A (EXPERIMENTAL)
+ - xc3se: Spartan 3E (EXPERIMENTAL)
+ - xc3s: Spartan 3 (EXPERIMENTAL)
+ - xc2vp: Virtex 2 Pro (EXPERIMENTAL)
+ - xc2v: Virtex 2 (EXPERIMENTAL)
+ - xcve: Virtex E, Spartan 2E (EXPERIMENTAL)
+ - xcv: Virtex, Spartan 2 (EXPERIMENTAL)
+
-edif <file>
write the design to the specified edif file. writing of an output file
is omitted if this parameter is not specified.
@@ -4247,6 +5982,42 @@ compatible with 7-Series Xilinx devices.
generate an output netlist (and BLIF file) suitable for VPR
(this feature is experimental and incomplete)
+ -ise
+ generate an output netlist suitable for ISE
+
+ -nobram
+ do not use block RAM cells in output netlist
+
+ -nolutram
+ do not use distributed RAM cells in output netlist
+
+ -nosrl
+ do not use distributed SRL cells in output netlist
+
+ -nocarry
+ do not use XORCY/MUXCY/CARRY4 cells in output netlist
+
+ -nowidelut
+ do not use MUXF[5-9] resources to implement LUTs larger than native for the target
+
+ -nodsp
+ do not use DSP48*s to implement multipliers and associated logic
+
+ -noiopad
+ disable I/O buffer insertion (useful for hierarchical or
+ out-of-context flows)
+
+ -noclkbuf
+ disable automatic clock buffer insertion
+
+ -uram
+ infer URAM288s for large memories (xcup only)
+
+ -widemux <int>
+ enable inference of hard multiplexer resources (MUXF[78]) for muxes at or
+ above this number of inputs (minimum value 2, recommended value >= 5).
+ default: 0 (no inference)
+
-run <from_label>:<to_label>
only run the commands between the labels (see below). an empty
from label is synonymous to 'begin', and empty to label is
@@ -4255,67 +6026,125 @@ compatible with 7-Series Xilinx devices.
-flatten
flatten design before synthesis
+ -dff
+ run 'abc'/'abc9' with -dff option
+
-retime
- run 'abc' with -dff option
+ run 'abc' with '-D 1' option to enable flip-flop retiming.
+ implies -dff.
+
+ -abc9
+ use new ABC9 flow (EXPERIMENTAL)
The following commands are executed by this synthesis command:
begin:
- read_verilog -lib +/xilinx/cells_sim.v
+ read_verilog -lib -specify +/xilinx/cells_sim.v
read_verilog -lib +/xilinx/cells_xtra.v
- read_verilog -lib +/xilinx/brams_bb.v
- hierarchy -check -top <top>
+ hierarchy -check -auto-top
- flatten: (only if -flatten)
+ prepare:
proc
- flatten
+ flatten (with '-flatten')
+ tribuf -logic
+ deminout
+ opt_expr
+ opt_clean
+ check
+ opt
+ wreduce [-keepdc] (option for '-widemux')
+ peepopt
+ opt_clean
+ muxpack ('-widemux' only)
+ pmux2shiftx (skip if '-nosrl' and '-widemux=0')
+ clean (skip if '-nosrl' and '-widemux=0')
+
+ map_dsp: (skip if '-nodsp')
+ memory_dff
+ techmap -map +/mul2dsp.v -map +/xilinx/{family}_dsp_map.v {options}
+ select a:mul2dsp
+ setattr -unset mul2dsp
+ opt_expr -fine
+ wreduce
+ select -clear
+ xilinx_dsp -family <family>
+ chtype -set $mul t:$__soft_mul
coarse:
- synth -run coarse
+ techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=[46]
+ alumacc
+ share
+ opt
+ fsm
+ opt -fast
+ memory -nomap
+ opt_clean
- bram:
- memory_bram -rules +/xilinx/brams.txt
- techmap -map +/xilinx/brams_map.v
+ map_uram: (only if '-uram')
+ memory_bram -rules +/xilinx/{family}_urams.txt
+ techmap -map +/xilinx/{family}_urams_map.v
- dram:
- memory_bram -rules +/xilinx/drams.txt
- techmap -map +/xilinx/drams_map.v
+ map_bram: (skip if '-nobram')
+ memory_bram -rules +/xilinx/{family}_brams.txt
+ techmap -map +/xilinx/{family}_brams_map.v
- fine:
+ map_lutram: (skip if '-nolutram')
+ memory_bram -rules +/xilinx/lut[46]_lutrams.txt
+ techmap -map +/xilinx/lutrams_map.v
+
+ map_ffram:
+ simplemap t:$dff t:$adff t:$mux
+ dff2dffs [-match-init] (-match-init for xc6s only)
opt -fast -full
memory_map
- dffsr2dff
- dff2dffe
+
+ fine:
+ dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*
+ muxcover <internal options> ('-widemux' only)
opt -full
- techmap -map +/techmap.v -map +/xilinx/arith_map.v
+ xilinx_srl -variable -minlen 3 (skip if '-nosrl')
+ techmap -map +/techmap.v -D LUT_SIZE=[46] [-map +/xilinx/mux_map.v] -map +/xilinx/arith_map.v
opt -fast
- map_luts:
- abc -luts 2:2,3,6:5,10,20 [-dff]
+ map_cells:
+ iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top (skip if '-noiopad')
+ techmap -map +/techmap.v -map +/xilinx/cells_map.v
clean
- map_cells:
- techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)
- dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT
+ map_ffs:
+ techmap -map +/xilinx/{family}_ff_map.v ('-abc9' only)
+
+ map_luts:
+ opt_expr -mux_undef
+ abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1] (option for 'nowidelut', '-dff', '-retime')
+ clean
+ xilinx_srl -fixed -minlen 3 (skip if '-nosrl')
+ techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v -map +/xilinx/{family}_ff_map.v -D LUT_WIDTH=[46]
+ xilinx_dffopt [-lut4]
+ opt_lut_ins -tech xilinx
+
+ finalize:
+ clkbufmap -buf BUFG O:I (skip if '-noclkbuf')
+ extractinv -inv INV O:I (only if '-ise')
clean
check:
hierarchy -check
- stat
+ stat -tech xilinx
check -noinit
- edif: (only if -edif)
- write_edif <file-name>
+ edif:
+ write_edif -pvector bra
- blif: (only if -blif)
- write_blif <file-name>
+ blif:
+ write_blif
\end{lstlisting}
\section{tcl -- execute a TCL script file}
\label{cmd:tcl}
\begin{lstlisting}[numbers=left,frame=single]
- tcl <filename>
+ tcl <filename> [args]
This command executes the tcl commands in the specified file.
Use 'yosys cmd' to run the yosys command 'cmd' from tcl.
@@ -4324,6 +6153,9 @@ The tcl command 'yosys -import' can be used to import all yosys
commands directly as tcl commands to the tcl shell. Yosys commands
'proc' and 'rename' are wrapped to tcl commands 'procs' and 'renames'
in order to avoid a name collision with the built in commands.
+
+If any arguments are specified, these arguments are provided to the script via
+the standard $argc and $argv variables.
\end{lstlisting}
\section{techmap -- generic technology mapper}
@@ -4349,7 +6181,8 @@ file.
instead of inlining them.
-max_iter <number>
- only run the specified number of iterations.
+ only run the specified number of iterations on each module.
+ default: unlimited
-recursive
instead of the iterative breadth-first algorithm use a recursive
@@ -4359,6 +6192,9 @@ file.
-autoproc
Automatically call "proc" on implementations that contain processes.
+ -wb
+ Ignore the 'whitebox' attribute on cell implementations.
+
-assert
this option will cause techmap to exit with an error if it can't map
a selected cell. only cell types that end on an underscore are accepted
@@ -4383,6 +6219,11 @@ When a module in the map file has the 'techmap_wrap' attribute set, techmap
will create a wrapper for the cell and then run the command string that the
attribute is set to on the wrapper module.
+When a port on a module in the map file has the 'techmap_autopurge' attribute
+set, and that port is not connected in the instantiation that is mapped, then
+then a cell port connected only to such wires will be omitted in the mapped
+version of the circuit.
+
All wires in the modules from the map file matching the pattern _TECHMAP_*
or *._TECHMAP_* are special wires that are used to pass instructions from
the mapping module to the techmap command. At the moment the following special
@@ -4421,6 +6262,13 @@ wires are supported:
It is possible to combine both prefixes to 'RECURSION; CONSTMAP; '.
+ _TECHMAP_REMOVEINIT_<port-name>_
+ When this wire is set to a constant value, the init attribute of the wire(s)
+ connected to this port will be consumed. This wire must have the same
+ width as the given port, and for every bit that is set to 1 in the value,
+ the corresponding init attribute bit will be changed to 1'bx. If all
+ bits of an init attribute are left as x, it will be removed.
+
In addition to this special wires, techmap also supports special parameters in
modules in the map file:
@@ -4434,6 +6282,13 @@ modules in the map file:
former has a 1-bit for each constant input bit and the latter has the
value for this bit. The unused bits of the latter are set to undef (x).
+ _TECHMAP_WIREINIT_<port-name>_
+ When a parameter with this name exists, it will be set to the initial
+ value of the wire(s) connected to the given port, as specified by the init
+ attribute. If the attribute doesn't exist, x will be filled for the
+ missing bits. To remove the init attribute bits used, use the
+ _TECHMAP_REMOVEINIT_*_ wires.
+
_TECHMAP_BITS_CONNMAP_
_TECHMAP_CONNMAP_<port-name>_
For an N-bit port, the _TECHMAP_CONNMAP_<port-name>_ parameter, if it
@@ -4449,6 +6304,12 @@ constant value.
A cell with the name _TECHMAP_REPLACE_ in the map file will inherit the name
and attributes of the cell that is being replaced.
+A cell with a name of the form `_TECHMAP_REPLACE_.<suffix>` in the map file will
+be named thus but with the `_TECHMAP_REPLACE_' prefix substituted with the name
+of the cell being replaced.
+Similarly, a wire named in the form `_TECHMAP_REPLACE_.<suffix>` will cause a
+new wire alias to be created and named as above but with the `_TECHMAP_REPLACE_'
+prefix also substituted.
See 'help extract' for a pass that does the opposite thing.
@@ -4465,7 +6326,7 @@ Execute the specified command, optionally writing the commands output to the
specified logfile(s).
-q
- Do not print output to the normal destination (console and/or log file)
+ Do not print output to the normal destination (console and/or log file).
-o logfile
Write output to this file, truncate if exists.
@@ -4474,7 +6335,7 @@ specified logfile(s).
Write output to this file, append if exists.
+INT, -INT
- Add/subract INT from the -v setting for this command.
+ Add/subtract INT from the -v setting for this command.
\end{lstlisting}
\section{test\_abcloop -- automatically test handling of loops in abc command}
@@ -4511,8 +6372,16 @@ The attribute 'gentb_constant' can be used to force a signal to a constant
value after initialization. This can e.g. be used to force a reset signal
low in order to explore more inner states in a state machine.
+The attribute 'gentb_skip' can be attached to modules to suppress testbench
+generation.
+
-n <int>
number of iterations the test bench should run (default = 1000)
+
+ -seed <int>
+ seed used for pseudo-random number generation (default = 0).
+ a value of 0 will cause an arbitrary seed to be chosen, based on
+ the current system time.
\end{lstlisting}
\section{test\_cell -- automatically test the implementation of a cell type}
@@ -4574,6 +6443,29 @@ cell types. Use for example 'all /$add' for all cell types except $add.
create a Verilog test bench to test simlib and write_verilog
\end{lstlisting}
+\section{test\_pmgen -- test pass for pmgen}
+\label{cmd:test_pmgen}
+\begin{lstlisting}[numbers=left,frame=single]
+ test_pmgen -reduce_chain [options] [selection]
+
+Demo for recursive pmgen patterns. Map chains of AND/OR/XOR to $reduce_*.
+
+
+ test_pmgen -reduce_tree [options] [selection]
+
+Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*.
+
+
+ test_pmgen -eqpmux [options] [selection]
+
+Demo for recursive pmgen patterns. Optimize EQ/NE/PMUX circuits.
+
+
+ test_pmgen -generate [options] <pattern_name>
+
+Create modules that match the specified pattern.
+\end{lstlisting}
+
\section{torder -- print cells in topological order}
\label{cmd:torder}
\begin{lstlisting}[numbers=left,frame=single]
@@ -4656,12 +6548,18 @@ Like -sv, but define FORMAL instead of SYNTHESIS.
Load the specified VHDL files into Verific.
- verific -work <libname> {-sv|-vhdl|...} <hdl-file>
+ verific [-work <libname>] {-sv|-vhdl|...} <hdl-file>
Load the specified Verilog/SystemVerilog/VHDL file into the specified library.
(default library when -work is not present: "work")
+ verific [-L <libname>] {-sv|-vhdl|...} <hdl-file>
+
+Look up external definitions in the specified library.
+(-L may be used more than once)
+
+
verific -vlog-incdir <directory>..
Add Verilog include directories.
@@ -4715,6 +6613,16 @@ Import options:
-autocover
Generate automatic cover statements for all asserts
+ -fullinit
+ Keep all register initializations, even those for non-FF registers.
+
+ -chparam name value
+ Elaborate the specified top modules (all modules when -all given) using
+ this parameter value. Modules on which this parameter does not exist will
+ cause Verific to produce a VERI-1928 or VHDL-1676 message. This option
+ can be specified multiple times to override multiple parameters.
+ String values must be passed in double quotes (").
+
-v, -vv
Verbose log messages. (-vv is even more verbose than -v.)
@@ -4743,7 +6651,12 @@ bindings (for Yosys and/or Verific developers):
-d <dump_file>
Dump the Verific netlist as a verilog file.
-Visit http://verific.com/ for more information on Verific.
+
+Use Symbiotic EDA Suite if you need Yosys+Verifc.
+https://www.symbioticeda.com/seda-suite
+
+Contact office@symbioticeda.com for free evaluation
+binaries of Symbiotic EDA Suite.
\end{lstlisting}
\section{verilog\_defaults -- set default options for read\_verilog}
@@ -4779,6 +6692,21 @@ Define and undefine verilog preprocessor macros.
-Uname[=definition]
undefine the preprocessor symbol 'name'
+
+ -reset
+ clear list of defined preprocessor symbols
+
+ -list
+ list currently defined preprocessor symbols
+\end{lstlisting}
+
+\section{wbflip -- flip the whitebox attribute}
+\label{cmd:wbflip}
+\begin{lstlisting}[numbers=left,frame=single]
+ wbflip [selection]
+
+Flip the whitebox attribute on selected cells. I.e. if it's set, unset it, and
+vice-versa. Blackbox cells are not effected by this command.
\end{lstlisting}
\section{wreduce -- reduce the word size of operations if possible}
@@ -4798,6 +6726,9 @@ Options:
-memx
Do not change the width of memory address ports. Use this options in
flows that use the 'memory_memx' pass.
+
+ -keepdc
+ Do not optimize explicit don't-care values.
\end{lstlisting}
\section{write\_aiger -- write design to AIGER file}
@@ -4813,7 +6744,7 @@ $assert and $assume cells are converted to AIGER bad state properties and
invariant constraints.
-ascii
- write ASCII version of AGIER format
+ write ASCII version of AIGER format
-zinit
convert FFs to zero-initialized FFs, adding additional inputs for
@@ -4830,6 +6761,11 @@ invariant constraints.
-vmap <filename>
like -map, but more verbose
+
+ -I, -O, -B, -L
+ If the design contains no input/output/assert/flip-flop then create one
+ dummy input/output/bad_state-pin or latch to make the tools reading the
+ AIGER file happy.
\end{lstlisting}
\section{write\_blif -- write design to BLIF file}
@@ -4913,6 +6849,58 @@ Write a BTOR description of the current design.
-s
Output only a single bad property for all asserts
+
+ -c
+ Output cover properties using 'bad' statements instead of asserts
+
+ -i <filename>
+ Create additional info file with auxiliary information
+\end{lstlisting}
+
+\section{write\_cxxrtl -- convert design to C++ RTL simulation}
+\label{cmd:write_cxxrtl}
+\begin{lstlisting}[numbers=left,frame=single]
+ write_cxxrtl [options] [filename]
+
+Write C++ code for simulating the design. The generated code requires a driver;
+the following simple driver is provided as an example:
+
+ #include "top.cc"
+
+ int main() {
+ cxxrtl_design::p_top top;
+ while (1) {
+ top.p_clk.next = value<1> {1u};
+ top.step();
+ top.p_clk.next = value<1> {0u};
+ top.step();
+ }
+ }
+
+The following options are supported by this backend:
+
+ -O <level>
+ set the optimization level. the default is -O5. higher optimization
+ levels dramatically decrease compile and run time, and highest level
+ possible for a design should be used.
+
+ -O0
+ no optimization.
+
+ -O1
+ elide internal wires if possible.
+
+ -O2
+ like -O1, and localize internal wires if possible.
+
+ -O3
+ like -O2, and elide public wires not marked (*keep*) if possible.
+
+ -O4
+ like -O3, and localize public wires not marked (*keep*) if possible.
+
+ -O5
+ like -O4, and run `splitnets -driver; opt_clean -purge` first.
\end{lstlisting}
\section{write\_edif -- write design to EDIF netlist file}
@@ -4930,6 +6918,13 @@ Write the current design to an EDIF netlist file.
if the design contains constant nets. use "hilomap" to map to custom
constant drivers first)
+ -gndvccy
+ create "GND" and "VCC" cells with "Y" outputs. (the default is "G"
+ for "GND" and "P" for "VCC".)
+
+ -attrprop
+ create EDIF properties for cell attributes
+
-pvector {par|bra|ang}
sets the delimiting character for module port rename clauses to
parentheses, square brackets, or angle brackets.
@@ -4964,6 +6959,8 @@ Inside a script the input file can also can a here-document:
write_firrtl [options] [filename]
Write a FIRRTL netlist of the current design.
+The following commands are executed by this command:
+ pmuxtree
\end{lstlisting}
\section{write\_ilang -- write design to ilang file}
@@ -5012,6 +7009,10 @@ Write a JSON netlist of the current design.
-aig
include AIG models for the different gate types
+ -compat-int
+ emit 32-bit or smaller fully-defined parameter values directly
+ as JSON numbers (for compatibility with old parsers)
+
The general syntax of the JSON output created by this command is as follows:
@@ -5083,12 +7084,10 @@ interface is known.
Module and cell ports and nets can be single bit wide or vectors of multiple
bits. Each individual signal bit is assigned a unique integer. The <bit_vector>
values referenced above are vectors of this integers. Signal bits that are
-connected to a constant driver are denoted as string "0" or "1" instead of
-a number.
+connected to a constant driver are denoted as string "0", "1", "x", or
+"z" instead of a number.
-Numeric parameter and attribute values up to 32 bits are written as decimal
-values. Numbers larger than that are written as string holding the binary
-representation of the value.
+Bit vectors (including integers) are written as string holding the binaryrepresentation of the value. Strings are written as strings, with an appendedblank in cases of strings of the form /[01xz]* */.
For example the following Verilog code:
@@ -5214,7 +7213,7 @@ format. A program processing this format must ignore all unknown fields.
\begin{lstlisting}[numbers=left,frame=single]
write_simplec [options] [filename]
-Write simple C code for simulating the design. The C code writen can be used to
+Write simple C code for simulating the design. The C code written can be used to
simulate the design in a C environment, but the purpose of this command is to
generate code that works well with C-based formal verification.
@@ -5471,6 +7470,10 @@ Write the current design to a Verilog file.
without this option all internal cells are converted to Verilog
expressions.
+ -siminit
+ add initial statements with hierarchical refs to initialize FFs when
+ in -noexpr mode.
+
-nodec
32-bit constant values are by default dumped as decimal numbers,
not bit pattern. This option deactivates this feature and instead
@@ -5490,8 +7493,16 @@ Write the current design to a Verilog file.
deactivates this feature and instead will write string constants
as binary numbers.
+ -extmem
+ instead of initializing memories using assignments to individual
+ elements, use the '$readmemh' function to read initialization data
+ from a file. This data is written to a file named by appending
+ a sequential index to the Verilog filename and replacing the extension
+ with '.mem', e.g. 'write_verilog -extmem foo.v' writes 'foo-1.mem',
+ 'foo-2.mem' and so on.
+
-defparam
- Use 'defparam' statements instead of the Verilog-2001 syntax for
+ use 'defparam' statements instead of the Verilog-2001 syntax for
cell parameters.
-blackboxes
@@ -5513,6 +7524,97 @@ processes to logic networks and registers. A warning is generated when
this command is called on a design with RTLIL processes.
\end{lstlisting}
+\section{write\_xaiger -- write design to XAIGER file}
+\label{cmd:write_xaiger}
+\begin{lstlisting}[numbers=left,frame=single]
+ write_xaiger [options] [filename]
+
+Write the top module (according to the (* top *) attribute or if only one module
+is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, ornon (* abc9_box_id *) cells will be converted into psuedo-inputs and
+pseudo-outputs. Whitebox contents will be taken from the '<module-name>$holes'
+module, if it exists.
+
+ -ascii
+ write ASCII version of AIGER format
+
+ -map <filename>
+ write an extra file with port and box symbols
+\end{lstlisting}
+
+\section{xilinx\_dffopt -- Xilinx: optimize FF control signal usage}
+\label{cmd:xilinx_dffopt}
+\begin{lstlisting}[numbers=left,frame=single]
+ xilinx_dffopt [options] [selection]
+
+Converts hardware clock enable and set/reset signals on FFs to emulation
+using LUTs, if doing so would improve area. Operates on post-techmap Xilinx
+cells (LUT*, FD*).
+
+ -lut4
+ Assume a LUT4-based device (instead of a LUT6-based device).
+\end{lstlisting}
+
+\section{xilinx\_dsp -- Xilinx: pack resources into DSPs}
+\label{cmd:xilinx_dsp}
+\begin{lstlisting}[numbers=left,frame=single]
+ xilinx_dsp [options] [selection]
+
+Pack input registers (A2, A1, B2, B1, C, D, AD; with optional enable/reset),
+pipeline registers (M; with optional enable/reset), output registers (P; with
+optional enable/reset), pre-adder and/or post-adder into Xilinx DSP resources.
+
+Multiply-accumulate operations using the post-adder with feedback on the 'C'
+input will be folded into the DSP. In this scenario only, the 'C' input can be
+used to override the current accumulation result with a new value, which will
+be added to the multiplier result to form the next accumulation result.
+
+Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C'
+connections (optionally, where 'P' is right-shifted by 17-bits and used as an
+input to the post-adder -- a pattern common for summing partial products to
+implement wide multipliers). Limited support also exists for similar cascading
+for A and B using '[AB]COUT' -> '[AB]CIN'. Currently, cascade chains are limited
+to a maximum length of 20 cells, corresponding to the smallest Xilinx 7 Series
+device.
+
+This pass is a no-op if the scratchpad variable 'xilinx_dsp.multonly' is set
+to 1.
+
+
+Experimental feature: addition/subtractions less than 12 or 24 bits with the
+'(* use_dsp="simd" *)' attribute attached to the output wire or attached to
+the add/subtract operator will cause those operations to be implemented using
+the 'SIMD' feature of DSPs.
+
+Experimental feature: the presence of a `$ge' cell attached to the registered
+P output implementing the operation "(P >= <power-of-2>)" will be transformed
+into using the DSP48E1's pattern detector feature for overflow detection.
+
+ -family {xcup|xcu|xc7|xc6v|xc5v|xc4v|xc6s|xc3sda}
+ select the family to target
+ default: xc7
+\end{lstlisting}
+
+\section{xilinx\_srl -- Xilinx shift register extraction}
+\label{cmd:xilinx_srl}
+\begin{lstlisting}[numbers=left,frame=single]
+ xilinx_srl [options] [selection]
+
+This pass converts chains of built-in flops (bit-level: $_DFF_[NP]_, $_DFFE_*
+and word-level: $dff, $dffe) as well as Xilinx flops (FDRE, FDRE_1) into a
+$__XILINX_SHREG cell. Chains must be of the same cell type, clock, clock polarity,
+enable, and enable polarity (where relevant).
+Flops with resets cannot be mapped to Xilinx devices and will not be inferred.
+ -minlen N
+ min length of shift register (default = 3)
+
+ -fixed
+ infer fixed-length shift registers.
+
+ -variable
+ infer variable-length shift registers (i.e. fixed-length shifts where
+ each element also fans-out to a $shiftx cell).
+\end{lstlisting}
+
\section{zinit -- add inverters so all FF are zero-initialized}
\label{cmd:zinit}
\begin{lstlisting}[numbers=left,frame=single]
diff --git a/misc/yosys-config.in b/misc/yosys-config.in
index 1473948cf..370835f8f 100644
--- a/misc/yosys-config.in
+++ b/misc/yosys-config.in
@@ -18,21 +18,21 @@ help() {
echo ""
echo "Use --exec to call a command instead of generating output. Example usage:"
echo ""
- echo " yosys-config --exec --cxx --cxxflags --ldflags -o plugin.so -shared plugin.cc --ldlibs"
+ echo " $0 --exec --cxx --cxxflags --ldflags -o plugin.so -shared plugin.cc --ldlibs"
echo ""
echo "The above command can be abbreviated as:"
echo ""
- echo " yosys-config --build plugin.so plugin.cc"
+ echo " $0 --build plugin.so plugin.cc"
echo ""
echo "Use --prefix to change the prefix for the special args from '--' to"
echo "something else. Example:"
echo ""
- echo " yosys-config --prefix @ bindir: @bindir"
+ echo " $0 --prefix @ bindir: @bindir"
echo ""
echo "The args --bindir and --datdir can be directly followed by a slash and"
echo "additional text. Example:"
echo ""
- echo " yosys-config --datdir/simlib.v"
+ echo " $0 --datdir/simlib.v"
echo ""
} >&2
exit 1
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index 2556d188a..8d973869e 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -149,7 +149,7 @@ struct SetundefPass : public Pass {
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- bool got_value = false;
+ int got_value = 0;
bool undriven_mode = false;
bool expose_mode = false;
bool init_mode = false;
@@ -170,31 +170,31 @@ struct SetundefPass : public Pass {
continue;
}
if (args[argidx] == "-zero") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_ZERO;
worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-one") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_ONE;
worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-anyseq") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_ANYSEQ;
worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-anyconst") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_ANYCONST;
worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-undef") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_UNDEF;
worker.next_bit_state = 0;
continue;
@@ -207,8 +207,8 @@ struct SetundefPass : public Pass {
params_mode = true;
continue;
}
- if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
- got_value = true;
+ if (args[argidx] == "-random" && argidx+1 < args.size()) {
+ got_value++;
worker.next_bit_mode = MODE_RANDOM;
worker.next_bit_state = atoi(args[++argidx].c_str()) + 1;
for (int i = 0; i < 10; i++)
@@ -221,7 +221,7 @@ struct SetundefPass : public Pass {
if (!got_value && expose_mode) {
log("Using default as -undef with -expose.\n");
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_UNDEF;
worker.next_bit_state = 0;
}
@@ -229,7 +229,9 @@ struct SetundefPass : public Pass {
if (expose_mode && !undriven_mode)
log_cmd_error("Option -expose must be used with option -undriven.\n");
if (!got_value)
- log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, or -random <seed> must be specified.\n");
+ log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, -random <seed>, or -expose must be specified.\n");
+ else if (got_value > 1)
+ log_cmd_error("Only one of the options -zero, -one, -anyseq, -anyconst, or -random <seed> can be specified.\n");
if (init_mode && (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST))
log_cmd_error("The options -init and -anyseq / -anyconst are exclusive.\n");
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc
index 52ee1e99d..0898ec288 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -137,9 +137,26 @@ struct rules_t
vector<vector<std::tuple<bool,IdString,Const>>> attributes;
};
+ bool attr_icase;
dict<IdString, vector<bram_t>> brams;
vector<match_t> matches;
+ std::string map_case(std::string value) const
+ {
+ if (attr_icase) {
+ for (char &c : value)
+ c = tolower(c);
+ }
+ return value;
+ }
+
+ RTLIL::Const map_case(RTLIL::Const value) const
+ {
+ if (value.flags & RTLIL::CONST_FLAG_STRING)
+ return map_case(value.decode_string());
+ return value;
+ }
+
std::ifstream infile;
vector<string> tokens;
vector<string> labels;
@@ -337,7 +354,7 @@ struct rules_t
IdString key = RTLIL::escape_id(tokens[idx].substr(c1, c2));
Const val = c2 != std::string::npos ? tokens[idx].substr(c2+1) : RTLIL::Const(1);
- data.attributes.back().emplace_back(exists, key, val);
+ data.attributes.back().emplace_back(exists, key, map_case(val));
}
continue;
}
@@ -351,6 +368,7 @@ struct rules_t
rewrite_filename(filename);
infile.open(filename);
linecount = 0;
+ attr_icase = false;
if (infile.fail())
log_error("Can't open rules file `%s'.\n", filename.c_str());
@@ -360,6 +378,11 @@ struct rules_t
if (!labels.empty())
syntax_error();
+ if (GetSize(tokens) == 2 && tokens[0] == "attr_icase") {
+ attr_icase = atoi(tokens[1].c_str());
+ continue;
+ }
+
if (tokens[0] == "bram") {
parse_bram();
continue;
@@ -843,7 +866,7 @@ grow_read_ports:;
}
else if (!exists)
continue;
- if (it->second != value)
+ if (rules.map_case(it->second) != value)
continue;
found = true;
break;
@@ -855,7 +878,7 @@ grow_read_ports:;
ss << "!";
IdString key = std::get<1>(sums.front());
ss << log_id(key);
- const Const &value = std::get<2>(sums.front());
+ const Const &value = rules.map_case(std::get<2>(sums.front()));
if (exists && value != Const(1))
ss << "=\"" << value.decode_string() << "\"";
@@ -1079,9 +1102,6 @@ void handle_cell(Cell *cell, const rules_t &rules)
auto &bram = rules.brams.at(match.name).at(vi);
bool or_next_if_better = match.or_next_if_better || vi+1 < GetSize(rules.brams.at(match.name));
- if (failed_brams.count(pair<IdString, int>(bram.name, bram.variant)))
- continue;
-
int avail_rd_ports = 0;
int avail_wr_ports = 0;
for (int j = 0; j < bram.groups; j++) {
@@ -1117,6 +1137,9 @@ void handle_cell(Cell *cell, const rules_t &rules)
int efficiency = (100 * match_properties["bits"]) / (dups * cells * bram.dbits * (1 << bram.abits));
match_properties["efficiency"] = efficiency;
+ if (failed_brams.count(pair<IdString, int>(bram.name, bram.variant)))
+ goto next_match_rule;
+
log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n",
log_id(match.name), awaste, dwaste, bwaste, waste, efficiency);
@@ -1167,7 +1190,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
}
else if (!exists)
continue;
- if (it->second != value)
+ if (rules.map_case(it->second) != value)
continue;
found = true;
break;
@@ -1179,7 +1202,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
ss << "!";
IdString key = std::get<1>(sums.front());
ss << log_id(key);
- const Const &value = std::get<2>(sums.front());
+ const Const &value = rules.map_case(std::get<2>(sums.front()));
if (exists && value != Const(1))
ss << "=\"" << value.decode_string() << "\"";
@@ -1252,8 +1275,13 @@ struct MemoryBramPass : public Pass {
log("The given rules file describes the available resources and how they should be\n");
log("used.\n");
log("\n");
- log("The rules file contains a set of block ram description and a sequence of match\n");
- log("rules. A block ram description looks like this:\n");
+ log("The rules file contains configuration options, a set of block ram description\n");
+ log("and a sequence of match rules.\n");
+ log("\n");
+ log("The option 'attr_icase' configures how attribute values are matched. The value 0\n");
+ log("means case-sensitive, 1 means case-insensitive.\n");
+ log("\n");
+ log("A block ram description looks like this:\n");
log("\n");
log(" bram RAMB1024X32 # name of BRAM cell\n");
log(" init 1 # set to '1' if BRAM can be initialized\n");
diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc
index da0673c8f..9d455f55b 100644
--- a/passes/memory/memory_map.cc
+++ b/passes/memory/memory_map.cc
@@ -28,11 +28,32 @@ PRIVATE_NAMESPACE_BEGIN
struct MemoryMapWorker
{
+ bool attr_icase = false;
+ dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
+
RTLIL::Design *design;
RTLIL::Module *module;
std::map<std::pair<RTLIL::SigSpec, RTLIL::SigSpec>, RTLIL::SigBit> decoder_cache;
+ MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module) {}
+
+ std::string map_case(std::string value) const
+ {
+ if (attr_icase) {
+ for (char &c : value)
+ c = tolower(c);
+ }
+ return value;
+ }
+
+ RTLIL::Const map_case(RTLIL::Const value) const
+ {
+ if (value.flags & RTLIL::CONST_FLAG_STRING)
+ return map_case(value.decode_string());
+ return value;
+ }
+
std::string genid(RTLIL::IdString name, std::string token1 = "", int i = -1, std::string token2 = "", int j = -1, std::string token3 = "", int k = -1, std::string token4 = "")
{
std::stringstream sstr;
@@ -98,6 +119,36 @@ struct MemoryMapWorker
return;
}
+ // check if attributes allow us to infer FFRAM for this cell
+ for (const auto &attr : attributes) {
+ if (cell->attributes.count(attr.first)) {
+ const auto &cell_attr = cell->attributes[attr.first];
+ if (attr.second.empty()) {
+ log("Not mapping memory cell %s in module %s (attribute %s is set).\n",
+ cell->name.c_str(), module->name.c_str(), attr.first.c_str());
+ return;
+ }
+
+ bool found = false;
+ for (auto &value : attr.second) {
+ if (map_case(cell_attr) == map_case(value)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ if (cell_attr.flags & RTLIL::CONST_FLAG_STRING) {
+ log("Not mapping memory cell %s in module %s (attribute %s is set to \"%s\").\n",
+ cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.decode_string().c_str());
+ } else {
+ log("Not mapping memory cell %s in module %s (attribute %s is set to %d).\n",
+ cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.as_int());
+ }
+ return;
+ }
+ }
+ }
+
// all write ports must share the same clock
RTLIL::SigSpec clocks = cell->getPort(ID::WR_CLK);
RTLIL::Const clocks_pol = cell->parameters[ID::WR_CLK_POLARITY];
@@ -339,7 +390,7 @@ struct MemoryMapWorker
module->remove(cell);
}
- MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module)
+ void run()
{
std::vector<RTLIL::Cell*> cells;
for (auto cell : module->selected_cells())
@@ -356,17 +407,73 @@ struct MemoryMapPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" memory_map [selection]\n");
+ log(" memory_map [options] [selection]\n");
log("\n");
log("This pass converts multiport memory cells as generated by the memory_collect\n");
log("pass to word-wide DFFs and address decoders.\n");
log("\n");
+ log(" -attr !<name>\n");
+ log(" do not map memories that have attribute <name> set.\n");
+ log("\n");
+ log(" -attr <name>[=<value>]\n");
+ log(" for memories that have attribute <name> set, only map them if its value\n");
+ log(" is a string <value> (if specified), or an integer 1 (otherwise). if this\n");
+ log(" option is specified multiple times, map the memory if the attribute is\n");
+ log(" to any of the values.\n");
+ log("\n");
+ log(" -iattr\n");
+ log(" for -attr, ignore case of <value>.\n");
+ log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ bool attr_icase = false;
+ dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
+
log_header(design, "Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n");
- extra_args(args, 1, design);
- for (auto mod : design->selected_modules())
- MemoryMapWorker(design, mod);
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-attr" && argidx + 1 < args.size())
+ {
+ std::string attr_arg = args[++argidx];
+ std::string name;
+ RTLIL::Const value;
+ size_t eq_at = attr_arg.find('=');
+ if (eq_at != std::string::npos) {
+ name = attr_arg.substr(0, eq_at);
+ value = attr_arg.substr(eq_at + 1);
+ } else {
+ name = attr_arg;
+ value = RTLIL::Const(1);
+ }
+ if (attr_arg.size() > 1 && attr_arg[0] == '!') {
+ if (value != RTLIL::Const(1)) {
+ --argidx;
+ break; // we don't support -attr !<name>=<value>
+ }
+ attributes[RTLIL::escape_id(name.substr(1))].clear();
+ } else {
+ attributes[RTLIL::escape_id(name)].push_back(value);
+ }
+ continue;
+ }
+ if (args[argidx] == "-iattr")
+ {
+ attr_icase = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto mod : design->selected_modules()) {
+ MemoryMapWorker worker(design, mod);
+ worker.attr_icase = attr_icase;
+ worker.attributes = attributes;
+ worker.run();
+ }
}
} MemoryMapPass;
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index da3961218..6271376f1 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -406,6 +406,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
if (verbose && del_temp_wires_count)
log_debug(" removed %d unused temporary wires.\n", del_temp_wires_count);
+ if (!del_wires_queue.empty())
+ module->design->scratchpad_set_bool("opt.did_something", true);
+
return !del_wires_queue.empty();
}
@@ -476,6 +479,9 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
next_wire:;
}
+ if (did_something)
+ module->design->scratchpad_set_bool("opt.did_something", true);
+
return did_something;
}
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 1a4dd9239..3229dd1b2 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -717,31 +717,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
RTLIL::SigSpec sig_co = cell->getPort(ID::CO);
- bool sub = (sig_ci == State::S1 && sig_bi == State::S1);
+ if (sig_bi != State::S0 && sig_bi != State::S1)
+ goto skip_fine_alu;
+ if (sig_ci != State::S0 && sig_ci != State::S1)
+ goto skip_fine_alu;
- // If not a subtraction, yet there is a carry or B is inverted
- // then no optimisation is possible as carry will not be constant
- if (!sub && (sig_ci != State::S0 || sig_bi != State::S0))
- goto next_cell;
+ bool bi = sig_bi == State::S1;
+ bool ci = sig_ci == State::S1;
int i;
for (i = 0; i < GetSize(sig_y); i++) {
RTLIL::SigBit b = sig_b.at(i, State::Sx);
RTLIL::SigBit a = sig_a.at(i, State::Sx);
- if (b == State::S0 && a != State::Sx) {
- module->connect(sig_y[i], sig_a[i]);
- module->connect(sig_x[i], sub ? module->Not(NEW_ID, a).as_bit() : a);
- module->connect(sig_co[i], sub ? State::S1 : State::S0);
- }
- else if (sub && b == State::S1 && a == State::S1) {
- module->connect(sig_y[i], State::S0);
- module->connect(sig_x[i], module->Not(NEW_ID, a));
- module->connect(sig_co[i], State::S0);
+ if (b == ((bi ^ ci) ? State::S1 : State::S0) && a != State::Sx) {
+ module->connect(sig_y[i], a);
+ module->connect(sig_x[i], ci ? module->Not(NEW_ID, a).as_bit() : a);
+ module->connect(sig_co[i], ci ? State::S1 : State::S0);
}
- else if (!sub && a == State::S0 && b != State::Sx) {
- module->connect(sig_y[i], b);
- module->connect(sig_x[i], b);
- module->connect(sig_co[i], State::S0);
+ else if (a == (ci ? State::S1 : State::S0) && b != State::Sx) {
+ module->connect(sig_y[i], bi ? module->Not(NEW_ID, b).as_bit() : b);
+ module->connect(sig_x[i], (bi ^ ci) ? module->Not(NEW_ID, b).as_bit() : b);
+ module->connect(sig_co[i], ci ? State::S1 : State::S0);
}
else
break;
@@ -758,6 +754,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
}
+skip_fine_alu:
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr),
ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow)))
@@ -1089,7 +1086,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
// If not a subtraction, yet there is a carry or B is inverted
// then no optimisation is possible as carry will not be constant
if (!sub && (sig_ci != State::S0 || sig_bi != State::S0))
- goto next_cell;
+ goto skip_identity;
}
if (!sub && a.is_fully_const() && a.as_bool() == false)
@@ -1163,6 +1160,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
goto next_cell;
}
}
+skip_identity:
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
cell->getPort(ID::A) == State::S0 && cell->getPort(ID::B) == State::S1) {
@@ -1426,6 +1424,39 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
goto next_cell;
}
}
+
+ sig_a = assign_map(cell->getPort(ID::A));
+ sig_b = assign_map(cell->getPort(ID::B));
+ int a_zeros, b_zeros;
+ for (a_zeros = 0; a_zeros < GetSize(sig_a); a_zeros++)
+ if (sig_a[a_zeros] != RTLIL::State::S0)
+ break;
+ for (b_zeros = 0; b_zeros < GetSize(sig_b); b_zeros++)
+ if (sig_b[b_zeros] != RTLIL::State::S0)
+ break;
+ if (a_zeros || b_zeros) {
+ int y_zeros = a_zeros + b_zeros;
+ cover("opt.opt_expr.mul_low_zeros");
+
+ log_debug("Removing low %d A and %d B bits from cell `%s' in module `%s'.\n",
+ a_zeros, b_zeros, cell->name.c_str(), module->name.c_str());
+
+ if (a_zeros) {
+ cell->setPort(ID::A, sig_a.extract_end(a_zeros));
+ cell->parameters[ID::A_WIDTH] = GetSize(sig_a) - a_zeros;
+ }
+ if (b_zeros) {
+ cell->setPort(ID::B, sig_b.extract_end(b_zeros));
+ cell->parameters[ID::B_WIDTH] = GetSize(sig_b) - b_zeros;
+ }
+ cell->setPort(ID::Y, sig_y.extract_end(y_zeros));
+ cell->parameters[ID::Y_WIDTH] = GetSize(sig_y) - y_zeros;
+ module->connect(RTLIL::SigSig(sig_y.extract(0, y_zeros), RTLIL::SigSpec(0, y_zeros)));
+ cell->check();
+
+ did_something = true;
+ goto next_cell;
+ }
}
if (!keepdc && cell->type.in(ID($div), ID($mod)))
@@ -1497,6 +1528,99 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
+ // Find places in $alu cell where the carry is constant, and split it at these points.
+ if (do_fine && !keepdc && cell->type == ID($alu))
+ {
+ bool a_signed = cell->parameters[ID::A_SIGNED].as_bool();
+ bool b_signed = cell->parameters[ID::B_SIGNED].as_bool();
+ bool is_signed = a_signed && b_signed;
+
+ RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
+ RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
+ RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
+ RTLIL::SigSpec sig_bi = assign_map(cell->getPort(ID::BI));
+ if (GetSize(sig_a) == 0)
+ sig_a = State::S0;
+ if (GetSize(sig_b) == 0)
+ sig_b = State::S0;
+ sig_a.extend_u0(GetSize(sig_y), is_signed);
+ sig_b.extend_u0(GetSize(sig_y), is_signed);
+
+ if (sig_bi != State::S0 && sig_bi != State::S1)
+ goto skip_alu_split;
+
+ std::vector<std::pair<int, State>> split_points;
+
+ for (int i = 0; i < GetSize(sig_y); i++) {
+ SigBit bit_a = sig_a[i];
+ SigBit bit_b = sig_b[i];
+ if (bit_a != State::S0 && bit_a != State::S1)
+ continue;
+ if (bit_b != State::S0 && bit_b != State::S1)
+ continue;
+ if (sig_bi == State::S1) {
+ if (bit_b == State::S0)
+ bit_b = State::S1;
+ else
+ bit_b = State::S0;
+ }
+ if (bit_a != bit_b)
+ continue;
+ split_points.push_back(std::make_pair(i + 1, bit_a.data));
+ }
+
+ if (split_points.empty() || split_points[0].first == GetSize(sig_y))
+ goto skip_alu_split;
+
+ for (auto &p : split_points)
+ log_debug("Splitting $alu cell `%s' in module `%s' at const-carry point %d.\n",
+ cell->name.c_str(), module->name.c_str(), p.first);
+
+ if (split_points.back().first != GetSize(sig_y))
+ split_points.push_back(std::make_pair(GetSize(sig_y), State::Sx));
+
+ RTLIL::SigSpec sig_ci = assign_map(cell->getPort(ID::CI));
+ int prev = 0;
+ RTLIL::SigSpec sig_x = assign_map(cell->getPort(ID::X));
+ RTLIL::SigSpec sig_co = assign_map(cell->getPort(ID::CO));
+
+ for (auto &p : split_points) {
+ int cur = p.first;
+ int sz = cur - prev;
+ bool last = cur == GetSize(sig_y);
+
+ RTLIL::Cell *c = module->addCell(NEW_ID, cell->type);
+ c->setPort(ID::A, sig_a.extract(prev, sz));
+ c->setPort(ID::B, sig_b.extract(prev, sz));
+ c->setPort(ID::BI, sig_bi);
+ c->setPort(ID::CI, sig_ci);
+ c->setPort(ID::Y, sig_y.extract(prev, sz));
+ c->setPort(ID::X, sig_x.extract(prev, sz));
+ RTLIL::SigSpec new_co = sig_co.extract(prev, sz);
+ if (p.second != State::Sx) {
+ module->connect(new_co[sz-1], p.second);
+ RTLIL::Wire *dummy = module->addWire(NEW_ID);
+ new_co[sz-1] = dummy;
+ }
+ c->setPort(ID::CO, new_co);
+ c->parameters[ID::A_WIDTH] = sz;
+ c->parameters[ID::B_WIDTH] = sz;
+ c->parameters[ID::Y_WIDTH] = sz;
+ c->parameters[ID::A_SIGNED] = last ? a_signed : false;
+ c->parameters[ID::B_SIGNED] = last ? b_signed : false;
+
+ prev = p.first;
+ sig_ci = p.second;
+ }
+
+ cover("opt.opt_expr.alu_split");
+ module->remove(cell);
+
+ did_something = true;
+ goto next_cell;
+ }
+skip_alu_split:
+
// remove redundant pairs of bits in ==, ===, !=, and !==
// replace cell with const driver if inputs can't be equal
if (do_fine && cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex)))
diff --git a/passes/sat/Makefile.inc b/passes/sat/Makefile.inc
index 4bb4b0edc..a928c57de 100644
--- a/passes/sat/Makefile.inc
+++ b/passes/sat/Makefile.inc
@@ -13,4 +13,5 @@ OBJS += passes/sat/fmcombine.o
OBJS += passes/sat/mutate.o
OBJS += passes/sat/cutpoint.o
OBJS += passes/sat/fminit.o
+OBJS += passes/sat/qbfsat.o
diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc
new file mode 100644
index 000000000..44691425f
--- /dev/null
+++ b/passes/sat/qbfsat.cc
@@ -0,0 +1,550 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Alberto Gonzalez <boqwxp@airmail.cc>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/celltypes.h"
+#include "kernel/log.h"
+#include "kernel/rtlil.h"
+#include "kernel/register.h"
+#include <cstdio>
+#include <algorithm>
+
+#if defined(_WIN32)
+# define WIFEXITED(x) 1
+# define WIFSIGNALED(x) 0
+# define WIFSTOPPED(x) 0
+# define WEXITSTATUS(x) ((x) & 0xff)
+# define WTERMSIG(x) SIGTERM
+#else
+# include <sys/wait.h>
+#endif
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct QbfSolutionType {
+ std::vector<std::string> stdout;
+ dict<std::string, std::string> hole_to_value;
+ bool sat;
+ bool unknown; //true if neither 'sat' nor 'unsat'
+ bool success; //true if exit code 0
+
+ QbfSolutionType() : sat(false), unknown(true), success(false) {}
+};
+
+struct QbfSolveOptions {
+ bool specialize, specialize_from_file, write_solution, nocleanup, dump_final_smt2, assume_outputs;
+ bool sat, unsat, show_smtbmc;
+ std::string specialize_soln_file;
+ std::string write_soln_soln_file;
+ std::string dump_final_smt2_file;
+ size_t argidx;
+ QbfSolveOptions() : specialize(false), specialize_from_file(false), write_solution(false),
+ nocleanup(false), dump_final_smt2(false), assume_outputs(false), sat(false), unsat(false),
+ show_smtbmc(false), argidx(0) {};
+};
+
+void recover_solution(QbfSolutionType &sol) {
+ YS_REGEX_TYPE sat_regex = YS_REGEX_COMPILE("Status: PASSED");
+ YS_REGEX_TYPE unsat_regex = YS_REGEX_COMPILE("Solver Error.*model is not available");
+ YS_REGEX_TYPE hole_value_regex = YS_REGEX_COMPILE_WITH_SUBS("Value for anyconst in [a-zA-Z0-9_]* \\(([^:]*:[^\\)]*)\\): (.*)");
+#ifndef NDEBUG
+ YS_REGEX_TYPE hole_loc_regex = YS_REGEX_COMPILE("[^:]*:[0-9]+.[0-9]+-[0-9]+.[0-9]+");
+ YS_REGEX_TYPE hole_val_regex = YS_REGEX_COMPILE("[0-9]+");
+#endif
+ YS_REGEX_MATCH_TYPE m;
+ bool sat_regex_found = false;
+ bool unsat_regex_found = false;
+ dict<std::string, bool> hole_value_recovered;
+ for (const std::string &x : sol.stdout) {
+ if(YS_REGEX_NS::regex_search(x, m, hole_value_regex)) {
+ std::string loc = m[1].str();
+ std::string val = m[2].str();
+#ifndef NDEBUG
+ log_assert(YS_REGEX_NS::regex_search(loc, hole_loc_regex));
+ log_assert(YS_REGEX_NS::regex_search(val, hole_val_regex));
+#endif
+ sol.hole_to_value[loc] = val;
+ }
+ else if (YS_REGEX_NS::regex_search(x, sat_regex))
+ sat_regex_found = true;
+ else if (YS_REGEX_NS::regex_search(x, unsat_regex))
+ unsat_regex_found = true;
+ }
+#ifndef NDEBUG
+ log_assert(!sol.unknown && sol.sat? sat_regex_found : true);
+ log_assert(!sol.unknown && !sol.sat? unsat_regex_found : true);
+#endif
+}
+
+dict<std::string, std::string> get_hole_loc_name_map(RTLIL::Module *module, const QbfSolutionType &sol) {
+ dict<std::string, std::string> hole_loc_to_name;
+ for (auto cell : module->cells()) {
+ std::string cell_src = cell->get_src_attribute();
+ auto pos = sol.hole_to_value.find(cell_src);
+ if (pos != sol.hole_to_value.end()) {
+#ifndef NDEBUG
+ log_assert(cell->type.in("$anyconst", "$anyseq"));
+ log_assert(cell->getPort(ID::Y).is_wire());
+#endif
+ hole_loc_to_name[pos->first] = cell->getPort(ID::Y).as_wire()->name.str();
+ }
+ }
+
+ return hole_loc_to_name;
+}
+
+void write_solution(RTLIL::Module *module, const QbfSolutionType &sol, const std::string &file) {
+ std::ofstream fout(file.c_str());
+ if (!fout)
+ log_cmd_error("could not open solution file for writing.\n");
+
+ dict<std::string, std::string> hole_loc_to_name = get_hole_loc_name_map(module, sol);
+ for(auto &x : sol.hole_to_value)
+ fout << hole_loc_to_name[x.first] << "=" << x.second << std::endl;
+}
+
+void specialize_from_file(RTLIL::Module *module, const std::string &file) {
+ YS_REGEX_TYPE hole_assn_regex = YS_REGEX_COMPILE_WITH_SUBS("^(.*)=([01]+)$");
+ YS_REGEX_MATCH_TYPE m;
+ pool<RTLIL::Cell *> anyconsts_to_remove;
+ dict<std::string, std::string> hole_name_to_value;
+ std::ifstream fin(file.c_str());
+ if (!fin)
+ log_cmd_error("could not read solution file.\n");
+
+ std::string buf;
+ while (std::getline(fin, buf)) {
+ log_assert(YS_REGEX_NS::regex_search(buf, m, hole_assn_regex));
+ std::string hole_name = m[1].str();
+ std::string hole_value = m[2].str();
+ hole_name_to_value[hole_name] = hole_value;
+ }
+
+ for (auto cell : module->cells())
+ if (cell->type == "$anyconst") {
+ auto anyconst_port_y = cell->getPort(ID::Y).as_wire();
+ if (anyconst_port_y == nullptr)
+ continue;
+ if (hole_name_to_value.find(anyconst_port_y->name.str()) != hole_name_to_value.end())
+ anyconsts_to_remove.insert(cell);
+ }
+ for (auto cell : anyconsts_to_remove)
+ module->remove(cell);
+
+ for (auto &it : hole_name_to_value) {
+ std::string hole_name = it.first;
+ std::string hole_value = it.second;
+ RTLIL::Wire *wire = module->wire(hole_name);
+#ifndef NDEBUG
+ log_assert(wire != nullptr);
+ log_assert(wire->width > 0 && GetSize(hole_value) == wire->width);
+#endif
+
+ log("Specializing %s from file with %s = %d'b%s.\n", module->name.c_str(), hole_name.c_str(), wire->width, hole_value.c_str());
+ std::vector<RTLIL::SigBit> value_bv;
+ value_bv.reserve(wire->width);
+ for (char c : hole_value)
+ value_bv.emplace_back(c == '1'? RTLIL::S1 : RTLIL::S0);
+ std::reverse(value_bv.begin(), value_bv.end());
+ module->connect(wire, value_bv);
+ }
+}
+
+void specialize(RTLIL::Module *module, const QbfSolutionType &sol) {
+ dict<std::string, std::string> hole_loc_to_name = get_hole_loc_name_map(module, sol);
+ pool<RTLIL::Cell *> anyconsts_to_remove;
+ for (auto cell : module->cells())
+ if (cell->type == "$anyconst")
+ if (hole_loc_to_name.find(cell->get_src_attribute()) != hole_loc_to_name.end())
+ anyconsts_to_remove.insert(cell);
+ for (auto cell : anyconsts_to_remove)
+ module->remove(cell);
+ for (auto &it : sol.hole_to_value) {
+ std::string hole_loc = it.first;
+ std::string hole_value = it.second;
+
+#ifndef NDEBUG
+ auto pos = hole_loc_to_name.find(hole_loc);
+ log_assert(pos != hole_loc_to_name.end());
+#endif
+
+ std::string hole_name = hole_loc_to_name[hole_loc];
+ RTLIL::Wire *wire = module->wire(hole_name);
+#ifndef NDEBUG
+ log_assert(wire != nullptr);
+ log_assert(wire->width > 0 && GetSize(hole_value) == wire->width);
+#endif
+
+ log("Specializing %s with %s = %d'b%s.\n", module->name.c_str(), hole_name.c_str(), wire->width, hole_value.c_str());
+ std::vector<RTLIL::SigBit> value_bv;
+ value_bv.reserve(wire->width);
+ for (char c : hole_value)
+ value_bv.emplace_back(c == '1'? RTLIL::S1 : RTLIL::S0);
+ std::reverse(value_bv.begin(), value_bv.end());
+ module->connect(wire, value_bv);
+ }
+}
+
+void dump_model(RTLIL::Module *module, const QbfSolutionType &sol) {
+ log("Satisfiable model:\n");
+ dict<std::string, std::string> hole_loc_to_name = get_hole_loc_name_map(module, sol);
+ for (auto &it : sol.hole_to_value) {
+ std::string hole_loc = it.first;
+ std::string hole_value = it.second;
+
+#ifndef NDEBUG
+ auto pos = hole_loc_to_name.find(hole_loc);
+ log_assert(pos != hole_loc_to_name.end());
+#endif
+
+ std::string hole_name = hole_loc_to_name[hole_loc];
+ log("\t%s = %lu'b%s\n", hole_name.c_str(), hole_value.size(), hole_value.c_str());
+ std::vector<RTLIL::SigBit> value_bv;
+ value_bv.reserve(hole_value.size());
+ for (char c : hole_value)
+ value_bv.emplace_back(c == '1'? RTLIL::S1 : RTLIL::S0);
+ std::reverse(value_bv.begin(), value_bv.end());
+ }
+
+}
+
+void allconstify_inputs(RTLIL::Module *module, const pool<std::string> &input_wires) {
+ for (auto &n : input_wires) {
+ RTLIL::Wire *input = module->wire(n);
+#ifndef NDEBUG
+ log_assert(input != nullptr);
+#endif
+
+ RTLIL::Cell *allconst = module->addCell("$allconst$" + n, "$allconst");
+ allconst->setParam(ID(WIDTH), input->width);
+ allconst->setPort(ID::Y, input);
+ allconst->set_src_attribute(input->get_src_attribute());
+ input->port_input = false;
+ log("Replaced input %s with $allconst cell.\n", n.c_str());
+ }
+ module->fixup_ports();
+}
+
+void assume_miter_outputs(RTLIL::Module *module) {
+ std::vector<RTLIL::Wire *> wires_to_assume;
+ for (auto w : module->wires())
+ if (w->port_output && w->width == 1)
+ wires_to_assume.push_back(w);
+
+ if (wires_to_assume.size() == 0)
+ return;
+ else {
+ log("Adding $assume cell for output(s): ");
+ for (auto w : wires_to_assume)
+ log("\"%s\" ", w->name.c_str());
+ log("\n");
+ }
+
+ for(auto i = 0; wires_to_assume.size() > 1; ++i) {
+ std::vector<RTLIL::Wire *> buf;
+ for (auto j = 0; j + 1 < GetSize(wires_to_assume); j += 2) {
+ std::stringstream strstr; strstr << i << "_" << j;
+ RTLIL::Wire *and_wire = module->addWire("\\_qbfsat_and_" + strstr.str(), 1);
+ module->addLogicAnd("$_qbfsat_and_" + strstr.str(), wires_to_assume[j], wires_to_assume[j+1], and_wire, false, wires_to_assume[j]->get_src_attribute());
+ buf.push_back(and_wire);
+ }
+ if (wires_to_assume.size() % 2 == 1)
+ buf.push_back(wires_to_assume[wires_to_assume.size() - 1]);
+ wires_to_assume.swap(buf);
+ }
+
+#ifndef NDEBUG
+ log_assert(wires_to_assume.size() == 1);
+#endif
+ module->addAssume("$assume_qbfsat_miter_outputs", wires_to_assume[0], RTLIL::S1);
+}
+
+QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) {
+ QbfSolutionType ret;
+ const std::string yosys_smtbmc_exe = proc_self_dirname() + "yosys-smtbmc";
+ const std::string smtbmc_warning = "z3: WARNING:";
+ const bool show_smtbmc = opt.show_smtbmc;
+
+ const std::string tempdir_name = make_temp_dir("/tmp/yosys-z3-XXXXXX");
+ const std::string smt2_command = "write_smt2 -stbv -wires " + tempdir_name + "/problem.smt2";
+#ifndef NDEBUG
+ log_assert(mod->design != nullptr);
+#endif
+ Pass::call(mod->design, smt2_command);
+ log_header(mod->design, "Solving QBF-SAT problem.\n");
+
+ //Execute and capture stdout from `yosys-smtbmc -s z3 -t 1 -g --binary [--dump-smt2 <file>]`
+ {
+ const std::string cmd = yosys_smtbmc_exe + " -s z3 -t 1 -g --binary " + (opt.dump_final_smt2? "--dump-smt2 " + opt.dump_final_smt2_file + " " : "") + tempdir_name + "/problem.smt2 2>&1";
+ auto process_line = [&ret, &smtbmc_warning, &show_smtbmc](const std::string &line) {
+ ret.stdout.push_back(line.substr(0, line.size()-1)); //don't include trailing newline
+ auto warning_pos = line.find(smtbmc_warning);
+ if (warning_pos != std::string::npos)
+ log_warning("%s", line.substr(warning_pos + smtbmc_warning.size() + 1).c_str());
+ else
+ if (show_smtbmc)
+ log("smtbmc output: %s", line.c_str());
+ };
+
+ log("Launching \"%s\".\n", cmd.c_str());
+ int retval = run_command(cmd, process_line);
+ if (retval == 0) {
+ ret.sat = true;
+ ret.unknown = false;
+ } else if (retval == 1) {
+ ret.sat = false;
+ ret.unknown = false;
+ }
+ }
+
+ if(!opt.nocleanup)
+ remove_directory(tempdir_name);
+
+ recover_solution(ret);
+
+ return ret;
+}
+
+pool<std::string> validate_design_and_get_inputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
+ bool found_input = false;
+ bool found_hole = false;
+ bool found_1bit_output = false;
+ bool found_assert_assume = false;
+ pool<std::string> input_wires;
+ for (auto wire : module->wires()) {
+ if (wire->port_input) {
+ found_input = true;
+ input_wires.insert(wire->name.str());
+ }
+ if (wire->port_output && wire->width == 1)
+ found_1bit_output = true;
+ }
+ for (auto cell : module->cells()) {
+ if (cell->type == "$allconst")
+ found_input = true;
+ if (cell->type == "$anyconst")
+ found_hole = true;
+ if (cell->type.in("$assert", "$assume"))
+ found_assert_assume = true;
+ }
+ if (!found_input)
+ log_cmd_error("Can't perform QBF-SAT on a miter with no inputs!\n");
+ if (!found_hole)
+ log_cmd_error("Did not find any existentially-quantified variables. Use 'sat' instead.\n");
+ if (!found_1bit_output && !found_assert_assume)
+ log_cmd_error("Did not find any single-bit outputs or $assert/$assume cells. Is this a miter circuit?\n");
+ if (!found_assert_assume && !opt.assume_outputs)
+ log_cmd_error("Did not find any $assert/$assume cells. Single-bit outputs were found, but `-assume-outputs` was not specified.\n");
+
+ return input_wires;
+}
+
+QbfSolveOptions parse_args(const std::vector<std::string> &args) {
+ QbfSolveOptions opt;
+ for (opt.argidx = 1; opt.argidx < args.size(); opt.argidx++) {
+ if (args[opt.argidx] == "-nocleanup") {
+ opt.nocleanup = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-specialize") {
+ opt.specialize = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-assume-outputs") {
+ opt.assume_outputs = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-sat") {
+ opt.sat = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-unsat") {
+ opt.unsat = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-show-smtbmc") {
+ opt.show_smtbmc = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-dump-final-smt2") {
+ opt.dump_final_smt2 = true;
+ if (args.size() <= opt.argidx + 1)
+ log_cmd_error("smt2 file not specified.\n");
+ else
+ opt.dump_final_smt2_file = args[++opt.argidx];
+ continue;
+ }
+ else if (args[opt.argidx] == "-specialize-from-file") {
+ opt.specialize_from_file = true;
+ if (args.size() <= opt.argidx + 1)
+ log_cmd_error("solution file not specified.\n");
+ else
+ opt.specialize_soln_file = args[++opt.argidx];
+ continue;
+ }
+ else if (args[opt.argidx] == "-write-solution") {
+ opt.write_solution = true;
+ if (args.size() <= opt.argidx + 1)
+ log_cmd_error("solution file not specified.\n");
+ else
+ opt.write_soln_soln_file = args[++opt.argidx];
+ continue;
+ }
+ break;
+ }
+
+ return opt;
+}
+
+void print_proof_failed()
+{
+ log("\n");
+ log(" ______ ___ ___ _ _ _ _ \n");
+ log(" (_____ \\ / __) / __) (_) | | | |\n");
+ log(" _____) )___ ___ ___ _| |__ _| |__ _____ _| | _____ __| | |\n");
+ log(" | ____/ ___) _ \\ / _ (_ __) (_ __|____ | | || ___ |/ _ |_|\n");
+ log(" | | | | | |_| | |_| || | | | / ___ | | || ____( (_| |_ \n");
+ log(" |_| |_| \\___/ \\___/ |_| |_| \\_____|_|\\_)_____)\\____|_|\n");
+ log("\n");
+}
+
+void print_qed()
+{
+ log("\n");
+ log(" /$$$$$$ /$$$$$$$$ /$$$$$$$ \n");
+ log(" /$$__ $$ | $$_____/ | $$__ $$ \n");
+ log(" | $$ \\ $$ | $$ | $$ \\ $$ \n");
+ log(" | $$ | $$ | $$$$$ | $$ | $$ \n");
+ log(" | $$ | $$ | $$__/ | $$ | $$ \n");
+ log(" | $$/$$ $$ | $$ | $$ | $$ \n");
+ log(" | $$$$$$/ /$$| $$$$$$$$ /$$| $$$$$$$//$$\n");
+ log(" \\____ $$$|__/|________/|__/|_______/|__/\n");
+ log(" \\__/ \n");
+ log("\n");
+}
+
+struct QbfSatPass : public Pass {
+ QbfSatPass() : Pass("qbfsat", "solve a 2QBF-SAT problem in the circuit") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" qbfsat [options] [selection]\n");
+ log("\n");
+ log("This command solves a 2QBF-SAT problem defined over the currently selected module.\n");
+ log("Existentially-quantified variables are declared by assigning a wire \"$anyconst\".\n");
+ log("Universally-quantified variables may be explicitly declared by assigning a wire\n");
+ log("\"$allconst\", but module inputs will be treated as universally-quantified variables\n");
+ log("by default.\n");
+ log("\n");
+ log(" -nocleanup\n");
+ log(" Do not delete temporary files and directories. Useful for\n");
+ log(" debugging.\n");
+ log("\n");
+ log(" -dump-final-smt2 <file>\n");
+ log(" Pass the --dump-smt2 option to yosys-smtbmc.\n");
+ log("\n");
+ log(" -assume-outputs\n");
+ log(" Add an $assume cell for the conjunction of all one-bit module output wires.\n");
+ log("\n");
+ log(" -sat\n");
+ log(" Generate an error if the solver does not return \"sat\".\n");
+ log("\n");
+ log(" -unsat\n");
+ log(" Generate an error if the solver does not return \"unsat\".\n");
+ log("\n");
+ log(" -show-smtbmc\n");
+ log(" Print the output from yosys-smtbmc.\n");
+ log("\n");
+ log(" -specialize\n");
+ log(" Replace all \"$anyconst\" cells with constant values determined by the solver.\n");
+ log("\n");
+ log(" -specialize-from-file <solution file>\n");
+ log(" Do not run the solver, but instead only attempt to replace all \"$anyconst\"\n");
+ log(" cells in the current module with values provided by the specified file.\n");
+ log("\n");
+ log(" -write-solution <solution file>\n");
+ log(" Write the assignments discovered by the solver for all \"$anyconst\" cells\n");
+ log(" to the specified file.");
+ log("\n");
+ log("\n");
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing QBFSAT pass (solving QBF-SAT problems in the circuit).\n");
+ QbfSolveOptions opt = parse_args(args);
+ extra_args(args, opt.argidx, design);
+
+ RTLIL::Module *module = nullptr;
+ for (auto mod : design->selected_modules()) {
+ if (module)
+ log_cmd_error("Only one module must be selected for the QBF-SAT pass! (selected: %s and %s)\n", log_id(module), log_id(mod));
+ module = mod;
+ }
+ if (module == nullptr)
+ log_cmd_error("Can't perform QBF-SAT on an empty selection!\n");
+
+ log_push();
+ if (!opt.specialize_from_file) {
+ //Save the design to restore after modiyfing the current module.
+ std::string module_name = module->name.str();
+ Pass::call(design, "design -push-copy");
+
+ //Replace input wires with wires assigned $allconst cells.
+ pool<std::string> input_wires = validate_design_and_get_inputs(module, opt);
+ allconstify_inputs(module, input_wires);
+ if (opt.assume_outputs)
+ assume_miter_outputs(module);
+
+ QbfSolutionType ret = qbf_solve(module, opt);
+ Pass::call(design, "design -pop");
+ module = design->module(module_name);
+
+ if (ret.unknown)
+ log_warning("solver did not give an answer\n");
+ else if (ret.sat)
+ print_qed();
+ else
+ print_proof_failed();
+
+ if(!ret.unknown && ret.sat) {
+ if (opt.write_solution) {
+ write_solution(module, ret, opt.write_soln_soln_file);
+ }
+ if (opt.specialize) {
+ specialize(module, ret);
+ } else {
+ dump_model(module, ret);
+ }
+ if (opt.unsat)
+ log_cmd_error("expected problem to be UNSAT\n");
+ }
+ else if (!ret.unknown && !ret.sat && opt.sat)
+ log_cmd_error("expected problem to be SAT\n");
+ else if (ret.unknown && (opt.sat || opt.unsat))
+ log_cmd_error("expected problem to be %s\n", opt.sat? "SAT" : "UNSAT");
+ } else
+ specialize_from_file(module, opt.specialize_soln_file);
+ log_pop();
+ }
+} QbfSatPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index c16db0d57..766b954df 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -34,7 +34,6 @@ OBJS += passes/techmap/aigmap.o
OBJS += passes/techmap/tribuf.o
OBJS += passes/techmap/lut2mux.o
OBJS += passes/techmap/nlutmap.o
-OBJS += passes/techmap/dffsr2dff.o
OBJS += passes/techmap/shregmap.o
OBJS += passes/techmap/deminout.o
OBJS += passes/techmap/insbuf.o
@@ -59,10 +58,10 @@ passes/techmap/techmap.inc: techlibs/common/techmap.v
passes/techmap/techmap.o: passes/techmap/techmap.inc
ifneq ($(CONFIG),emcc)
-TARGETS += yosys-filterlib$(EXE)
+TARGETS += $(PROGRAM_PREFIX)yosys-filterlib$(EXE)
EXTRA_OBJS += passes/techmap/filterlib.o
-yosys-filterlib$(EXE): passes/techmap/filterlib.o
+$(PROGRAM_PREFIX)yosys-filterlib$(EXE): passes/techmap/filterlib.o
$(Q) mkdir -p $(dir $@)
- $(P) $(LD) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS)
+ $(P) $(LD) -o $(PROGRAM_PREFIX)yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS)
endif
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 78ecab1e7..0ee495abd 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -702,7 +702,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (dff_mode && clk_sig.empty())
log_cmd_error("Clock domain %s not found.\n", clk_str.c_str());
- std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
+ std::string tempdir_name = "/tmp/" + proc_program_prefix()+ "yosys-abc-XXXXXX";
if (!cleanup)
tempdir_name[0] = tempdir_name[4] = '_';
tempdir_name = make_temp_dir(tempdir_name);
@@ -1305,7 +1305,7 @@ struct AbcPass : public Pass {
#ifdef ABCEXTERNAL
log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
#else
- log(" use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
+ log(" use the specified command instead of \"<yosys-bindir>/%syosys-abc\" to execute ABC.\n", proc_program_prefix().c_str());
#endif
log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
log("\n");
@@ -1491,7 +1491,7 @@ struct AbcPass : public Pass {
#ifdef ABCEXTERNAL
std::string exe_file = ABCEXTERNAL;
#else
- std::string exe_file = proc_self_dirname() + "yosys-abc";
+ std::string exe_file = proc_self_dirname() + proc_program_prefix() + "yosys-abc";
#endif
std::string script_file, liberty_file, constr_file, clk_str;
std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1";
@@ -1509,8 +1509,8 @@ struct AbcPass : public Pass {
#ifdef _WIN32
#ifndef ABCEXTERNAL
- if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe"))
- exe_file = proc_self_dirname() + "..\\yosys-abc";
+ if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix()+ "yosys-abc.exe"))
+ exe_file = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc";
#endif
#endif
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 9757b1539..1b3d5ff06 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -100,7 +100,7 @@ struct Abc9Pass : public ScriptPass
#ifdef ABCEXTERNAL
log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
#else
- log(" use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
+ log(" use the specified command instead of \"<yosys-bindir>/%syosys-abc\" to execute ABC.\n", proc_program_prefix().c_str());
#endif
log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
log("\n");
@@ -326,7 +326,7 @@ struct Abc9Pass : public ScriptPass
if (!active_design->selected_whole_module(mod))
log_error("Can't handle partially selected module %s!\n", log_id(mod));
- std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
+ std::string tempdir_name = "/tmp/" + proc_program_prefix() + "yosys-abc-XXXXXX";
if (!cleanup)
tempdir_name[0] = tempdir_name[4] = '_';
tempdir_name = make_temp_dir(tempdir_name);
diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc
index 898285c69..18618ff91 100644
--- a/passes/techmap/abc9_exe.cc
+++ b/passes/techmap/abc9_exe.cc
@@ -222,9 +222,9 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
abc9_script += stringf("; &ps -l; &write -n %s/output.aig", tempdir_name.c_str());
if (design->scratchpad_get_bool("abc9.verify")) {
if (dff_mode)
- abc9_script += "; verify -s";
+ abc9_script += "; &verify -s";
else
- abc9_script += "; verify";
+ abc9_script += "; &verify";
}
abc9_script += "; time";
abc9_script = add_echos_to_abc9_cmd(abc9_script);
@@ -293,7 +293,7 @@ struct Abc9ExePass : public Pass {
#ifdef ABCEXTERNAL
log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
#else
- log(" use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
+ log(" use the specified command instead of \"<yosys-bindir>/%syosys-abc\" to execute ABC.\n", proc_program_prefix().c_str());
#endif
log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
log("\n");
@@ -367,7 +367,7 @@ struct Abc9ExePass : public Pass {
#ifdef ABCEXTERNAL
std::string exe_file = ABCEXTERNAL;
#else
- std::string exe_file = proc_self_dirname() + "yosys-abc";
+ std::string exe_file = proc_self_dirname() + proc_program_prefix()+ "yosys-abc";
#endif
std::string script_file, clk_str, box_file, lut_file;
std::string delay_target, lutin_shared = "-S 1", wire_delay;
@@ -383,8 +383,8 @@ struct Abc9ExePass : public Pass {
#ifdef _WIN32
#ifndef ABCEXTERNAL
- if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe"))
- exe_file = proc_self_dirname() + "..\\yosys-abc";
+ if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc.exe"))
+ exe_file = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc";
#endif
#endif
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc
index 00af36615..8ae1b51ff 100644
--- a/passes/techmap/abc9_ops.cc
+++ b/passes/techmap/abc9_ops.cc
@@ -434,6 +434,9 @@ void prep_delays(RTLIL::Design *design, bool dff_mode)
auto &t = timing.at(derived_type).required;
for (auto &conn : cell->connections_) {
auto port_wire = inst_module->wire(conn.first);
+ if (!port_wire)
+ log_error("Port %s in cell %s (type %s) of module %s does not actually exist",
+ log_id(conn.first), log_id(cell->name), log_id(cell->type), log_id(module->name));
if (!port_wire->port_input)
continue;
diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc
index 0424ce434..35645582b 100644
--- a/passes/techmap/dffinit.cc
+++ b/passes/techmap/dffinit.cc
@@ -154,9 +154,11 @@ struct DffinitPass : public Pass {
value = Const(low_string);
}
- log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second),
- log_id(it.first), log_signal(sig), log_signal(value));
- cell->setParam(it.second, value);
+ if (value.size() != 0) {
+ log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second),
+ log_id(it.first), log_signal(sig), log_signal(value));
+ cell->setParam(it.second, value);
+ }
}
}
diff --git a/passes/techmap/dffsr2dff.cc b/passes/techmap/dffsr2dff.cc
deleted file mode 100644
index 4a3ddaf73..000000000
--- a/passes/techmap/dffsr2dff.cc
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
-{
- if (cell->type == ID($dffsr))
- {
- int width = cell->getParam(ID::WIDTH).as_int();
- bool setpol = cell->getParam(ID::SET_POLARITY).as_bool();
- bool clrpol = cell->getParam(ID::CLR_POLARITY).as_bool();
-
- SigBit setunused = setpol ? State::S0 : State::S1;
- SigBit clrunused = clrpol ? State::S0 : State::S1;
-
- SigSpec setsig = sigmap(cell->getPort(ID::SET));
- SigSpec clrsig = sigmap(cell->getPort(ID::CLR));
-
- Const reset_val;
- SigSpec setctrl, clrctrl;
-
- for (int i = 0; i < width; i++)
- {
- SigBit setbit = setsig[i], clrbit = clrsig[i];
-
- if (setbit == setunused) {
- clrctrl.append(clrbit);
- reset_val.bits.push_back(State::S0);
- continue;
- }
-
- if (clrbit == clrunused) {
- setctrl.append(setbit);
- reset_val.bits.push_back(State::S1);
- continue;
- }
-
- return;
- }
-
- setctrl.sort_and_unify();
- clrctrl.sort_and_unify();
-
- if (GetSize(setctrl) > 1 || GetSize(clrctrl) > 1)
- return;
-
- if (GetSize(setctrl) == 0 && GetSize(clrctrl) == 0)
- return;
-
- if (GetSize(setctrl) == 1 && GetSize(clrctrl) == 1) {
- if (setpol != clrpol)
- return;
- if (setctrl != clrctrl)
- return;
- }
-
- log("Converting %s cell %s.%s to $adff.\n", log_id(cell->type), log_id(module), log_id(cell));
-
- if (GetSize(setctrl) == 1) {
- cell->setPort(ID::ARST, setctrl);
- cell->setParam(ID::ARST_POLARITY, setpol);
- } else {
- cell->setPort(ID::ARST, clrctrl);
- cell->setParam(ID::ARST_POLARITY, clrpol);
- }
-
- cell->type = ID($adff);
- cell->unsetPort(ID::SET);
- cell->unsetPort(ID::CLR);
- cell->setParam(ID::ARST_VALUE, reset_val);
- cell->unsetParam(ID::SET_POLARITY);
- cell->unsetParam(ID::CLR_POLARITY);
-
- return;
- }
-
- if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
- ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_)))
- {
- char clkpol = cell->type.c_str()[8];
- char setpol = cell->type.c_str()[9];
- char clrpol = cell->type.c_str()[10];
-
- SigBit setbit = sigmap(cell->getPort(ID::S));
- SigBit clrbit = sigmap(cell->getPort(ID::R));
-
- SigBit setunused = setpol == 'P' ? State::S0 : State::S1;
- SigBit clrunused = clrpol == 'P' ? State::S0 : State::S1;
-
- IdString oldtype = cell->type;
-
- if (setbit == setunused) {
- cell->type = stringf("$_DFF_%c%c0_", clkpol, clrpol);
- cell->unsetPort(ID::S);
- goto converted_gate;
- }
-
- if (clrbit == clrunused) {
- cell->type = stringf("$_DFF_%c%c1_", clkpol, setpol);
- cell->setPort(ID::R, cell->getPort(ID::S));
- cell->unsetPort(ID::S);
- goto converted_gate;
- }
-
- return;
-
- converted_gate:
- log("Converting %s cell %s.%s to %s.\n", log_id(oldtype), log_id(module), log_id(cell), log_id(cell->type));
- return;
- }
-}
-
-void adff_worker(SigMap &sigmap, Module *module, Cell *cell)
-{
- if (cell->type == ID($adff))
- {
- bool rstpol = cell->getParam(ID::ARST_POLARITY).as_bool();
- SigBit rstunused = rstpol ? State::S0 : State::S1;
- SigSpec rstsig = sigmap(cell->getPort(ID::ARST));
-
- if (rstsig != rstunused)
- return;
-
- log("Converting %s cell %s.%s to $dff.\n", log_id(cell->type), log_id(module), log_id(cell));
-
- cell->type = ID($dff);
- cell->unsetPort(ID::ARST);
- cell->unsetParam(ID::ARST_VALUE);
- cell->unsetParam(ID::ARST_POLARITY);
-
- return;
- }
-
- if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
- {
- char clkpol = cell->type.c_str()[6];
- char rstpol = cell->type.c_str()[7];
-
- SigBit rstbit = sigmap(cell->getPort(ID::R));
- SigBit rstunused = rstpol == 'P' ? State::S0 : State::S1;
-
- if (rstbit != rstunused)
- return;
-
- IdString newtype = stringf("$_DFF_%c_", clkpol);
- log("Converting %s cell %s.%s to %s.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(newtype));
-
- cell->type = newtype;
- cell->unsetPort(ID::R);
-
- return;
- }
-}
-
-struct Dffsr2dffPass : public Pass {
- Dffsr2dffPass() : Pass("dffsr2dff", "convert DFFSR cells to simpler FF cell types") { }
- void help() YS_OVERRIDE
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" dffsr2dff [options] [selection]\n");
- log("\n");
- log("This pass converts DFFSR cells ($dffsr, $_DFFSR_???_) and ADFF cells ($adff,\n");
- log("$_DFF_???_) to simpler FF cell types when any of the set/reset inputs is unused.\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
- {
- log_header(design, "Executing DFFSR2DFF pass (mapping DFFSR cells to simpler FFs).\n");
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- // if (args[argidx] == "-v") {
- // continue;
- // }
- break;
- }
- extra_args(args, argidx, design);
-
- for (auto module : design->selected_modules()) {
- SigMap sigmap(module);
- for (auto cell : module->selected_cells()) {
- dffsr_worker(sigmap, module, cell);
- adff_worker(sigmap, module, cell);
- }
- }
- }
-} Dffsr2dffPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 518afa1a7..a554be257 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -1282,7 +1282,7 @@ struct TechmapPass : public Pass {
if (fn.compare(0, 1, "%") == 0) {
if (!saved_designs.count(fn.substr(1))) {
delete map;
- log_cmd_error("Can't saved design `%s'.\n", fn.c_str()+1);
+ log_cmd_error("Can't open saved design `%s'.\n", fn.c_str()+1);
}
for (auto mod : saved_designs.at(fn.substr(1))->modules())
if (!map->has(mod->name))
diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc
index a427c4987..74604ba3b 100644
--- a/passes/techmap/zinit.cc
+++ b/passes/techmap/zinit.cc
@@ -57,8 +57,7 @@ struct ZinitPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, State> initbits;
- pool<SigBit> donebits;
+ dict<SigBit, std::pair<State,SigBit>> initbits;
for (auto wire : module->selected_wires())
{
@@ -67,7 +66,6 @@ struct ZinitPass : public Pass {
SigSpec wirebits = sigmap(wire);
Const initval = wire->attributes.at(ID::init);
- wire->attributes.erase(ID::init);
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
{
@@ -78,24 +76,35 @@ struct ZinitPass : public Pass {
continue;
if (initbits.count(bit)) {
- if (initbits.at(bit) != val)
+ if (initbits.at(bit).first != val)
log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
log_signal(bit), log_signal(SigBit(wire, i)),
- log_signal(val), log_signal(initbits.at(bit)));
+ log_signal(val), log_signal(initbits.at(bit).first));
continue;
}
- initbits[bit] = val;
+ initbits[bit] = std::make_pair(val,SigBit(wire,i));
}
}
pool<IdString> dff_types = {
- ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($adff),
+ // FIXME: It would appear that supporting
+ // $dffsr/$_DFFSR_* would require a new
+ // cell type where S has priority over R
+ ID($ff), ID($dff), ID($dffe), /*ID($dffsr),*/ ID($adff),
ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
- ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
- ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),
+ /*ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
+ ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),*/
ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)
+ ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
+ // Async set/reset
+ ID($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1),
+ ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1),
+ // Sync set/reset
+ ID($__DFFS_NN0_), ID($__DFFS_NN1_), ID($__DFFS_NP0_), ID($__DFFS_NP1_),
+ ID($__DFFS_PN0_), ID($__DFFS_PN1_), ID($__DFFS_PP0_), ID($__DFFS_PP1_),
+ ID($__DFFSE_NN0), ID($__DFFSE_NN1), ID($__DFFSE_NP0), ID($__DFFSE_NP1),
+ ID($__DFFSE_PN0), ID($__DFFSE_PN1), ID($__DFFSE_PP0), ID($__DFFSE_PP1)
};
for (auto cell : module->selected_cells())
@@ -113,8 +122,10 @@ struct ZinitPass : public Pass {
for (int i = 0; i < GetSize(sig_q); i++) {
if (initbits.count(sig_q[i])) {
- initval.bits.push_back(initbits.at(sig_q[i]));
- donebits.insert(sig_q[i]);
+ const auto &d = initbits.at(sig_q[i]);
+ initval.bits.push_back(d.first);
+ const auto &b = d.second;
+ b.wire->attributes.at(ID::init)[b.offset] = State::Sx;
} else
initval.bits.push_back(all_mode ? State::S0 : State::Sx);
}
@@ -123,11 +134,11 @@ struct ZinitPass : public Pass {
initwire->attributes[ID::init] = initval;
for (int i = 0; i < GetSize(initwire); i++)
- if (initval.bits.at(i) == State::S1)
+ if (initval[i] == State::S1)
{
sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
- initwire->attributes[ID::init].bits.at(i) = State::S0;
+ initwire->attributes[ID::init][i] = State::S0;
}
else
{
@@ -139,11 +150,36 @@ struct ZinitPass : public Pass {
cell->setPort(ID::D, sig_d);
cell->setPort(ID::Q, initwire);
- }
- for (auto &it : initbits)
- if (donebits.count(it.first) == 0)
- log_error("Failed to handle init bit %s = %s.\n", log_signal(it.first), log_signal(it.second));
+ if (cell->type == ID($adff)) {
+ auto val = cell->getParam(ID::ARST_VALUE);
+ for (int i = 0; i < GetSize(initwire); i++)
+ if (initval[i] == State::S1)
+ val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
+ cell->setParam(ID::ARST_VALUE, std::move(val));
+ }
+ else if (initval == State::S1) {
+ std::string t = cell->type.str();
+ if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
+ ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
+ {
+ t[8] = (t[8] == '0' ? '1' : '0');
+ }
+ else if (cell->type.in(ID($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1),
+ ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1),
+ ID($__DFFS_NN0_), ID($__DFFS_NN1_), ID($__DFFS_NP0_), ID($__DFFS_NP1_),
+ ID($__DFFS_PN0_), ID($__DFFS_PN1_), ID($__DFFS_PP0_), ID($__DFFS_PP1_)))
+ {
+ t[10] = (t[10] == '0' ? '1' : '0');
+ }
+ else if (cell->type.in(ID($__DFFSE_NN0), ID($__DFFSE_NN1), ID($__DFFSE_NP0), ID($__DFFSE_NP1),
+ ID($__DFFSE_PN0), ID($__DFFSE_PN1), ID($__DFFSE_PP0), ID($__DFFSE_PP1)))
+ {
+ t[11] = (t[11] == '0' ? '1' : '0');
+ }
+ cell->type = t;
+ }
+ }
}
}
} ZinitPass;
diff --git a/techlibs/achronix/synth_achronix.cc b/techlibs/achronix/synth_achronix.cc
index 1dc6bdb2f..262a5e700 100644
--- a/techlibs/achronix/synth_achronix.cc
+++ b/techlibs/achronix/synth_achronix.cc
@@ -144,7 +144,6 @@ struct SynthAchronixPass : public ScriptPass {
run("opt -fast -mux_undef -undriven -fine -full");
run("memory_map");
run("opt -undriven -fine");
- run("dffsr2dff");
run("dff2dffe -direct-match $_DFF_*");
run("opt -fine");
run("techmap -map +/techmap.v");
diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc
index 96a231286..791dc922f 100644
--- a/techlibs/anlogic/synth_anlogic.cc
+++ b/techlibs/anlogic/synth_anlogic.cc
@@ -182,7 +182,6 @@ struct SynthAnlogicPass : public ScriptPass
if (check_label("map_ffs"))
{
- run("dffsr2dff");
run("techmap -D NO_LUT -map +/anlogic/cells_map.v");
run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit");
run("opt_expr -mux_undef");
diff --git a/techlibs/common/gen_fine_ffs.py b/techlibs/common/gen_fine_ffs.py
index 3a9aa6c59..0abe48f61 100644
--- a/techlibs/common/gen_fine_ffs.py
+++ b/techlibs/common/gen_fine_ffs.py
@@ -8,15 +8,14 @@ TEMPLATES = [
//-
//- Truth table: S R | Q
//- -----+---
-//- {S:0|1} {R:0|1} | x
-//- {S:0|1} {R:1|0} | 1
-//- {S:1|0} {R:0|1} | 0
-//- {S:1|0} {R:1|0} | y
+//- - {R:0|1} | 0
+//- {S:0|1} - | 1
+//- - - | q
//-
module \$_SR_{S:N|P}{R:N|P}_ (S, R, Q);
input S, R;
output reg Q;
-always @({S:neg|pos}edge S, {R:neg|pos}edge R) begin
+always @* begin
if (R == {R:0|1})
Q <= 0;
else if (S == {S:0|1})
diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v
index 2bac78d38..157e8d23b 100644
--- a/techlibs/common/simcells.v
+++ b/techlibs/common/simcells.v
@@ -469,15 +469,14 @@ endmodule
//-
//- Truth table: S R | Q
//- -----+---
-//- 0 0 | x
-//- 0 1 | 1
-//- 1 0 | 0
-//- 1 1 | y
+//- - 0 | 0
+//- 0 - | 1
+//- - - | q
//-
module \$_SR_NN_ (S, R, Q);
input S, R;
output reg Q;
-always @(negedge S, negedge R) begin
+always @* begin
if (R == 0)
Q <= 0;
else if (S == 0)
@@ -493,15 +492,14 @@ endmodule
//-
//- Truth table: S R | Q
//- -----+---
-//- 0 1 | x
-//- 0 0 | 1
-//- 1 1 | 0
-//- 1 0 | y
+//- - 1 | 0
+//- 0 - | 1
+//- - - | q
//-
module \$_SR_NP_ (S, R, Q);
input S, R;
output reg Q;
-always @(negedge S, posedge R) begin
+always @* begin
if (R == 1)
Q <= 0;
else if (S == 0)
@@ -517,15 +515,14 @@ endmodule
//-
//- Truth table: S R | Q
//- -----+---
-//- 1 0 | x
-//- 1 1 | 1
-//- 0 0 | 0
-//- 0 1 | y
+//- - 0 | 0
+//- 1 - | 1
+//- - - | q
//-
module \$_SR_PN_ (S, R, Q);
input S, R;
output reg Q;
-always @(posedge S, negedge R) begin
+always @* begin
if (R == 0)
Q <= 0;
else if (S == 1)
@@ -541,15 +538,14 @@ endmodule
//-
//- Truth table: S R | Q
//- -----+---
-//- 1 1 | x
-//- 1 0 | 1
-//- 0 1 | 0
-//- 0 0 | y
+//- - 1 | 0
+//- 1 - | 1
+//- - - | q
//-
module \$_SR_PP_ (S, R, Q);
input S, R;
output reg Q;
-always @(posedge S, posedge R) begin
+always @* begin
if (R == 1)
Q <= 0;
else if (S == 1)
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index 7845a3fed..2cdddeabb 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -1633,7 +1633,7 @@ wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
genvar i;
generate
for (i = 0; i < WIDTH; i = i+1) begin:bitslices
- always @(posedge pos_set[i], posedge pos_clr[i])
+ always @*
if (pos_clr[i])
Q[i] <= 0;
else if (pos_set[i])
diff --git a/techlibs/ecp5/brams.txt b/techlibs/ecp5/brams.txt
index 777ccaa2e..d34d9ec07 100644
--- a/techlibs/ecp5/brams.txt
+++ b/techlibs/ecp5/brams.txt
@@ -37,7 +37,17 @@ bram $__ECP5_DP16KD
clkpol 2 3
endbram
+# The syn_* attributes are described in:
+# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
+attr_icase 1
+
match $__ECP5_PDPW16KD
+ # implicitly requested RAM or ROM
+ attribute !syn_ramstyle syn_ramstyle=auto
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
min bits 2048
min efficiency 5
shuffle_enable A
@@ -45,8 +55,60 @@ match $__ECP5_PDPW16KD
or_next_if_better
endmatch
+match $__ECP5_PDPW16KD
+ # explicitly requested RAM
+ attribute syn_ramstyle=block_ram ram_block
+ attribute !syn_romstyle
+ attribute !rom_block
+ attribute !logic_block
+ min wports 1
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__ECP5_PDPW16KD
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
match $__ECP5_DP16KD
+ # implicitly requested RAM or ROM
+ attribute !syn_ramstyle syn_ramstyle=auto
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
min bits 2048
min efficiency 5
shuffle_enable A
+ or_next_if_better
+endmatch
+
+match $__ECP5_DP16KD
+ # explicitly requested RAM
+ attribute syn_ramstyle=block_ram ram_block
+ attribute !syn_romstyle
+ attribute !rom_block
+ attribute !logic_block
+ min wports 1
+ shuffle_enable A
+ or_next_if_better
+endmatch
+
+match $__ECP5_DP16KD
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ shuffle_enable A
endmatch
diff --git a/techlibs/ecp5/lutrams.txt b/techlibs/ecp5/lutrams.txt
index b94357429..9e6a23eba 100644
--- a/techlibs/ecp5/lutrams.txt
+++ b/techlibs/ecp5/lutrams.txt
@@ -11,7 +11,16 @@ bram $__TRELLIS_DPR16X4
clkpol 0 2
endbram
+# The syn_* attributes are described in:
+# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
+attr_icase 1
+
match $__TRELLIS_DPR16X4
+ attribute !syn_ramstyle syn_ramstyle=auto syn_ramstyle=distributed
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
make_outreg
min wports 1
endmatch
diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc
index 9916fdafb..ab740ea0d 100644
--- a/techlibs/ecp5/synth_ecp5.cc
+++ b/techlibs/ecp5/synth_ecp5.cc
@@ -279,7 +279,9 @@ struct SynthEcp5Pass : public ScriptPass
if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
- run("memory_map");
+ run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
+ "-attr syn_ramstyle=auto -attr syn_ramstyle=registers "
+ "-attr syn_romstyle=auto -attr syn_romstyle=logic");
run("opt -undriven -fine");
}
@@ -296,7 +298,6 @@ struct SynthEcp5Pass : public ScriptPass
if (check_label("map_ffs"))
{
- run("dffsr2dff");
run("dff2dffs");
run("opt_clean");
if (!nodffe)
diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc
index 637d7c00d..f9a7ef865 100644
--- a/techlibs/efinix/synth_efinix.cc
+++ b/techlibs/efinix/synth_efinix.cc
@@ -182,7 +182,6 @@ struct SynthEfinixPass : public ScriptPass
if (check_label("map_ffs"))
{
- run("dffsr2dff");
run("techmap -D NO_LUT -map +/efinix/cells_map.v");
run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit");
run("opt_expr -mux_undef");
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 86ec9cdc2..dd965c0b8 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -219,7 +219,6 @@ struct SynthGowinPass : public ScriptPass
if (check_label("map_ffs"))
{
- run("dffsr2dff");
run("dff2dffs -match-init");
run("opt_clean");
if (!nodffe)
diff --git a/techlibs/ice40/brams.txt b/techlibs/ice40/brams.txt
index 03d596111..36dfddab2 100644
--- a/techlibs/ice40/brams.txt
+++ b/techlibs/ice40/brams.txt
@@ -28,13 +28,73 @@ bram $__ICE40_RAM4K_M123
clkpol 2 3
endbram
+# The syn_* attributes are described in:
+# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
+attr_icase 1
+
match $__ICE40_RAM4K_M0
+ # implicitly requested RAM or ROM
+ attribute !syn_ramstyle syn_ramstyle=auto
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
min efficiency 2
make_transp
or_next_if_better
endmatch
+match $__ICE40_RAM4K_M0
+ # explicitly requested RAM
+ attribute syn_ramstyle=block_ram ram_block
+ attribute !syn_romstyle
+ attribute !rom_block
+ attribute !logic_block
+ min wports 1
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__ICE40_RAM4K_M0
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ make_transp
+ or_next_if_better
+endmatch
+
match $__ICE40_RAM4K_M123
+ # implicitly requested RAM or ROM
+ attribute !syn_ramstyle syn_ramstyle=auto
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
min efficiency 2
make_transp
+ or_next_if_better
+endmatch
+
+match $__ICE40_RAM4K_M123
+ # explicitly requested RAM
+ attribute syn_ramstyle=block_ram ram_block
+ attribute !syn_romstyle
+ attribute !rom_block
+ attribute !logic_block
+ min wports 1
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__ICE40_RAM4K_M123
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ make_transp
endmatch
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 59ada8bae..9724b7dd5 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -319,7 +319,9 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
- run("memory_map");
+ run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
+ "-attr syn_ramstyle=auto -attr syn_ramstyle=registers "
+ "-attr syn_romstyle=auto -attr syn_romstyle=logic");
run("opt -undriven -fine");
}
@@ -339,7 +341,6 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_ffs"))
{
- run("dffsr2dff");
if (!nodffe)
run("dff2dffe -direct-match $_DFF_*");
if (min_ce_use >= 0) {
diff --git a/techlibs/intel/Makefile.inc b/techlibs/intel/Makefile.inc
index d97a9b58f..f751e341f 100644
--- a/techlibs/intel/Makefile.inc
+++ b/techlibs/intel/Makefile.inc
@@ -11,4 +11,3 @@ families := max10 arria10gx cyclonev cyclone10lp cycloneiv cycloneive
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v)))
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v)))
#$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v))
-
diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc
index 3689df70e..8601ebb37 100644
--- a/techlibs/intel/synth_intel.cc
+++ b/techlibs/intel/synth_intel.cc
@@ -202,7 +202,6 @@ struct SynthIntelPass : public ScriptPass {
run("opt -fast -mux_undef -undriven -fine -full");
run("memory_map");
run("opt -undriven -fine");
- run("dffsr2dff");
run("dff2dffe -direct-match $_DFF_*");
run("opt -fine");
run("techmap -map +/techmap.v");
diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc
new file mode 100644
index 000000000..66204c8fc
--- /dev/null
+++ b/techlibs/intel_alm/Makefile.inc
@@ -0,0 +1,23 @@
+
+OBJS += techlibs/intel_alm/synth_intel_alm.o
+
+# Techmap
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_map.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_sim.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_map.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_sim.v))
+
+# RAM
+bramtypes := m10k m20k
+$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype).txt)))
+$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype)_map.v)))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab.txt))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab_map.v))
+
+families := cyclonev cyclone10gx
+
+# Miscellaneous
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/megafunction_bb.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/quartus_rename.v))
+$(foreach family, $(families), $(eval $(call add_share_file,share/intel_alm/$(family),techlibs/intel_alm/$(family)/quartus_rename.v)))
diff --git a/techlibs/intel_alm/common/alm_map.v b/techlibs/intel_alm/common/alm_map.v
new file mode 100644
index 000000000..fe646c5d6
--- /dev/null
+++ b/techlibs/intel_alm/common/alm_map.v
@@ -0,0 +1,56 @@
+module \$lut (A, Y);
+
+parameter WIDTH = 1;
+parameter LUT = 0;
+
+input [WIDTH-1:0] A;
+output Y;
+
+generate
+ if (WIDTH == 1) begin
+ generate
+ if (LUT == 2'b00) begin
+ assign Y = 1'b0;
+ end
+ else if (LUT == 2'b01) begin
+ MISTRAL_NOT _TECHMAP_REPLACE_(
+ .A(A[0]), .Q(Y)
+ );
+ end
+ else if (LUT == 2'b10) begin
+ assign Y = A;
+ end
+ else if (LUT == 2'b11) begin
+ assign Y = 1'b1;
+ end
+ endgenerate
+ end else
+ if (WIDTH == 2) begin
+ MISTRAL_ALUT2 #(.LUT(LUT)) _TECHMAP_REPLACE_(
+ .A(A[0]), .B(A[1]), .Q(Y)
+ );
+ end else
+ if (WIDTH == 3) begin
+ MISTRAL_ALUT3 #(.LUT(LUT)) _TECHMAP_REPLACE_(
+ .A(A[0]), .B(A[1]), .C(A[2]), .Q(Y)
+ );
+ end else
+ if (WIDTH == 4) begin
+ MISTRAL_ALUT4 #(.LUT(LUT)) _TECHMAP_REPLACE_(
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .Q(Y)
+ );
+ end else
+ if (WIDTH == 5) begin
+ MISTRAL_ALUT5 #(.LUT(LUT)) _TECHMAP_REPLACE_ (
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .Q(Y)
+ );
+ end else
+ if (WIDTH == 6) begin
+ MISTRAL_ALUT6 #(.LUT(LUT)) _TECHMAP_REPLACE_ (
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .F(A[5]), .Q(Y)
+ );
+ end else begin
+ wire _TECHMAP_FAIL_ = 1'b1;
+ end
+endgenerate
+endmodule
diff --git a/techlibs/intel_alm/common/alm_sim.v b/techlibs/intel_alm/common/alm_sim.v
new file mode 100644
index 000000000..69768d9f7
--- /dev/null
+++ b/techlibs/intel_alm/common/alm_sim.v
@@ -0,0 +1,482 @@
+`default_nettype none
+
+(* abc9_lut=2, lib_whitebox *)
+module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q);
+
+parameter [63:0] LUT = 64'h0000_0000_0000_0000;
+
+`ifdef cyclonev
+specify
+ (A => Q) = 602;
+ (B => Q) = 584;
+ (C => Q) = 510;
+ (D => Q) = 510;
+ (E => Q) = 339;
+ (F => Q) = 94;
+endspecify
+`endif
+`ifdef cyclone10gx
+specify
+ (A => Q) = 275;
+ (B => Q) = 272;
+ (C => Q) = 175;
+ (D => Q) = 165;
+ (E => Q) = 162;
+ (F => Q) = 53;
+endspecify
+`endif
+
+assign Q = LUT >> {F, E, D, C, B, A};
+
+endmodule
+
+
+(* abc9_lut=1, lib_whitebox *)
+module MISTRAL_ALUT5(input A, B, C, D, E, output Q);
+
+parameter [31:0] LUT = 32'h0000_0000;
+
+`ifdef cyclonev
+specify
+ (A => Q) = 584;
+ (B => Q) = 510;
+ (C => Q) = 510;
+ (D => Q) = 339;
+ (E => Q) = 94;
+endspecify
+`endif
+`ifdef cyclone10gx
+specify
+ (A => Q) = 272;
+ (B => Q) = 175;
+ (C => Q) = 165;
+ (D => Q) = 162;
+ (E => Q) = 53;
+endspecify
+`endif
+
+assign Q = LUT >> {E, D, C, B, A};
+
+endmodule
+
+
+(* abc9_lut=1, lib_whitebox *)
+module MISTRAL_ALUT4(input A, B, C, D, output Q);
+
+parameter [15:0] LUT = 16'h0000;
+
+`ifdef cyclonev
+specify
+ (A => Q) = 510;
+ (B => Q) = 510;
+ (C => Q) = 339;
+ (D => Q) = 94;
+endspecify
+`endif
+`ifdef cyclone10gx
+specify
+ (A => Q) = 175;
+ (B => Q) = 165;
+ (C => Q) = 162;
+ (D => Q) = 53;
+endspecify
+`endif
+
+assign Q = LUT >> {D, C, B, A};
+
+endmodule
+
+
+(* abc9_lut=1, lib_whitebox *)
+module MISTRAL_ALUT3(input A, B, C, output Q);
+
+parameter [7:0] LUT = 8'h00;
+
+`ifdef cyclonev
+specify
+ (A => Q) = 510;
+ (B => Q) = 339;
+ (C => Q) = 94;
+endspecify
+`endif
+`ifdef cyclone10gx
+specify
+ (A => Q) = 165;
+ (B => Q) = 162;
+ (C => Q) = 53;
+endspecify
+`endif
+
+assign Q = LUT >> {C, B, A};
+
+endmodule
+
+
+(* abc9_lut=1, lib_whitebox *)
+module MISTRAL_ALUT2(input A, B, output Q);
+
+parameter [3:0] LUT = 4'h0;
+
+`ifdef cyclonev
+specify
+ (A => Q) = 339;
+ (B => Q) = 94;
+endspecify
+`endif
+`ifdef cyclone10gx
+specify
+ (A => Q) = 162;
+ (B => Q) = 53;
+endspecify
+`endif
+
+assign Q = LUT >> {B, A};
+
+endmodule
+
+
+(* abc9_lut=1, lib_whitebox *)
+module MISTRAL_NOT(input A, output Q);
+
+`ifdef cyclonev
+specify
+ (A => Q) = 94;
+endspecify
+`endif
+`ifdef cyclone10gx
+specify
+ (A => Q) = 53;
+endspecify
+`endif
+
+assign Q = ~A;
+
+endmodule
+
+(* abc9_box, lib_whitebox *)
+module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO);
+
+parameter LUT0 = 16'h0000;
+parameter LUT1 = 16'h0000;
+
+`ifdef cyclonev
+specify
+ (A => SO) = 1283;
+ (B => SO) = 1167;
+ (C => SO) = 866;
+ (D0 => SO) = 756;
+ (D1 => SO) = 756;
+ (CI => SO) = 355;
+ (A => CO) = 950;
+ (B => CO) = 1039;
+ (C => CO) = 820;
+ (D0 => CO) = 1006;
+ (D1 => CO) = 1006;
+ (CI => CO) = 23;
+endspecify
+`endif
+`ifdef cyclone10gx
+specify
+ (A => SO) = 644;
+ (B => SO) = 477;
+ (C => SO) = 416;
+ (D0 => SO) = 380;
+ (D1 => SO) = 431;
+ (CI => SO) = 276;
+ (A => CO) = 525;
+ (B => CO) = 433;
+ (C => CO) = 712;
+ (D0 => CO) = 653;
+ (D1 => CO) = 593;
+ (CI => CO) = 16;
+endspecify
+`endif
+
+wire q0, q1;
+
+assign q0 = LUT0 >> {D0, C, B, A};
+assign q1 = LUT1 >> {D1, C, B, A};
+
+assign {CO, SO} = q0 + !q1 + CI;
+
+endmodule
+
+
+/*
+// A, B, C0, C1, E0, E1, F0, F1: data inputs
+// CARRYIN: carry input
+// SHAREIN: shared-arithmetic input
+// CLK0, CLK1, CLK2: clock inputs
+//
+// COMB0, COMB1: combinational outputs
+// FF0, FF1, FF2, FF3: DFF outputs
+// SUM0, SUM1: adder outputs
+// CARRYOUT: carry output
+// SHAREOUT: shared-arithmetic output
+module MISTRAL_ALM(
+ input A, B, C0, C1, E0, E1, F0, F1, CARRYIN, SHAREIN, // LUT path
+ input CLK0, CLK1, CLK2, AC0, AC1, // FF path
+ output COMB0, COMB1, SUM0, SUM1, CARRYOUT, SHAREOUT,
+ output FF0, FF1, FF2, FF3
+);
+
+parameter LUT0 = 16'b0000;
+parameter LUT1 = 16'b0000;
+parameter LUT2 = 16'b0000;
+parameter LUT3 = 16'b0000;
+
+parameter INIT0 = 1'b0;
+parameter INIT1 = 1'b0;
+parameter INIT2 = 1'b0;
+parameter INIT3 = 1'b0;
+
+parameter C0_MUX = "C0";
+parameter C1_MUX = "C1";
+
+parameter F0_MUX = "VCC";
+parameter F1_MUX = "GND";
+
+parameter FEEDBACK0 = "FF0";
+parameter FEEDBACK1 = "FF2";
+
+parameter ADD_MUX = "LUT";
+
+parameter DFF01_DATA_MUX = "COMB";
+parameter DFF23_DATA_MUX = "COMB";
+
+parameter DFF0_CLK = "CLK0";
+parameter DFF1_CLK = "CLK0";
+parameter DFF2_CLK = "CLK0";
+parameter DFF3_CLK = "CLK0";
+
+parameter DFF0_AC = "AC0";
+parameter DFF1_AC = "AC0";
+parameter DFF2_AC = "AC0";
+parameter DFF3_AC = "AC0";
+
+// Feedback muxes from the flip-flop outputs.
+wire ff_feedback_mux0, ff_feedback_mux1;
+
+// C-input muxes which can be set to also use the F-input.
+wire c0_input_mux, c1_input_mux;
+
+// F-input muxes which can be set to a constant to allow LUT5 use.
+wire f0_input_mux, f1_input_mux;
+
+// Adder input muxes to select between shared-arithmetic mode and arithmetic mode.
+wire add0_input_mux, add1_input_mux;
+
+// Combinational-output muxes for LUT #1 and LUT #3
+wire lut1_comb_mux, lut3_comb_mux;
+
+// Sum-output muxes for LUT #1 and LUT #3
+wire lut1_sum_mux, lut3_sum_mux;
+
+// DFF data-input muxes
+wire dff01_data_mux, dff23_data_mux;
+
+// DFF clock selectors
+wire dff0_clk, dff1_clk, dff2_clk, dff3_clk;
+
+// DFF asynchronous-clear selectors
+wire dff0_ac, dff1_ac, dff2_ac, dff3_ac;
+
+// LUT, DFF and adder output wires for routing.
+wire lut0_out, lut1a_out, lut1b_out, lut2_out, lut3a_out, lut3b_out;
+wire dff0_out, dff1_out, dff2_out, dff3_out;
+wire add0_sum, add1_sum, add0_carry, add1_carry;
+
+generate
+ if (FEEDBACK0 === "FF0")
+ assign ff_feedback_mux0 = dff0_out;
+ else if (FEEDBACK0 === "FF1")
+ assign ff_feedback_mux0 = dff1_out;
+ else
+ $error("Invalid FEEDBACK0 setting!");
+
+ if (FEEDBACK1 == "FF2")
+ assign ff_feedback_mux1 = dff2_out;
+ else if (FEEDBACK1 == "FF3")
+ assign ff_feedback_mux1 = dff3_out;
+ else
+ $error("Invalid FEEDBACK1 setting!");
+
+ if (C0_MUX === "C0")
+ assign c0_input_mux = C0;
+ else if (C0_MUX === "F1")
+ assign c0_input_mux = F1;
+ else if (C0_MUX === "FEEDBACK1")
+ assign c0_input_mux = ff_feedback_mux1;
+ else
+ $error("Invalid C0_MUX setting!");
+
+ if (C1_MUX === "C1")
+ assign c1_input_mux = C1;
+ else if (C1_MUX === "F0")
+ assign c1_input_mux = F0;
+ else if (C1_MUX === "FEEDBACK0")
+ assign c1_input_mux = ff_feedback_mux0;
+ else
+ $error("Invalid C1_MUX setting!");
+
+ // F0 == VCC is LUT5
+ // F0 == F0 is LUT6
+ // F0 == FEEDBACK is unknown
+ if (F0_MUX === "VCC")
+ assign f0_input_mux = 1'b1;
+ else if (F0_MUX === "F0")
+ assign f0_input_mux = F0;
+ else if (F0_MUX === "FEEDBACK0")
+ assign f0_input_mux = ff_feedback_mux0;
+ else
+ $error("Invalid F0_MUX setting!");
+
+ // F1 == GND is LUT5
+ // F1 == F1 is LUT6
+ // F1 == FEEDBACK is unknown
+ if (F1_MUX === "GND")
+ assign f1_input_mux = 1'b0;
+ else if (F1_MUX === "F1")
+ assign f1_input_mux = F1;
+ else if (F1_MUX === "FEEDBACK1")
+ assign f1_input_mux = ff_feedback_mux1;
+ else
+ $error("Invalid F1_MUX setting!");
+
+ if (ADD_MUX === "LUT") begin
+ assign add0_input_mux = ~lut1_sum_mux;
+ assign add1_input_mux = ~lut3_sum_mux;
+ end else if (ADD_MUX === "SHARE") begin
+ assign add0_input_mux = SHAREIN;
+ assign add1_input_mux = lut1_comb_mux;
+ end else
+ $error("Invalid ADD_MUX setting!");
+
+ if (DFF01_DATA_MUX === "COMB")
+ assign dff01_data_mux = COMB0;
+ else if (DFF01_DATA_MUX === "SUM")
+ assign dff01_data_mux = SUM0;
+ else
+ $error("Invalid DFF01_DATA_MUX setting!");
+
+ if (DFF23_DATA_MUX === "COMB")
+ assign dff23_data_mux = COMB0;
+ else if (DFF23_DATA_MUX === "SUM")
+ assign dff23_data_mux = SUM0;
+ else
+ $error("Invalid DFF23_DATA_MUX setting!");
+
+ if (DFF0_CLK === "CLK0")
+ assign dff0_clk = CLK0;
+ else if (DFF0_CLK === "CLK1")
+ assign dff0_clk = CLK1;
+ else if (DFF0_CLK === "CLK2")
+ assign dff0_clk = CLK2;
+ else
+ $error("Invalid DFF0_CLK setting!");
+
+ if (DFF1_CLK === "CLK0")
+ assign dff1_clk = CLK0;
+ else if (DFF1_CLK === "CLK1")
+ assign dff1_clk = CLK1;
+ else if (DFF1_CLK === "CLK2")
+ assign dff1_clk = CLK2;
+ else
+ $error("Invalid DFF1_CLK setting!");
+
+ if (DFF2_CLK === "CLK0")
+ assign dff2_clk = CLK0;
+ else if (DFF2_CLK === "CLK1")
+ assign dff2_clk = CLK1;
+ else if (DFF2_CLK === "CLK2")
+ assign dff2_clk = CLK2;
+ else
+ $error("Invalid DFF2_CLK setting!");
+
+ if (DFF3_CLK === "CLK0")
+ assign dff3_clk = CLK0;
+ else if (DFF3_CLK === "CLK1")
+ assign dff3_clk = CLK1;
+ else if (DFF3_CLK === "CLK2")
+ assign dff3_clk = CLK2;
+ else
+ $error("Invalid DFF3_CLK setting!");
+
+ if (DFF0_AC === "AC0")
+ assign dff0_ac = AC0;
+ else if (DFF0_AC === "AC1")
+ assign dff0_ac = AC1;
+ else
+ $error("Invalid DFF0_AC setting!");
+
+ if (DFF1_AC === "AC0")
+ assign dff1_ac = AC0;
+ else if (DFF1_AC === "AC1")
+ assign dff1_ac = AC1;
+ else
+ $error("Invalid DFF1_AC setting!");
+
+ if (DFF2_AC === "AC0")
+ assign dff2_ac = AC0;
+ else if (DFF2_AC === "AC1")
+ assign dff2_ac = AC1;
+ else
+ $error("Invalid DFF2_AC setting!");
+
+ if (DFF3_AC === "AC0")
+ assign dff3_ac = AC0;
+ else if (DFF3_AC === "AC1")
+ assign dff3_ac = AC1;
+ else
+ $error("Invalid DFF3_AC setting!");
+
+endgenerate
+
+// F0 on the Quartus diagram
+MISTRAL_ALUT4 #(.LUT(LUT0)) lut0 (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut0_out));
+
+// F2 on the Quartus diagram
+MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_comb (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut1_comb_mux));
+MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_sum (.A(A), .B(B), .C(C0), .D(E0), .Q(lut1_sum_mux));
+
+// F1 on the Quartus diagram
+MISTRAL_ALUT4 #(.LUT(LUT2)) lut2 (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut2_out));
+
+// F3 on the Quartus diagram
+MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_comb (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut3_comb_mux));
+MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_sum (.A(A), .B(B), .C(C1), .D(E1), .Q(lut3_sum_mux));
+
+MISTRAL_FF #(.INIT(INIT0)) dff0 (.D(dff01_data_mux), .CLK(dff0_clk), .ACn(dff0_ac), .Q(dff0_out));
+MISTRAL_FF #(.INIT(INIT1)) dff1 (.D(dff01_data_mux), .CLK(dff1_clk), .ACn(dff1_ac), .Q(dff1_out));
+MISTRAL_FF #(.INIT(INIT2)) dff2 (.D(dff23_data_mux), .CLK(dff2_clk), .ACn(dff2_ac), .Q(dff2_out));
+MISTRAL_FF #(.INIT(INIT3)) dff3 (.D(dff23_data_mux), .CLK(dff3_clk), .ACn(dff3_ac), .Q(dff3_out));
+
+// Adders
+assign {add0_carry, add0_sum} = CARRYIN + lut0_out + lut1_sum_mux;
+assign {add1_carry, add1_sum} = add0_carry + lut2_out + lut3_sum_mux;
+
+// COMBOUT outputs on the Quartus diagram
+assign COMB0 = E0 ? (f0_input_mux ? lut3_comb_mux : lut1_comb_mux)
+ : (f0_input_mux ? lut2_out : lut0_out);
+
+assign COMB1 = E1 ? (f1_input_mux ? lut3_comb_mux : lut1_comb_mux)
+ : (f1_input_mux ? lut2_out : lut0_out);
+
+// SUMOUT output on the Quartus diagram
+assign SUM0 = add0_sum;
+assign SUM1 = add1_sum;
+
+// COUT output on the Quartus diagram
+assign CARRYOUT = add1_carry;
+
+// SHAREOUT output on the Quartus diagram
+assign SHAREOUT = lut3_comb_mux;
+
+// REGOUT outputs on the Quartus diagram
+assign FF0 = dff0_out;
+assign FF1 = dff1_out;
+assign FF2 = dff2_out;
+assign FF3 = dff3_out;
+
+endmodule
+*/
diff --git a/techlibs/intel_alm/common/arith_alm_map.v b/techlibs/intel_alm/common/arith_alm_map.v
new file mode 100644
index 000000000..ddf81d9d0
--- /dev/null
+++ b/techlibs/intel_alm/common/arith_alm_map.v
@@ -0,0 +1,64 @@
+`default_nettype none
+
+module \$alu (A, B, CI, BI, X, Y, CO);
+
+parameter A_SIGNED = 0;
+parameter B_SIGNED = 0;
+parameter A_WIDTH = 1;
+parameter B_WIDTH = 1;
+parameter Y_WIDTH = 1;
+
+parameter _TECHMAP_CONSTMSK_CI_ = 0;
+parameter _TECHMAP_CONSTVAL_CI_ = 0;
+
+input [A_WIDTH-1:0] A;
+input [B_WIDTH-1:0] B;
+input CI, BI;
+output [Y_WIDTH-1:0] X, Y, CO;
+
+wire [Y_WIDTH-1:0] A_buf, B_buf;
+\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
+\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+wire [Y_WIDTH-1:0] AA = A_buf;
+wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
+wire [Y_WIDTH-1:0] BX = B_buf;
+wire [Y_WIDTH:0] ALM_CARRY;
+
+// Start of carry chain
+generate
+ if (_TECHMAP_CONSTMSK_CI_ == 1) begin
+ assign ALM_CARRY[0] = _TECHMAP_CONSTVAL_CI_;
+ end else begin
+ MISTRAL_ALUT_ARITH #(
+ .LUT0(16'b1010_1010_1010_1010), // Q = A
+ .LUT1(16'b0000_0000_0000_0000), // Q = 0 (LUT1's input to the adder is inverted)
+ ) alm_start (
+ .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1),
+ .CI(1'b0),
+ .CO(ALM_CARRY[0])
+ );
+ end
+endgenerate
+
+// Carry chain
+genvar i;
+generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
+ // TODO: mwk suggests that a pass could merge pre-adder logic into this.
+ MISTRAL_ALUT_ARITH #(
+ .LUT0(16'b1010_1010_1010_1010), // Q = A
+ .LUT1(16'b1100_0011_1100_0011), // Q = C ? B : ~B (LUT1's input to the adder is inverted)
+ ) alm_i (
+ .A(AA[i]), .B(BX[i]), .C(BI), .D0(1'b1), .D1(1'b1),
+ .CI(ALM_CARRY[i]),
+ .SO(Y[i]),
+ .CO(ALM_CARRY[i+1])
+ );
+
+ // ALM carry chain is not directly accessible, so calculate the carry through soft logic if really needed.
+ assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i]));
+end endgenerate
+
+assign X = AA ^ BB;
+
+endmodule
diff --git a/techlibs/intel_alm/common/bram_m10k.txt b/techlibs/intel_alm/common/bram_m10k.txt
new file mode 100644
index 000000000..837e3a330
--- /dev/null
+++ b/techlibs/intel_alm/common/bram_m10k.txt
@@ -0,0 +1,33 @@
+bram __MISTRAL_M10K_SDP
+ init 0 # TODO: Re-enable when I figure out how BRAM init works
+ abits 13 @D8192x1
+ dbits 1 @D8192x1
+ abits 12 @D4096x2
+ dbits 2 @D4096x2
+ abits 11 @D2048x4 @D2048x5
+ dbits 4 @D2048x4
+ dbits 5 @D2048x5
+ abits 10 @D1024x8 @D1024x10
+ dbits 8 @D1024x8
+ dbits 10 @D1024x10
+ abits 9 @D512x16 @D512x20
+ dbits 16 @D512x16
+ dbits 20 @D512x20
+ abits 8 @D256x32 @D256x40
+ dbits 32 @D256x32
+ dbits 40 @D256x40
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ # read enable; write enable + byte enables (only for multiples of 8)
+ enable 1 1
+ transp 0 0
+ clocks 1 1
+ clkpol 1 1
+endbram
+
+
+match __MISTRAL_M10K_SDP
+ min efficiency 5
+ make_transp
+endmatch
diff --git a/techlibs/intel_alm/common/bram_m10k_map.v b/techlibs/intel_alm/common/bram_m10k_map.v
new file mode 100644
index 000000000..e5566010d
--- /dev/null
+++ b/techlibs/intel_alm/common/bram_m10k_map.v
@@ -0,0 +1,31 @@
+module __MISTRAL_M10K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+parameter CFG_ABITS = 10;
+parameter CFG_DBITS = 10;
+parameter CFG_ENABLE_A = 1;
+parameter CFG_ENABLE_B = 1;
+
+input CLK1;
+input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
+input [CFG_DBITS-1:0] A1DATA;
+output [CFG_DBITS-1:0] B1DATA;
+input [CFG_ENABLE_A-1:0] A1EN, B1EN;
+
+altsyncram #(
+ .operation_mode("dual_port"),
+ .ram_block_type("m10k"),
+ .widthad_a(CFG_ABITS),
+ .width_a(CFG_DBITS),
+ .widthad_b(CFG_ABITS),
+ .width_b(CFG_DBITS),
+) _TECHMAP_REPLACE_ (
+ .address_a(A1ADDR),
+ .data_a(A1DATA),
+ .wren_a(A1EN),
+ .address_b(B1ADDR),
+ .q_b(B1DATA),
+ .clock0(CLK1),
+ .clock1(CLK1)
+);
+
+endmodule
diff --git a/techlibs/intel_alm/common/bram_m20k.txt b/techlibs/intel_alm/common/bram_m20k.txt
new file mode 100644
index 000000000..b4c5a5372
--- /dev/null
+++ b/techlibs/intel_alm/common/bram_m20k.txt
@@ -0,0 +1,33 @@
+bram __MISTRAL_M20K_SDP
+ init 1 # TODO: Re-enable when I figure out how BRAM init works
+ abits 14 @D16384x1
+ dbits 1 @D16384x1
+ abits 13 @D8192x2
+ dbits 2 @D8192x2
+ abits 12 @D4096x4 @D4096x5
+ dbits 4 @D4096x4
+ dbits 5 @D4096x5
+ abits 11 @D2048x8 @D2048x10
+ dbits 8 @D2048x8
+ dbits 10 @D2048x10
+ abits 10 @D1024x16 @D1024x20
+ dbits 16 @D1024x16
+ dbits 20 @D1024x20
+ abits 9 @D512x32 @D512x40
+ dbits 32 @D512x32
+ dbits 40 @D512x40
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ # read enable; write enable + byte enables (only for multiples of 8)
+ enable 1 1
+ transp 0 0
+ clocks 1 1
+ clkpol 1 1
+endbram
+
+
+match __MISTRAL_M20K_SDP
+ min efficiency 5
+ make_transp
+endmatch
diff --git a/techlibs/intel_alm/common/bram_m20k_map.v b/techlibs/intel_alm/common/bram_m20k_map.v
new file mode 100644
index 000000000..92f41310f
--- /dev/null
+++ b/techlibs/intel_alm/common/bram_m20k_map.v
@@ -0,0 +1,31 @@
+module __MISTRAL_M20K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+parameter CFG_ABITS = 10;
+parameter CFG_DBITS = 20;
+parameter CFG_ENABLE_A = 1;
+parameter CFG_ENABLE_B = 1;
+
+input CLK1;
+input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
+input [CFG_DBITS-1:0] A1DATA;
+output [CFG_DBITS-1:0] B1DATA;
+input [CFG_ENABLE_A-1:0] A1EN, B1EN;
+
+altsyncram #(
+ .operation_mode("dual_port"),
+ .ram_block_type("m20k"),
+ .widthad_a(CFG_ABITS),
+ .width_a(CFG_DBITS),
+ .widthad_b(CFG_ABITS),
+ .width_b(CFG_DBITS),
+) _TECHMAP_REPLACE_ (
+ .address_a(A1ADDR),
+ .data_a(A1DATA),
+ .wren_a(A1EN),
+ .address_b(B1ADDR),
+ .q_b(B1DATA),
+ .clock0(CLK1),
+ .clock1(CLK1)
+);
+
+endmodule
diff --git a/techlibs/intel_alm/common/dff_map.v b/techlibs/intel_alm/common/dff_map.v
new file mode 100644
index 000000000..f7f2fe3c3
--- /dev/null
+++ b/techlibs/intel_alm/common/dff_map.v
@@ -0,0 +1,124 @@
+`default_nettype none
+
+// D flip-flops
+module \$_DFF_P_ (input D, C, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFF_P_ with INIT=1");
+endmodule
+
+module \$_DFF_N_ (input D, C, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFF_N_ with INIT=1");
+endmodule
+
+// D flip-flops with reset
+module \$_DFF_PP0_ (input D, C, R, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFF_PP0_ with INIT=1");
+endmodule
+
+module \$_DFF_PN0_ (input D, C, R, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFF_PN0_ with INIT=1");
+endmodule
+
+module \$_DFF_NP0_ (input D, C, R, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFF_NP0_ with INIT=1");
+endmodule
+
+module \$_DFF_NN0_ (input D, C, R, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFF_NN0_ with INIT=1");
+endmodule
+
+// D flip-flops with set
+module \$_DFF_PP1_ (input D, C, R, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ wire Q_tmp;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
+ assign Q = ~Q_tmp;
+end else $error("Unsupported flop: $_DFF_PP1_ with INIT=0");
+endmodule
+
+module \$_DFF_PN1_ (input D, C, R, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ wire Q_tmp;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
+end else $error("Unsupported flop: $_DFF_PN1_ with INIT=0");
+endmodule
+
+module \$_DFF_NP1_ (input D, C, R, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ wire Q_tmp;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
+ assign Q = ~Q_tmp;
+end else $error("Unsupported flop: $_DFF_NP1_ with INIT=0");
+endmodule
+
+module \$_DFF_NN1_ (input D, C, R, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ wire Q_tmp;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
+ assign Q = ~Q_tmp;
+end else $error("Unsupported flop: $_DFF_NN1_ with INIT=0");
+endmodule
+
+// D flip-flops with clock enable
+module \$_DFFE_PP_ (input D, C, E, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFFE_PP_ with INIT=1");
+endmodule
+
+module \$_DFFE_PN_ (input D, C, E, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFFE_PN_ with INIT=1");
+endmodule
+
+module \$_DFFE_NP_ (input D, C, E, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFFE_NP_ with INIT=1");
+endmodule
+
+module \$_DFFE_NN_ (input D, C, E, output Q);
+parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
+if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
+end else $error("Unsupported flop: $_DFFE_NN_ with INIT=1");
+endmodule
diff --git a/techlibs/intel_alm/common/dff_sim.v b/techlibs/intel_alm/common/dff_sim.v
new file mode 100644
index 000000000..07865905f
--- /dev/null
+++ b/techlibs/intel_alm/common/dff_sim.v
@@ -0,0 +1,48 @@
+// DATAIN: synchronous data input
+// CLK: clock input (positive edge)
+// ACLR: asynchronous clear (negative-true)
+// ENA: clock-enable
+// SCLR: synchronous clear
+// SLOAD: synchronous load
+// SDATA: synchronous load data
+//
+// Q: data output
+//
+// Note: the DFFEAS primitive is mostly emulated; it does not reflect what the hardware implements.
+module MISTRAL_FF(
+ input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA,
+ output reg Q
+);
+
+`ifdef cyclonev
+specify
+ (posedge CLK => (Q : DATAIN)) = 262;
+ $setup(DATAIN, posedge CLK, 522);
+endspecify
+`endif
+`ifdef cyclone10gx
+specify
+ (posedge CLK => (Q : DATAIN)) = 219;
+ $setup(DATAIN, posedge CLK, 268);
+endspecify
+`endif
+
+initial begin
+ // Altera flops initialise to zero.
+ Q = 0;
+end
+
+always @(posedge CLK, negedge ACLR) begin
+ // Asynchronous clear
+ if (!ACLR) Q <= 0;
+ // Clock-enable
+ else if (ENA) begin
+ // Synchronous clear
+ if (SCLR) Q <= 0;
+ // Synchronous load
+ else if (SLOAD) Q <= SDATA;
+ else Q <= DATAIN;
+ end
+end
+
+endmodule
diff --git a/techlibs/intel_alm/common/lutram_mlab.txt b/techlibs/intel_alm/common/lutram_mlab.txt
new file mode 100644
index 000000000..1d6174d85
--- /dev/null
+++ b/techlibs/intel_alm/common/lutram_mlab.txt
@@ -0,0 +1,20 @@
+bram __MISTRAL_MLAB
+ init 0 # TODO: Re-enable when I figure out how LUTRAM init works
+ abits 5
+ dbits 16 @D32x16
+ dbits 18 @D32x18
+ dbits 20 @D32x20
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ # read enable
+ enable 1 0
+ transp 1 0
+ clocks 1 2
+ clkpol 1 1
+endbram
+
+match __MISTRAL_MLAB
+ min efficiency 5
+ make_outreg
+endmatch
diff --git a/techlibs/intel_alm/common/lutram_mlab_map.v b/techlibs/intel_alm/common/lutram_mlab_map.v
new file mode 100644
index 000000000..3a9c8590e
--- /dev/null
+++ b/techlibs/intel_alm/common/lutram_mlab_map.v
@@ -0,0 +1,29 @@
+module __MISTRAL_MLAB(CLK1, CLK2, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA);
+
+parameter CFG_ABITS = 5;
+parameter CFG_DBITS = 20;
+
+input CLK1, CLK2;
+input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
+input [CFG_DBITS-1:0] A1DATA;
+input A1EN;
+output [CFG_DBITS-1:0] B1DATA;
+
+altsyncram #(
+ .operation_mode("dual_port"),
+ .ram_block_type("mlab"),
+ .widthad_a(CFG_ABITS),
+ .width_a(CFG_DBITS),
+ .widthad_b(CFG_ABITS),
+ .width_b(CFG_DBITS),
+) _TECHMAP_REPLACE_ (
+ .address_a(A1ADDR),
+ .data_a(A1DATA),
+ .wren_a(A1EN),
+ .address_b(B1ADDR),
+ .q_b(B1DATA),
+ .clock0(CLK1),
+ .clock1(CLK1),
+);
+
+endmodule
diff --git a/techlibs/intel_alm/common/megafunction_bb.v b/techlibs/intel_alm/common/megafunction_bb.v
new file mode 100644
index 000000000..21ba73a09
--- /dev/null
+++ b/techlibs/intel_alm/common/megafunction_bb.v
@@ -0,0 +1,108 @@
+// Intel megafunction declarations, to avoid Yosys complaining.
+`default_nettype none
+
+(* blackbox *)
+module altera_std_synchronizer(clk, din, dout, reset_n);
+
+parameter depth = 2;
+
+input clk;
+input reset_n;
+input din;
+output dout;
+
+endmodule
+
+(* blackbox *)
+module altiobuf_in(datain, dataout);
+
+parameter enable_bus_hold = "FALSE";
+parameter use_differential_mode = "FALSE";
+parameter number_of_channels = 1;
+
+input [number_of_channels-1:0] datain;
+output [number_of_channels-1:0] dataout;
+
+endmodule
+
+(* blackbox *)
+module altiobuf_out(datain, dataout);
+
+parameter enable_bus_hold = "FALSE";
+parameter use_differential_mode = "FALSE";
+parameter use_oe = "FALSE";
+parameter number_of_channels = 1;
+
+input [number_of_channels-1:0] datain;
+output [number_of_channels-1:0] dataout;
+
+endmodule
+
+(* blackbox *)
+module altiobuf_bidir(dataio, oe, datain, dataout);
+
+parameter number_of_channels = 1;
+parameter enable_bus_hold = "OFF";
+
+inout [number_of_channels-1:0] dataio;
+input [number_of_channels-1:0] datain;
+output [number_of_channels-1:0] dataout;
+input [number_of_channels-1:0] oe;
+
+endmodule
+
+(* blackbox *)
+module altsyncram(clock0, clock1, address_a, data_a, rden_a, wren_a, byteena_a, q_a, addressstall_a, address_b, data_b, rden_b, wren_b, byteena_b, q_b, addressstall_b, clocken0, clocken1, clocken2, clocken3, aclr0, aclr1, eccstatus);
+
+parameter lpm_type = "altsyncram";
+parameter operation_mode = "dual_port";
+parameter ram_block_type = "auto";
+parameter intended_device_family = "auto";
+parameter power_up_uninitialized = "false";
+parameter read_during_write_mode_mixed_ports = "dontcare";
+parameter byte_size = 8;
+parameter widthad_a = 1;
+parameter width_a = 1;
+parameter width_byteena_a = 1;
+parameter numwords_a = 1;
+parameter clock_enable_input_a = "clocken0";
+parameter widthad_b = 1;
+parameter width_b = 1;
+parameter numwords_b = 1;
+parameter address_aclr_b = "aclr0";
+parameter address_reg_b = "";
+parameter outdata_aclr_b = "aclr0";
+parameter outdata_reg_b = "";
+parameter clock_enable_input_b = "clocken0";
+parameter clock_enable_output_b = "clocken0";
+
+input clock0, clock1;
+input [widthad_a-1:0] address_a;
+input [width_a-1:0] data_a;
+input rden_a;
+input wren_a;
+input [(width_a/8)-1:0] byteena_a;
+input addressstall_a;
+
+output [width_a-1:0] q_a;
+
+input wren_b;
+input rden_b;
+input [widthad_b-1:0] address_b;
+input [width_b-1:0] data_b;
+input [(width_b/8)-1:0] byteena_b;
+input addressstall_b;
+
+output [width_b-1:0] q_b;
+
+input clocken0;
+input clocken1;
+input clocken2;
+input clocken3;
+
+input aclr0;
+input aclr1;
+
+output eccstatus;
+
+endmodule
diff --git a/techlibs/intel_alm/common/quartus_rename.v b/techlibs/intel_alm/common/quartus_rename.v
new file mode 100644
index 000000000..d9961c174
--- /dev/null
+++ b/techlibs/intel_alm/common/quartus_rename.v
@@ -0,0 +1,19 @@
+module __MISTRAL_VCC(output Q);
+
+MISTRAL_ALUT2 #(.LUT(4'b1111)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q));
+
+endmodule
+
+
+module __MISTRAL_GND(output Q);
+
+MISTRAL_ALUT2 #(.LUT(4'b0000)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q));
+
+endmodule
+
+
+module MISTRAL_FF(input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, output reg Q);
+
+dffeas #(.power_up("low"), .is_wysiwyg("true")) _TECHMAP_REPLACE_ (.d(DATAIN), .clk(CLK), .clrn(ACLR), .ena(ENA), .sclr(SCLR), .sload(SLOAD), .asdata(SDATA), .q(Q));
+
+endmodule
diff --git a/techlibs/intel_alm/cyclone10gx/quartus_rename.v b/techlibs/intel_alm/cyclone10gx/quartus_rename.v
new file mode 100644
index 000000000..3fbc508ed
--- /dev/null
+++ b/techlibs/intel_alm/cyclone10gx/quartus_rename.v
@@ -0,0 +1,54 @@
+module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q);
+parameter LUT = 64'h0000_0000_0000_0000;
+
+cyclone10gx_lcell_comb #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT5(input A, B, C, D, E, output Q);
+parameter LUT = 32'h0000_0000;
+
+cyclone10gx_lcell_comb #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT4(input A, B, C, D, output Q);
+parameter LUT = 16'h0000;
+
+cyclone10gx_lcell_comb #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT3(input A, B, C, output Q);
+parameter LUT = 8'h00;
+
+cyclone10gx_lcell_comb #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT2(input A, B, output Q);
+parameter LUT = 4'h0;
+
+cyclone10gx_lcell_comb #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_NOT(input A, output Q);
+
+NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO);
+parameter LUT0 = 16'h0000;
+parameter LUT1 = 16'h0000;
+
+cyclone10gx_lcell_comb #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO));
+
+endmodule
diff --git a/techlibs/intel_alm/cyclonev/quartus_rename.v b/techlibs/intel_alm/cyclonev/quartus_rename.v
new file mode 100644
index 000000000..6eff375e1
--- /dev/null
+++ b/techlibs/intel_alm/cyclonev/quartus_rename.v
@@ -0,0 +1,54 @@
+module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q);
+parameter LUT = 64'h0000_0000_0000_0000;
+
+cyclonev_lcell_comb #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT5(input A, B, C, D, E, output Q);
+parameter LUT = 32'h0000_0000;
+
+cyclonev_lcell_comb #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT4(input A, B, C, D, output Q);
+parameter LUT = 16'h0000;
+
+cyclonev_lcell_comb #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT3(input A, B, C, output Q);
+parameter LUT = 8'h00;
+
+cyclonev_lcell_comb #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT2(input A, B, output Q);
+parameter LUT = 4'h0;
+
+cyclonev_lcell_comb #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_NOT(input A, output Q);
+
+NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO);
+parameter LUT0 = 16'h0000;
+parameter LUT1 = 16'h0000;
+
+cyclonev_lcell_comb #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO));
+
+endmodule
diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc
new file mode 100644
index 000000000..47aa11500
--- /dev/null
+++ b/techlibs/intel_alm/synth_intel_alm.cc
@@ -0,0 +1,241 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Claire Wolf <claire@symbioticeda.com>
+ * Copyright (C) 2019 Dan Ravensloft <dan.ravensloft@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/celltypes.h"
+#include "kernel/log.h"
+#include "kernel/register.h"
+#include "kernel/rtlil.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct SynthIntelALMPass : public ScriptPass {
+ SynthIntelALMPass() : ScriptPass("synth_intel_alm", "synthesis for ALM-based Intel (Altera) FPGAs.") {}
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_intel_alm [options]\n");
+ log("\n");
+ log("This command runs synthesis for ALM-based Intel FPGAs.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module (default='top')\n");
+ log("\n");
+ log(" -family <family>\n");
+ log(" target one of:\n");
+ log(" \"cyclonev\" - Cyclone V (default)\n");
+ log(" \"cyclone10gx\" - Cyclone 10GX\n");
+ log("\n");
+ log(" -quartus\n");
+ log(" output a netlist using Quartus cells instead of MISTRAL_* cells\n");
+ log("\n");
+ log(" -vqm <file>\n");
+ log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
+ log(" output file is omitted if this parameter is not specified. Implies -quartus.\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\n");
+ log(" only run the commands between the labels (see below). an empty\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("\n");
+ log(" -nolutram\n");
+ log(" do not use LUT RAM cells in output netlist\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use block RAM cells in output netlist\n");
+ log("\n");
+ log(" -noflatten\n");
+ log(" do not flatten design before synthesis\n");
+ log("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, family_opt, bram_type, vout_file;
+ bool flatten, quartus, nolutram, nobram;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ family_opt = "cyclonev";
+ bram_type = "m10k";
+ vout_file = "";
+ flatten = true;
+ quartus = false;
+ nolutram = false;
+ nobram = false;
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ string run_from, run_to;
+ clear_flags();
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-family" && argidx + 1 < args.size()) {
+ family_opt = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-top" && argidx + 1 < args.size()) {
+ top_opt = "-top " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-vqm" && argidx + 1 < args.size()) {
+ quartus = true;
+ vout_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-run" && argidx + 1 < args.size()) {
+ size_t pos = args[argidx + 1].find(':');
+ if (pos == std::string::npos)
+ break;
+ run_from = args[++argidx].substr(0, pos);
+ run_to = args[argidx].substr(pos + 1);
+ continue;
+ }
+ if (args[argidx] == "-quartus") {
+ quartus = true;
+ continue;
+ }
+ if (args[argidx] == "-nolutram") {
+ nolutram = true;
+ continue;
+ }
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ flatten = false;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (!design->full_selection())
+ log_cmd_error("This command only operates on fully selected designs!\n");
+
+ if (family_opt == "cyclonev") {
+ bram_type = "m10k";
+ } else if (family_opt == "cyclone10gx") {
+ bram_type = "m20k";
+ } else {
+ log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str());
+ }
+
+ log_header(design, "Executing SYNTH_INTEL_ALM pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() YS_OVERRIDE
+ {
+ if (help_mode) {
+ family_opt = "<family>";
+ bram_type = "<bram_type>";
+ }
+
+ if (check_label("begin")) {
+ run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str()));
+ run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str()));
+ run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str()));
+
+ // Misc and common cells
+ run("read_verilog -lib +/intel/common/altpll_bb.v");
+ run("read_verilog -lib +/intel_alm/common/megafunction_bb.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
+
+ if (flatten && check_label("flatten", "(unless -noflatten)")) {
+ run("proc");
+ run("flatten");
+ run("tribuf -logic");
+ run("deminout");
+ }
+
+ if (check_label("coarse")) {
+ run("synth -run coarse -lut 6");
+ run("techmap -map +/intel_alm/common/arith_alm_map.v");
+ }
+
+ if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
+ run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str()));
+ run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str()));
+ }
+
+ if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) {
+ run("memory_bram -rules +/intel_alm/common/lutram_mlab.txt", "(for Cyclone V / Cyclone 10GX)");
+ run("techmap -map +/intel_alm/common/lutram_mlab_map.v", "(for Cyclone V / Cyclone 10GX)");
+ }
+
+ if (check_label("map_ffram")) {
+ run("memory_map");
+ run("opt -full");
+ }
+
+ if (check_label("map_ffs")) {
+ run("dff2dffe -direct-match $_DFF_*");
+ run("zinit");
+ run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v");
+ run("opt -full -undriven -mux_undef");
+ run("clean -purge");
+ }
+
+ if (check_label("map_luts")) {
+ run("read_verilog -icells -specify -lib +/abc9_model.v");
+ run("abc9 -maxlut 6 -W 200");
+ run("techmap -map +/intel_alm/common/alm_map.v");
+ run("opt -fast");
+ run("autoname");
+ run("clean");
+ }
+
+ if (check_label("check")) {
+ run("hierarchy -check");
+ run("stat");
+ run("check");
+ }
+
+ if (check_label("quartus")) {
+ if (quartus || help_mode) {
+ run("setundef -zero");
+ run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q");
+ run("techmap -map +/intel_alm/common/quartus_rename.v");
+ run(stringf("techmap -map +/intel_alm/%s/quartus_rename.v", family_opt.c_str()));
+ }
+ }
+
+ if (check_label("vqm")) {
+ if (!vout_file.empty() || help_mode) {
+ run(stringf("write_verilog -attr2comment -defparam -nohex -decimal %s", help_mode ? "<file-name>" : vout_file.c_str()));
+ }
+ }
+ }
+} SynthIntelALMPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc
index 5efa005c8..34a7e68be 100644
--- a/techlibs/sf2/synth_sf2.cc
+++ b/techlibs/sf2/synth_sf2.cc
@@ -187,7 +187,6 @@ struct SynthSf2Pass : public ScriptPass
if (check_label("map_ffs"))
{
- run("dffsr2dff");
run("techmap -D NO_LUT -map +/sf2/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index ac4f5bcf4..1c190d37e 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -522,10 +522,9 @@ struct SynthXilinxPass : public ScriptPass
}
if (check_label("map_ffram")) {
- // Required for dffsr2dff to work.
+ // Required for dff2dffs to work.
run("simplemap t:$dff t:$adff t:$mux");
// Needs to be done before opt -mux_bool happens.
- run("dffsr2dff");
if (help_mode)
run("dff2dffs [-match-init]", "(-match-init for xc6s only)");
else if (family == "xc6s")
diff --git a/tests/arch/common/blockram.v b/tests/arch/common/blockram.v
index dbc6ca65c..5ed0736d0 100644
--- a/tests/arch/common/blockram.v
+++ b/tests/arch/common/blockram.v
@@ -5,19 +5,20 @@ module sync_ram_sp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
input wire [ADDRESS_WIDTH-1:0] address_in,
output wire [DATA_WIDTH-1:0] data_out);
- localparam WORD = (DATA_WIDTH-1);
- localparam DEPTH = (2**ADDRESS_WIDTH-1);
+ localparam WORD = (DATA_WIDTH-1);
+ localparam DEPTH = (2**ADDRESS_WIDTH-1);
- reg [WORD:0] data_out_r;
- reg [WORD:0] memory [0:DEPTH];
+ reg [WORD:0] data_out_r;
+ reg [WORD:0] memory [0:DEPTH];
- always @(posedge clk) begin
- if (write_enable)
- memory[address_in] <= data_in;
- data_out_r <= memory[address_in];
- end
+ always @(posedge clk) begin
+ if (write_enable)
+ memory[address_in] <= data_in;
+ data_out_r <= memory[address_in];
+ end
+
+ assign data_out = data_out_r;
- assign data_out = data_out_r;
endmodule // sync_ram_sp
@@ -28,18 +29,19 @@ module sync_ram_sdp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
input wire [ADDRESS_WIDTH-1:0] address_in_r, address_in_w,
output wire [DATA_WIDTH-1:0] data_out);
- localparam WORD = (DATA_WIDTH-1);
- localparam DEPTH = (2**ADDRESS_WIDTH-1);
+ localparam WORD = (DATA_WIDTH-1);
+ localparam DEPTH = (2**ADDRESS_WIDTH-1);
+
+ reg [WORD:0] data_out_r;
+ reg [WORD:0] memory [0:DEPTH];
- reg [WORD:0] data_out_r;
- reg [WORD:0] memory [0:DEPTH];
+ always @(posedge clk) begin
+ if (write_enable)
+ memory[address_in_w] <= data_in;
+ data_out_r <= memory[address_in_r];
+ end
- always @(posedge clk) begin
- if (write_enable)
- memory[address_in_w] <= data_in;
- data_out_r <= memory[address_in_r];
- end
+ assign data_out = data_out_r;
- assign data_out = data_out_r;
endmodule // sync_ram_sdp
diff --git a/tests/arch/common/blockrom.v b/tests/arch/common/blockrom.v
new file mode 100644
index 000000000..93f5c9ddf
--- /dev/null
+++ b/tests/arch/common/blockrom.v
@@ -0,0 +1,31 @@
+`default_nettype none
+module sync_rom #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
+ (input wire clk,
+ input wire [ADDRESS_WIDTH-1:0] address_in,
+ output wire [DATA_WIDTH-1:0] data_out);
+
+ localparam WORD = (DATA_WIDTH-1);
+ localparam DEPTH = (2**ADDRESS_WIDTH-1);
+
+ reg [WORD:0] data_out_r;
+ reg [WORD:0] memory [0:DEPTH];
+
+ integer i,j = 64'hF4B1CA8127865242;
+ initial
+ for (i = 0; i <= DEPTH; i++) begin
+ // In case this ROM will be implemented in fabric: fill the memory with some data
+ // uncorrelated with the address, or Yosys might see through the ruse and e.g. not
+ // emit any LUTs at all for `memory[i] = i;`, just a latch.
+ memory[i] = j * 64'h2545F4914F6CDD1D;
+ j = j ^ (j >> 12);
+ j = j ^ (j << 25);
+ j = j ^ (j >> 27);
+ end
+
+ always @(posedge clk) begin
+ data_out_r <= memory[address_in];
+ end
+
+ assign data_out = data_out_r;
+
+endmodule // sync_rom
diff --git a/tests/arch/ecp5/memories.ys b/tests/arch/ecp5/memories.ys
new file mode 100644
index 000000000..e1f748e26
--- /dev/null
+++ b/tests/arch/ecp5/memories.ys
@@ -0,0 +1,330 @@
+# ================================ RAM ================================
+# RAM bits <= 18K; Data width <= 36; Address width <= 9: -> PDPW16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_ram_sdp
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:PDPW16KD
+
+## With parameters
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:PDPW16KD # too inefficient
+select -assert-count 9 t:TRELLIS_DPR16X4
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+setattr -set syn_ramstyle "block_ram" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:PDPW16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+setattr -set syn_ramstyle "Block_RAM" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:PDPW16KD # any case works
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+setattr -set ram_block 1 m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:PDPW16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+setattr -set syn_ramstyle "registers" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:PDPW16KD # requested FFRAM explicitly
+select -assert-count 180 t:TRELLIS_FF
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+setattr -set logic_block 1 m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:PDPW16KD # requested FFRAM explicitly
+select -assert-count 180 t:TRELLIS_FF
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+setattr -set syn_romstyle "ebr" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BROM but this is a RAM
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+setattr -set rom_block 1 m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BROM but this is a RAM
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+setattr -set syn_ramstyle "block_ram" m:memory
+synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+setattr -set ram_block 1 m:memory
+synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+
+# RAM bits <= 18K; Data width <= 18; Address width <= 10: -> DP16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:DP16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 9 sync_ram_sdp
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:DP16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 12 -set DATA_WIDTH 4 sync_ram_sdp
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:DP16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 13 -set DATA_WIDTH 2 sync_ram_sdp
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:DP16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 14 -set DATA_WIDTH 1 sync_ram_sdp
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:DP16KD
+
+## With parameters
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:DP16KD # too inefficient
+select -assert-count 5 t:TRELLIS_DPR16X4
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+setattr -set syn_ramstyle "block_ram" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:DP16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+setattr -set syn_ramstyle "Block_RAM" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:DP16KD # any case works
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+setattr -set ram_block 1 m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:DP16KD
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+setattr -set syn_ramstyle "registers" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:DP16KD # requested FFRAM explicitly
+select -assert-count 90 t:TRELLIS_FF
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+setattr -set logic_block 1 m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:DP16KD # requested FFRAM explicitly
+select -assert-count 90 t:TRELLIS_FF
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+setattr -set syn_romstyle "ebr" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BROM but this is a RAM
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+setattr -set rom_block 1 m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BROM but this is a RAM
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+setattr -set syn_ramstyle "block_ram" m:memory
+synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+setattr -set ram_block 1 m:memory
+synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+
+# RAM bits <= 64; Data width <= 4; Address width <= 4: -> DPR16X4
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:TRELLIS_DPR16X4
+
+## With parameters
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+setattr -set syn_ramstyle "distributed" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:TRELLIS_DPR16X4
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+setattr -set syn_ramstyle "registers" m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:TRELLIS_DPR16X4 # requested FFRAM explicitly
+select -assert-count 68 t:TRELLIS_FF
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+setattr -set logic_block 1 m:memory
+synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:TRELLIS_DPR16X4 # requested FFRAM explicitly
+select -assert-count 68 t:TRELLIS_FF
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+setattr -set syn_ramstyle "distributed" m:memory
+synth_ecp5 -top sync_ram_sdp -nolutram; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested LUTRAM but LUTRAM is disabled
+
+# ================================ ROM ================================
+# ROM bits <= 18K; Data width <= 36; Address width <= 9: -> PDPW16KD
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_rom
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:PDPW16KD
+
+## With parameters
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom
+write_ilang
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 0 t:PDPW16KD # too inefficient
+select -assert-min 18 t:LUT4
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+setattr -set syn_romstyle "ebr" m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:PDPW16KD
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+setattr -set rom_block 1 m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:PDPW16KD
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom
+setattr -set syn_romstyle "logic" m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 0 t:PDPW16KD # requested LUTROM explicitly
+select -assert-min 18 t:LUT4
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom
+setattr -set logic_block 1 m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 0 t:PDPW16KD # requested LUTROM explicitly
+select -assert-min 18 t:LUT4
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+setattr -set syn_ramstyle "block_ram" m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+setattr -set ram_block 1 m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+setattr -set syn_ramstyle "block_rom" m:memory
+synth_ecp5 -top sync_rom -nobram; cd sync_rom
+select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+setattr -set rom_block 1 m:memory
+synth_ecp5 -top sync_rom -nobram; cd sync_rom
+select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+
+# ROM bits <= 18K; Data width <= 18; Address width <= 10: -> DP16KD
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_rom
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:DP16KD
+
+## With parameters
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom
+write_ilang
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 0 t:DP16KD # too inefficient
+select -assert-min 9 t:LUT4
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+setattr -set syn_romstyle "ebr" m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:DP16KD
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+setattr -set rom_block 1 m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:DP16KD
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom
+setattr -set syn_romstyle "logic" m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 0 t:DP16KD # requested LUTROM explicitly
+select -assert-min 9 t:LUT4
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom
+setattr -set logic_block 1 m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 0 t:DP16KD # requested LUTROM explicitly
+select -assert-min 9 t:LUT4
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+setattr -set syn_ramstyle "block_ram" m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+setattr -set ram_block 1 m:memory
+synth_ecp5 -top sync_rom; cd sync_rom
+select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+setattr -set syn_ramstyle "block_rom" m:memory
+synth_ecp5 -top sync_rom -nobram; cd sync_rom
+select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+setattr -set rom_block 1 m:memory
+synth_ecp5 -top sync_rom -nobram; cd sync_rom
+select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
diff --git a/tests/arch/ice40/lutram.ys b/tests/arch/ice40/lutram.ys
deleted file mode 100644
index 1ba40f8ec..000000000
--- a/tests/arch/ice40/lutram.ys
+++ /dev/null
@@ -1,15 +0,0 @@
-read_verilog ../common/lutram.v
-hierarchy -top lutram_1w1r
-proc
-memory -nomap
-equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40
-memory
-opt -full
-
-miter -equiv -flatten -make_assert -make_outputs gold gate miter
-sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
-
-design -load postopt
-cd lutram_1w1r
-select -assert-count 1 t:SB_RAM40_4K
-select -assert-none t:SB_RAM40_4K %% t:* %D
diff --git a/tests/arch/ice40/memories.ys b/tests/arch/ice40/memories.ys
new file mode 100644
index 000000000..571edec1d
--- /dev/null
+++ b/tests/arch/ice40/memories.ys
@@ -0,0 +1,168 @@
+# ================================ RAM ================================
+# RAM bits <= 4K; Data width <= 16; Address width <= 11: -> SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 2 sync_ram_sdp
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 4 sync_ram_sdp
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 8 sync_ram_sdp
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 16 sync_ram_sdp
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:SB_RAM40_4K
+
+## With parameters
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:SB_RAM40_4K # too inefficient
+select -assert-min 1 t:SB_DFFE
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+setattr -set syn_ramstyle "block_ram" m:memory
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+setattr -set syn_ramstyle "Block_RAM" m:memory
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:SB_RAM40_4K # any case works
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+setattr -set ram_block 1 m:memory
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+setattr -set syn_ramstyle "registers" m:memory
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly
+select -assert-min 1 t:SB_DFFE
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+setattr -set logic_block 1 m:memory
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly
+select -assert-min 1 t:SB_DFFE
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+setattr -set syn_romstyle "ebr" m:memory
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BROM but this is a RAM
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+setattr -set rom_block 1 m:memory
+synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BROM but this is a RAM
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+setattr -set syn_ramstyle "block_ram" m:memory
+synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+
+design -reset; read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+setattr -set ram_block 1 m:memory
+synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp
+select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+
+# ================================ ROM ================================
+# ROM bits <= 4K; Data width <= 16; Address width <= 11: -> SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 2 sync_rom
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 4 sync_rom
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 8 sync_rom
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 16 sync_rom
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 1 t:SB_RAM40_4K
+
+## With parameters
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+write_ilang
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 0 t:SB_RAM40_4K # too inefficient
+select -assert-min 1 t:SB_LUT4
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+setattr -set syn_romstyle "ebr" m:memory
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+setattr -set rom_block 1 m:memory
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 1 t:SB_RAM40_4K
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+setattr -set syn_romstyle "logic" m:memory
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly
+select -assert-min 1 t:SB_LUT4
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+setattr -set logic_block 1 m:memory
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly
+select -assert-min 1 t:SB_LUT4
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+setattr -set syn_ramstyle "block_ram" m:memory
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+setattr -set ram_block 1 m:memory
+synth_ice40 -top sync_rom; cd sync_rom
+select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+setattr -set syn_romstyle "ebr" m:memory
+synth_ice40 -top sync_rom -nobram; cd sync_rom
+select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+
+design -reset; read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+setattr -set rom_block 1 m:memory
+synth_ice40 -top sync_rom -nobram; cd sync_rom
+select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
diff --git a/tests/arch/intel_alm/add_sub.ys b/tests/arch/intel_alm/add_sub.ys
new file mode 100644
index 000000000..4cb2c2e0d
--- /dev/null
+++ b/tests/arch/intel_alm/add_sub.ys
@@ -0,0 +1,8 @@
+read_verilog ../common/add_sub.v
+hierarchy -top top
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+stat
+select -assert-count 8 t:MISTRAL_ALUT_ARITH
+select -assert-none t:MISTRAL_ALUT_ARITH %% t:* %D
diff --git a/tests/arch/intel_alm/adffs.ys b/tests/arch/intel_alm/adffs.ys
new file mode 100644
index 000000000..5d8d3a220
--- /dev/null
+++ b/tests/arch/intel_alm/adffs.ys
@@ -0,0 +1,48 @@
+read_verilog ../common/adffs.v
+design -save read
+
+hierarchy -top adff
+proc
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd adff # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_FF
+select -assert-count 1 t:MISTRAL_NOT
+
+select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D
+
+
+design -load read
+hierarchy -top adffn
+proc
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd adffn # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_FF
+
+select -assert-none t:MISTRAL_FF %% t:* %D
+
+
+design -load read
+hierarchy -top dffs
+proc
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dffs # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_FF
+select -assert-count 1 t:MISTRAL_ALUT2
+
+select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 %% t:* %D
+
+
+design -load read
+hierarchy -top ndffnr
+proc
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd ndffnr # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_FF
+select -assert-count 1 t:MISTRAL_NOT
+select -assert-count 1 t:MISTRAL_ALUT2
+
+select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 %% t:* %D
diff --git a/tests/arch/intel_alm/counter.ys b/tests/arch/intel_alm/counter.ys
new file mode 100644
index 000000000..945c318d8
--- /dev/null
+++ b/tests/arch/intel_alm/counter.ys
@@ -0,0 +1,13 @@
+read_verilog ../common/counter.v
+hierarchy -top top
+proc
+flatten
+equiv_opt -async2sync -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+
+select -assert-count 2 t:MISTRAL_NOT
+select -assert-count 8 t:MISTRAL_ALUT_ARITH
+select -assert-count 8 t:MISTRAL_FF
+
+select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH t:MISTRAL_FF %% t:* %D
diff --git a/tests/arch/intel_alm/dffs.ys b/tests/arch/intel_alm/dffs.ys
new file mode 100644
index 000000000..cf29ad8e0
--- /dev/null
+++ b/tests/arch/intel_alm/dffs.ys
@@ -0,0 +1,22 @@
+read_verilog ../common/dffs.v
+design -save read
+
+hierarchy -top dff
+proc
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dff # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_FF
+
+select -assert-none t:MISTRAL_FF %% t:* %D
+
+design -load read
+hierarchy -top dffe
+proc
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dffe # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_FF
+select -assert-count 1 t:MISTRAL_ALUT3
+
+select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT3 %% t:* %D
diff --git a/tests/arch/intel_alm/fsm.ys b/tests/arch/intel_alm/fsm.ys
new file mode 100644
index 000000000..8bb0ebab2
--- /dev/null
+++ b/tests/arch/intel_alm/fsm.ys
@@ -0,0 +1,18 @@
+read_verilog ../common/fsm.v
+hierarchy -top fsm
+proc
+flatten
+
+equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev
+async2sync
+miter -equiv -make_assert -flatten gold gate miter
+sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter
+
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd fsm # Constrain all select calls below inside the top module
+
+select -assert-count 6 t:MISTRAL_FF
+select -assert-max 2 t:MISTRAL_ALUT2 # Clang returns 2, GCC returns 1
+select -assert-count 5 t:MISTRAL_ALUT5
+select -assert-count 1 t:MISTRAL_ALUT6
+select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
diff --git a/tests/arch/intel_alm/logic.ys b/tests/arch/intel_alm/logic.ys
new file mode 100644
index 000000000..fad45db74
--- /dev/null
+++ b/tests/arch/intel_alm/logic.ys
@@ -0,0 +1,11 @@
+read_verilog ../common/logic.v
+hierarchy -top top
+proc
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+
+select -assert-count 1 t:MISTRAL_NOT
+select -assert-count 6 t:MISTRAL_ALUT2
+select -assert-count 2 t:MISTRAL_ALUT4
+select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D
diff --git a/tests/arch/intel_alm/mux.ys b/tests/arch/intel_alm/mux.ys
new file mode 100644
index 000000000..308e45268
--- /dev/null
+++ b/tests/arch/intel_alm/mux.ys
@@ -0,0 +1,45 @@
+read_verilog ../common/mux.v
+design -save read
+
+hierarchy -top mux2
+proc
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux2 # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_ALUT3
+
+select -assert-none t:MISTRAL_ALUT3 %% t:* %D
+
+design -load read
+hierarchy -top mux4
+proc
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux4 # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_ALUT6
+
+select -assert-none t:MISTRAL_ALUT6 %% t:* %D
+
+design -load read
+hierarchy -top mux8
+proc
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux8 # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_ALUT3
+select -assert-count 1 t:MISTRAL_ALUT5
+select -assert-count 2 t:MISTRAL_ALUT6
+
+select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
+
+design -load read
+hierarchy -top mux16
+proc
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux16 # Constrain all select calls below inside the top module
+select -assert-count 1 t:MISTRAL_ALUT3
+select -assert-count 2 t:MISTRAL_ALUT5
+select -assert-count 4 t:MISTRAL_ALUT6
+
+select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
diff --git a/tests/arch/intel_alm/run-test.sh b/tests/arch/intel_alm/run-test.sh
new file mode 100755
index 000000000..bf19b887d
--- /dev/null
+++ b/tests/arch/intel_alm/run-test.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+set -e
+{
+echo "all::"
+for x in *.ys; do
+ echo "all:: run-$x"
+ echo "run-$x:"
+ echo " @echo 'Running $x..'"
+ echo " @../../../yosys -ql ${x%.ys}.log -w 'Yosys has only limited support for tri-state logic at the moment.' $x"
+done
+for s in *.sh; do
+ if [ "$s" != "run-test.sh" ]; then
+ echo "all:: run-$s"
+ echo "run-$s:"
+ echo " @echo 'Running $s..'"
+ echo " @bash $s"
+ fi
+done
+} > run-test.mk
+exec ${MAKE:-make} -f run-test.mk
diff --git a/tests/arch/intel_alm/shifter.ys b/tests/arch/intel_alm/shifter.ys
new file mode 100644
index 000000000..014dbd1a8
--- /dev/null
+++ b/tests/arch/intel_alm/shifter.ys
@@ -0,0 +1,10 @@
+read_verilog ../common/shifter.v
+hierarchy -top top
+proc
+flatten
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+select -assert-count 8 t:MISTRAL_FF
+
+select -assert-none t:MISTRAL_FF %% t:* %D
diff --git a/tests/arch/intel_alm/tribuf.ys b/tests/arch/intel_alm/tribuf.ys
new file mode 100644
index 000000000..71b05a747
--- /dev/null
+++ b/tests/arch/intel_alm/tribuf.ys
@@ -0,0 +1,13 @@
+read_verilog ../common/tribuf.v
+hierarchy -top tristate
+proc
+tribuf
+flatten
+synth
+equiv_opt -assert -map +/simcells.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd tristate # Constrain all select calls below inside the top module
+#Internal cell type used. Need support it.
+select -assert-count 1 t:$_TBUF_
+
+select -assert-none t:$_TBUF_ %% t:* %D
diff --git a/tests/opt/opt_expr.ys b/tests/opt/opt_expr.ys
index e0acead82..7c446afd1 100644
--- a/tests/opt/opt_expr.ys
+++ b/tests/opt/opt_expr.ys
@@ -291,3 +291,31 @@ check
equiv_opt -assert opt_expr -keepdc
design -load postopt
select -assert-count 1 t:$shift r:A_WIDTH=13 %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_mul_low_bits(input [2:0] a, input [2:0] b, output [7:0] y);
+ \$mul #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(4), .Y_WIDTH(8)) mul (.A({a, 1'b0}), .B({b, 1'b0}), .Y(y));
+endmodule
+EOT
+check
+
+equiv_opt -assert opt_expr
+design -load postopt
+select -assert-count 1 t:$mul r:A_WIDTH=3 %i r:B_WIDTH=3 %i r:Y_WIDTH=6 %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_mul_low_bits(input [2:0] a, input [2:0] b, output [7:0] y);
+ \$mul #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(4), .Y_WIDTH(8)) mul (.A({a, 1'b0}), .B({b, 1'b0}), .Y(y));
+endmodule
+EOT
+check
+
+equiv_opt -assert opt_expr -keepdc
+design -load postopt
+select -assert-count 1 t:$mul r:A_WIDTH=4 %i r:B_WIDTH=4 %i r:Y_WIDTH=8 %i
diff --git a/tests/opt/opt_expr_alu.ys b/tests/opt/opt_expr_alu.ys
index a3361ca43..e288bcea6 100644
--- a/tests/opt/opt_expr_alu.ys
+++ b/tests/opt/opt_expr_alu.ys
@@ -5,7 +5,7 @@ endmodule
EOT
alumacc
-equiv_opt opt_expr -fine
+equiv_opt -assert opt_expr -fine
design -load postopt
select -assert-count 1 t:$pos
select -assert-count none t:$pos t:* %D
@@ -30,7 +30,7 @@ assign y = {a,1'b1} - 1'b1;
endmodule
EOT
-equiv_opt opt_expr -fine
+equiv_opt -assert opt_expr -fine
design -load postopt
select -assert-count 1 t:$pos
select -assert-count none t:$pos t:* %D
@@ -43,7 +43,7 @@ assign y = {a,3'b101} - 1'b1;
endmodule
EOT
-equiv_opt opt_expr -fine
+equiv_opt -assert opt_expr -fine
design -load postopt
select -assert-count 1 t:$pos
select -assert-count none t:$pos t:* %D
@@ -57,7 +57,55 @@ endmodule
EOT
alumacc
-equiv_opt opt_expr -fine
+equiv_opt -assert opt_expr -fine
design -load postopt
select -assert-count 1 t:$pos
select -assert-count none t:$pos t:* %D
+
+
+design -reset
+read_verilog <<EOT
+module test(input [1:0] a, output [3:0] y);
+assign y = -{a[1], 2'b10, a[0]};
+endmodule
+EOT
+
+alumacc
+equiv_opt -assert opt -fine
+design -load postopt
+select -assert-count 1 t:$alu
+select -assert-count 1 t:$alu r:Y_WIDTH=3 %i
+select -assert-count 1 t:$not
+select -assert-count none t:$alu t:$not t:* %D %D
+
+
+design -reset
+read_verilog <<EOT
+module test(input [3:0] a, input [2:0] b, output [5:0] y);
+assign y = {a[3:2], 1'b1, a[1:0]} + {b[2], 2'b11, b[1:0]};
+endmodule
+EOT
+
+alumacc
+equiv_opt -assert opt -fine
+design -load postopt
+dump
+select -assert-count 2 t:$alu
+select -assert-count 1 t:$alu r:Y_WIDTH=2 %i
+select -assert-count 1 t:$alu r:Y_WIDTH=3 %i
+select -assert-count none t:$alu t:* %D
+
+
+design -reset
+read_verilog <<EOT
+module test(input [3:0] a, input [3:0] b, output [5:0] y);
+assign y = {a[3:2], 1'b0, a[1:0]} + {b[3:2], 1'b0, b[1:0]};
+endmodule
+EOT
+
+alumacc
+equiv_opt -assert opt -fine
+design -load postopt
+select -assert-count 2 t:$alu
+select -assert-count 2 t:$alu r:Y_WIDTH=3 %i
+select -assert-count none t:$alu t:* %D
diff --git a/tests/select/.gitignore b/tests/select/.gitignore
new file mode 100644
index 000000000..50e13221d
--- /dev/null
+++ b/tests/select/.gitignore
@@ -0,0 +1 @@
+/*.log
diff --git a/tests/svtypes/typedef_package.sv b/tests/svtypes/typedef_package.sv
index 57a78c53a..2d83742c5 100644
--- a/tests/svtypes/typedef_package.sv
+++ b/tests/svtypes/typedef_package.sv
@@ -1,6 +1,9 @@
package pkg;
typedef logic [7:0] uint8_t;
- typedef enum logic [7:0] {bb=8'hBB} enum8_t;
+ typedef enum logic [7:0] {bb=8'hBB, cc=8'hCC} enum8_t;
+
+ localparam uint8_t PCONST = cc;
+ parameter uint8_t PCONST_COPY = PCONST;
endpackage
module top;
@@ -8,7 +11,9 @@ module top;
(* keep *) pkg::uint8_t a = 8'hAA;
(* keep *) pkg::enum8_t b_enum = pkg::bb;
- always @* assert(a == 8'hAA);
- always @* assert(b_enum == 8'hBB);
+ always_comb assert(a == 8'hAA);
+ always_comb assert(b_enum == 8'hBB);
+ always_comb assert(pkg::PCONST == pkg::cc);
+ always_comb assert(pkg::PCONST_COPY == pkg::cc);
endmodule
diff --git a/tests/techmap/dffinit.ys b/tests/techmap/dffinit.ys
new file mode 100644
index 000000000..218d411f8
--- /dev/null
+++ b/tests/techmap/dffinit.ys
@@ -0,0 +1,25 @@
+read_verilog <<EOT
+
+module ff(...);
+input d;
+output q;
+
+endmodule
+
+module top(...);
+input d;
+output q1;
+(* init = 1'b1 *)
+output q2;
+
+ff my_ff1(.d(d), .q(q1));
+ff my_ff2(.d(d), .q(q2));
+
+endmodule
+
+EOT
+
+dffinit -ff ff q init
+select -assert-count 2 t:ff
+select -assert-count 1 t:ff r:init %i
+select -assert-count 1 t:ff r:init=1'b1 %i
diff --git a/tests/techmap/zinit.ys b/tests/techmap/zinit.ys
new file mode 100644
index 000000000..d0e41b4d2
--- /dev/null
+++ b/tests/techmap/zinit.ys
@@ -0,0 +1,151 @@
+read_verilog -icells <<EOT
+module top(input C, R, input [1:0] D, (* init = {2'b10, 2'b01, 1'b1, {8{1'b1}}} *) output [12:0] Q);
+
+(* init = 1'b1 *)
+wire unused;
+
+$_DFF_NN0_ dff0 (.C(C), .D(D[0]), .R(R), .Q(Q[0]));
+$_DFF_NN1_ dff1 (.C(C), .D(D[0]), .R(R), .Q(Q[1]));
+$_DFF_NP0_ dff2 (.C(C), .D(D[0]), .R(R), .Q(Q[2]));
+$_DFF_NP1_ dff3 (.C(C), .D(D[0]), .R(R), .Q(Q[3]));
+$_DFF_PN0_ dff4 (.C(C), .D(D[0]), .R(R), .Q(Q[4]));
+$_DFF_PN1_ dff5 (.C(C), .D(D[0]), .R(R), .Q(Q[5]));
+$_DFF_PP0_ dff6 (.C(C), .D(D[0]), .R(R), .Q(Q[6]));
+$_DFF_PP1_ dff7 (.C(C), .D(D[0]), .R(R), .Q(Q[7]));
+
+$adff #(.WIDTH(2), .CLK_POLARITY(1), .ARST_POLARITY(1'b0), .ARST_VALUE(2'b10)) dff8 (.CLK(C), .ARST(R), .D(D), .Q(Q[10:9]));
+$adff #(.WIDTH(2), .CLK_POLARITY(0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'b01)) dff9 (.CLK(C), .ARST(R), .D(D), .Q(Q[12:11]));
+endmodule
+EOT
+equiv_opt -assert -multiclock zinit
+design -load postopt
+
+select -assert-count 20 t:$_NOT_
+select -assert-count 1 w:unused a:init %i
+select -assert-count 1 w:Q a:init=13'bxxxx1xxxxxxxx %i
+select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$_DFF_??1_ %i
+select -assert-count 4 c:dff1 c:dff3 c:dff5 c:dff7 %% t:$_DFF_??0_ %i
+
+
+design -reset
+read_verilog -icells <<EOT
+module top(input C, R, input [1:0] D, (* init = {2'bx0, 2'b0x, 1'b1, {8{1'b0}}} *) output [12:0] Q);
+
+(* init = 1'b1 *)
+wire unused;
+
+$_DFF_NN0_ dff0 (.C(C), .D(D[0]), .R(R), .Q(Q[0]));
+$_DFF_NN1_ dff1 (.C(C), .D(D[0]), .R(R), .Q(Q[1]));
+$_DFF_NP0_ dff2 (.C(C), .D(D[0]), .R(R), .Q(Q[2]));
+$_DFF_NP1_ dff3 (.C(C), .D(D[0]), .R(R), .Q(Q[3]));
+$_DFF_PN0_ dff4 (.C(C), .D(D[0]), .R(R), .Q(Q[4]));
+$_DFF_PN1_ dff5 (.C(C), .D(D[0]), .R(R), .Q(Q[5]));
+$_DFF_PP0_ dff6 (.C(C), .D(D[0]), .R(R), .Q(Q[6]));
+$_DFF_PP1_ dff7 (.C(C), .D(D[0]), .R(R), .Q(Q[7]));
+
+$adff #(.WIDTH(2), .CLK_POLARITY(1), .ARST_POLARITY(1'b0), .ARST_VALUE(2'b10)) dff8 (.CLK(C), .ARST(R), .D(D), .Q(Q[10:9]));
+$adff #(.WIDTH(2), .CLK_POLARITY(0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'b01)) dff9 (.CLK(C), .ARST(R), .D(D), .Q(Q[12:11]));
+endmodule
+EOT
+equiv_opt -assert -multiclock zinit
+design -load postopt
+
+select -assert-count 0 t:$_NOT_
+select -assert-count 1 w:unused a:init %i
+select -assert-count 1 w:Q a:init=13'bxxxx1xxxxxxxx %i
+select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$_DFF_??0_ %i
+select -assert-count 4 c:dff1 c:dff3 c:dff5 c:dff7 %% t:$_DFF_??1_ %i
+
+
+design -reset
+read_verilog -icells <<EOT
+module top(input C, R, D, E, (* init = {24{1'b1}} *) output [23:0] Q);
+
+$__DFFE_NN0 dff0 (.C(C), .D(D), .E(E), .R(R), .Q(Q[0]));
+$__DFFE_NN1 dff1 (.C(C), .D(D), .E(E), .R(R), .Q(Q[1]));
+$__DFFE_NP0 dff2 (.C(C), .D(D), .E(E), .R(R), .Q(Q[2]));
+$__DFFE_NP1 dff3 (.C(C), .D(D), .E(E), .R(R), .Q(Q[3]));
+$__DFFE_PN0 dff4 (.C(C), .D(D), .E(E), .R(R), .Q(Q[4]));
+$__DFFE_PN1 dff5 (.C(C), .D(D), .E(E), .R(R), .Q(Q[5]));
+$__DFFE_PP0 dff6 (.C(C), .D(D), .E(E), .R(R), .Q(Q[6]));
+$__DFFE_PP1 dff7 (.C(C), .D(D), .E(E), .R(R), .Q(Q[7]));
+
+$__DFFS_NN0_ dff8 (.C(C), .D(D[0]), .R(R), .Q(Q[8]));
+$__DFFS_NN1_ dff9 (.C(C), .D(D[0]), .R(R), .Q(Q[9]));
+$__DFFS_NP0_ dff10(.C(C), .D(D[0]), .R(R), .Q(Q[10]));
+$__DFFS_NP1_ dff11(.C(C), .D(D[0]), .R(R), .Q(Q[11]));
+$__DFFS_PN0_ dff12(.C(C), .D(D[0]), .R(R), .Q(Q[12]));
+$__DFFS_PN1_ dff13(.C(C), .D(D[0]), .R(R), .Q(Q[13]));
+$__DFFS_PP0_ dff14(.C(C), .D(D[0]), .R(R), .Q(Q[14]));
+$__DFFS_PP1_ dff15(.C(C), .D(D[0]), .R(R), .Q(Q[15]));
+
+$__DFFSE_NN0 dff16(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[16]));
+$__DFFSE_NN1 dff17(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[17]));
+$__DFFSE_NP0 dff18(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[18]));
+$__DFFSE_NP1 dff19(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[19]));
+$__DFFSE_PN0 dff20(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[20]));
+$__DFFSE_PN1 dff21(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[21]));
+$__DFFSE_PP0 dff22(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[22]));
+$__DFFSE_PP1 dff23(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[23]));
+
+endmodule
+EOT
+#equiv_opt -assert -multiclock zinit
+#design -load postopt
+zinit
+
+select -assert-count 48 t:$_NOT_
+select -assert-count 1 w:Q a:init=24'bx %i
+select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$__DFFE_??1 %i
+select -assert-count 4 c:dff1 c:dff3 c:dff5 c:dff7 %% t:$__DFFE_??0 %i
+select -assert-count 4 c:dff8 c:dff10 c:dff12 c:dff14 %% t:$__DFFS_??1_ %i
+select -assert-count 4 c:dff9 c:dff11 c:dff13 c:dff15 %% t:$__DFFS_??0_ %i
+select -assert-count 4 c:dff16 c:dff18 c:dff20 c:dff22 %% t:$__DFFSE_??1 %i
+select -assert-count 4 c:dff17 c:dff19 c:dff21 c:dff23 %% t:$__DFFSE_??0 %i
+
+
+design -reset
+read_verilog -icells <<EOT
+module top(input C, R, D, E, (* init = {24{1'b0}} *) output [23:0] Q);
+
+$__DFFE_NN0 dff0 (.C(C), .D(D), .E(E), .R(R), .Q(Q[0]));
+$__DFFE_NN1 dff1 (.C(C), .D(D), .E(E), .R(R), .Q(Q[1]));
+$__DFFE_NP0 dff2 (.C(C), .D(D), .E(E), .R(R), .Q(Q[2]));
+$__DFFE_NP1 dff3 (.C(C), .D(D), .E(E), .R(R), .Q(Q[3]));
+$__DFFE_PN0 dff4 (.C(C), .D(D), .E(E), .R(R), .Q(Q[4]));
+$__DFFE_PN1 dff5 (.C(C), .D(D), .E(E), .R(R), .Q(Q[5]));
+$__DFFE_PP0 dff6 (.C(C), .D(D), .E(E), .R(R), .Q(Q[6]));
+$__DFFE_PP1 dff7 (.C(C), .D(D), .E(E), .R(R), .Q(Q[7]));
+
+$__DFFS_NN0_ dff8 (.C(C), .D(D[0]), .R(R), .Q(Q[8]));
+$__DFFS_NN1_ dff9 (.C(C), .D(D[0]), .R(R), .Q(Q[9]));
+$__DFFS_NP0_ dff10(.C(C), .D(D[0]), .R(R), .Q(Q[10]));
+$__DFFS_NP1_ dff11(.C(C), .D(D[0]), .R(R), .Q(Q[11]));
+$__DFFS_PN0_ dff12(.C(C), .D(D[0]), .R(R), .Q(Q[12]));
+$__DFFS_PN1_ dff13(.C(C), .D(D[0]), .R(R), .Q(Q[13]));
+$__DFFS_PP0_ dff14(.C(C), .D(D[0]), .R(R), .Q(Q[14]));
+$__DFFS_PP1_ dff15(.C(C), .D(D[0]), .R(R), .Q(Q[15]));
+
+$__DFFSE_NN0 dff16(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[16]));
+$__DFFSE_NN1 dff17(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[17]));
+$__DFFSE_NP0 dff18(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[18]));
+$__DFFSE_NP1 dff19(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[19]));
+$__DFFSE_PN0 dff20(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[20]));
+$__DFFSE_PN1 dff21(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[21]));
+$__DFFSE_PP0 dff22(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[22]));
+$__DFFSE_PP1 dff23(.C(C), .D(D[0]),.E(E), .R(R), .Q(Q[23]));
+
+endmodule
+EOT
+#equiv_opt -assert -multiclock zinit
+#design -load postopt
+zinit
+
+select -assert-count 0 t:$_NOT_
+select -assert-count 1 w:Q a:init=24'bx %i
+select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$__DFFE_??0 %i
+select -assert-count 4 c:dff1 c:dff3 c:dff5 c:dff7 %% t:$__DFFE_??1 %i
+select -assert-count 4 c:dff8 c:dff10 c:dff12 c:dff14 %% t:$__DFFS_??0_ %i
+select -assert-count 4 c:dff9 c:dff11 c:dff13 c:dff15 %% t:$__DFFS_??1_ %i
+select -assert-count 4 c:dff16 c:dff18 c:dff20 c:dff22 %% t:$__DFFSE_??0 %i
+select -assert-count 4 c:dff17 c:dff19 c:dff21 c:dff23 %% t:$__DFFSE_??1 %i
diff --git a/tests/various/bug1876.ys b/tests/various/bug1876.ys
new file mode 100644
index 000000000..7995eedcf
--- /dev/null
+++ b/tests/various/bug1876.ys
@@ -0,0 +1,60 @@
+read_verilog <<EOT
+module expression_00032(b5, y15);
+ input signed [5:0] b5;
+ output [3:0] y15;
+ assign y15 = (0 ? b5 : b5) > 0;
+endmodule
+EOT
+
+
+design -reset
+read_verilog <<EOT
+module expression_00057(a0, a1, a2, a3, a4, a5, b0, b1, b2, b3, b4, b5, y8);
+ input [3:0] a0;
+ input [4:0] a1;
+ input [5:0] a2;
+ input signed [3:0] a3;
+ input signed [4:0] a4;
+ input signed [5:0] a5;
+
+ input [3:0] b0;
+ input [4:0] b1;
+ input [5:0] b2;
+ input signed [3:0] b3;
+ input signed [4:0] b4;
+ input signed [5:0] b5;
+
+ output [5:0] y8;
+
+ localparam signed [4:0] p4 = ((2'd3)||(-4'sd1));
+ localparam signed [3:0] p9 = {3{(((2'sd0)^~(5'd20))>((-3'sd0)>>(4'sd2)))}};
+
+ assign y8 = (-(!($signed({3{p9}})<(p4?b4:b5))));
+endmodule
+EOT
+
+
+design -reset
+read_verilog <<EOT
+module expression_00354(a0, a1, a2, a3, a4, a5, b0, b1, b2, b3, b4, b5, y4);
+ input [3:0] a0;
+ input [4:0] a1;
+ input [5:0] a2;
+ input signed [3:0] a3;
+ input signed [4:0] a4;
+ input signed [5:0] a5;
+
+ input [3:0] b0;
+ input [4:0] b1;
+ input [5:0] b2;
+ input signed [3:0] b3;
+ input signed [4:0] b4;
+ input signed [5:0] b5;
+
+ output wire signed [4:0] y4;
+
+ localparam signed [4:0] p10 = ((3'd0)?(2'd1):(-2'sd1));
+
+ assign y4 = ((p10?a4:b4)&$signed(b3));
+endmodule
+EOT