aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.editorconfig5
-rw-r--r--CHANGELOG4
-rw-r--r--Makefile74
-rw-r--r--README.md9
-rw-r--r--backends/aiger/aiger.cc12
-rw-r--r--backends/aiger/xaiger.cc5
-rw-r--r--backends/cxxrtl/cxxrtl.cc99
-rw-r--r--frontends/aiger/aigerparse.cc77
-rw-r--r--frontends/ast/ast.cc4
-rw-r--r--frontends/rpc/Makefile.inc2
-rw-r--r--frontends/verific/verific.cc72
-rw-r--r--frontends/verific/verific.h2
-rw-r--r--kernel/constids.inc2
-rw-r--r--kernel/driver.cc17
-rw-r--r--kernel/register.cc4
-rw-r--r--kernel/rtlil.cc5
-rw-r--r--kernel/yosys.cc27
-rw-r--r--kernel/yosys.h2
-rw-r--r--libs/ezsat/ezminisat.cc11
-rw-r--r--libs/minisat/00_PATCH_wasm.patch34
-rwxr-xr-xlibs/minisat/00_UPDATE.sh2
-rw-r--r--libs/minisat/System.cc8
-rw-r--r--manual/CHAPTER_Auxprogs.tex5
-rw-r--r--passes/cmds/Makefile.inc4
-rw-r--r--passes/cmds/bugpoint.cc76
-rw-r--r--passes/cmds/cover.cc4
-rw-r--r--passes/cmds/select.cc35
-rw-r--r--passes/cmds/show.cc12
-rw-r--r--passes/opt/opt_expr.cc52
-rw-r--r--passes/pmgen/ice40_dsp.cc8
-rw-r--r--passes/pmgen/ice40_dsp.pmg18
-rw-r--r--passes/pmgen/xilinx_dsp.pmg18
-rw-r--r--passes/pmgen/xilinx_dsp_CREG.pmg4
-rw-r--r--passes/pmgen/xilinx_dsp_cascade.pmg24
-rw-r--r--passes/pmgen/xilinx_srl.cc4
-rw-r--r--passes/pmgen/xilinx_srl.pmg20
-rw-r--r--passes/sat/Makefile.inc3
-rw-r--r--passes/sat/qbfsat.cc35
-rw-r--r--passes/techmap/Makefile.inc2
-rw-r--r--passes/techmap/abc.cc11
-rw-r--r--passes/techmap/abc9_exe.cc23
-rw-r--r--passes/techmap/abc9_ops.cc8
-rw-r--r--techlibs/ecp5/Makefile.inc9
-rw-r--r--techlibs/ecp5/ecp5_ffinit.cc12
-rw-r--r--techlibs/ecp5/ecp5_gsr.cc4
-rw-r--r--techlibs/gowin/Makefile.inc3
-rw-r--r--techlibs/intel_alm/Makefile.inc3
-rw-r--r--techlibs/intel_alm/common/quartus_rename.v63
-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.cc13
-rw-r--r--techlibs/xilinx/xilinx_dffopt.cc9
-rw-r--r--tests/aiger/neg.ys36
-rwxr-xr-xtests/aiger/run-test.sh5
-rw-r--r--tests/arch/ice40/ice40_dsp.ys1
-rw-r--r--tests/arch/intel_alm/quartus_ice.ys12
-rw-r--r--tests/arch/xilinx/xilinx_dffopt.ys35
-rw-r--r--tests/arch/xilinx/xilinx_dsp.ys1
-rw-r--r--tests/opt/bug2010.ys10
-rw-r--r--tests/select/blackboxes.ys28
-rw-r--r--tests/various/bug2014.ys12
61 files changed, 806 insertions, 401 deletions
diff --git a/.editorconfig b/.editorconfig
index 4d6f5ef7a..f5444d81a 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,3 +5,8 @@ indent_style = tab
indent_size = tab
trim_trailing_whitespace = true
insert_final_newline = true
+
+[abc/**]
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = false
diff --git a/CHANGELOG b/CHANGELOG
index df8e14b26..3b36c3182 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,7 +8,7 @@ Yosys 0.9 .. Yosys 0.9-dev
* Various
- Added "write_xaiger" backend
- - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only, no FFs)
+ - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only)
- Added "synth_xilinx -abc9" (experimental)
- Added "synth_ice40 -abc9" (experimental)
- Added "synth -abc9" (experimental)
@@ -58,7 +58,6 @@ Yosys 0.9 .. Yosys 0.9-dev
- Added support for SystemVerilog wildcard port connections (.*)
- Added "xilinx_dffopt" pass
- Added "scratchpad" pass
- - Added "abc9 -dff"
- Added "synth_xilinx -dff"
- Improved support of $readmem[hb] Memory Content File inclusion
- Added "opt_lut_ins" pass
@@ -66,6 +65,7 @@ Yosys 0.9 .. Yosys 0.9-dev
- Removed "dffsr2dff" (use opt_rmdff instead)
- Added "design -delete"
- Added "select -unset"
+ - Use YosysHQ/abc instead of upstream berkeley-abc/abc
Yosys 0.8 .. Yosys 0.9
----------------------
diff --git a/Makefile b/Makefile
index b3cfd71f9..47de420b8 100644
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,7 @@ CONFIG := clang
# CONFIG := gcc-4.8
# CONFIG := afl-gcc
# CONFIG := emcc
+# CONFIG := wasi
# CONFIG := mxe
# CONFIG := msys2
# CONFIG := msys2-64
@@ -32,7 +33,9 @@ ENABLE_NDEBUG := 0
LINK_CURSES := 0
LINK_TERMCAP := 0
LINK_ABC := 0
-# Needed for environments that don't have proper thread support (i.e. emscripten)
+# Needed for environments that can't run executables (i.e. emscripten, wasm)
+DISABLE_SPAWN := 0
+# Needed for environments that don't have proper thread support (i.e. emscripten, wasm--for now)
DISABLE_ABC_THREADS := 0
# clang sanitizers
@@ -42,7 +45,7 @@ SANITIZER =
# SANITIZER = undefined
# SANITIZER = cfi
-PROGRAM_PREFIX :=
+PROGRAM_PREFIX :=
OS := $(shell uname -s)
PREFIX ?= /usr/local
@@ -133,9 +136,9 @@ bumpversion:
# is just a symlink to your actual ABC working directory, as 'make mrproper'
# will remove the 'abc' directory and you do not want to accidentally
# delete your work on ABC..
-ABCREV = ed90ce2
+ABCREV = d14acd8
ABCPULL = 1
-ABCURL ?= https://github.com/berkeley-abc/abc
+ABCURL ?= https://github.com/YosysHQ/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
# set ABCEXTERNAL = <abc-command> to use an external ABC instance
@@ -253,6 +256,8 @@ LDFLAGS += $(EMCCFLAGS)
LDLIBS =
EXE = .js
+DISABLE_SPAWN := 1
+
TARGETS := $(filter-out $(PROGRAM_PREFIX)yosys-config,$(TARGETS))
EXTRA_TARGETS += yosysjs-$(YOSYS_VER).zip
@@ -274,6 +279,35 @@ yosysjs-$(YOSYS_VER).zip: yosys.js yosys.wasm viz.js misc/yosysjs/*
yosys.html: misc/yosys.html
$(P) cp misc/yosys.html yosys.html
+else ifeq ($(CONFIG),wasi)
+ifeq ($(WASI_SDK),)
+CXX = clang++
+LD = clang++
+AR = llvm-ar
+RANLIB = llvm-ranlib
+WASIFLAGS := -target wasm32-wasi --sysroot $(WASI_SYSROOT) $(WASIFLAGS)
+else
+CXX = $(WASI_SDK)/bin/clang++
+LD = $(WASI_SDK)/bin/clang++
+AR = $(WASI_SDK)/bin/ar
+RANLIB = $(WASI_SDK)/bin/ranlib
+WASIFLAGS := --sysroot $(WASI_SDK)/share/wasi-sysroot $(WASIFLAGS)
+endif
+CXXFLAGS := $(WASIFLAGS) -std=c++11 -Os $(filter-out -fPIC,$(CXXFLAGS))
+LDFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LDFLAGS))
+LDLIBS := $(filter-out -lrt,$(LDLIBS))
+ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)"
+ABCMKARGS += ARCHFLAGS="$(WASIFLAGS) -DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING"
+ABCMKARGS += OPTFLAGS="-Os"
+EXE = .wasm
+
+DISABLE_SPAWN := 1
+
+ifeq ($(ENABLE_ABC),1)
+LINK_ABC := 1
+DISABLE_ABC_THREADS := 1
+endif
+
else ifeq ($(CONFIG),mxe)
PKG_CONFIG = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-pkg-config
CXX = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++
@@ -396,6 +430,10 @@ ifeq ($(DISABLE_ABC_THREADS),1)
ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
endif
+ifeq ($(DISABLE_SPAWN),1)
+CXXFLAGS += -DYOSYS_DISABLE_SPAWN
+endif
+
ifeq ($(ENABLE_PLUGINS),1)
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags libffi) -DYOSYS_ENABLE_PLUGINS
LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi)
@@ -584,10 +622,10 @@ include $(YOSYS_SRC)/techlibs/*/Makefile.inc
else
-include frontends/verilog/Makefile.inc
-include frontends/ilang/Makefile.inc
-include frontends/ast/Makefile.inc
-include frontends/blif/Makefile.inc
+include $(YOSYS_SRC)/frontends/verilog/Makefile.inc
+include $(YOSYS_SRC)/frontends/ilang/Makefile.inc
+include $(YOSYS_SRC)/frontends/ast/Makefile.inc
+include $(YOSYS_SRC)/frontends/blif/Makefile.inc
OBJS += passes/hierarchy/hierarchy.o
OBJS += passes/cmds/select.o
@@ -597,14 +635,14 @@ OBJS += passes/cmds/cover.o
OBJS += passes/cmds/design.o
OBJS += passes/cmds/plugin.o
-include passes/proc/Makefile.inc
-include passes/opt/Makefile.inc
-include passes/techmap/Makefile.inc
+include $(YOSYS_SRC)/passes/proc/Makefile.inc
+include $(YOSYS_SRC)/passes/opt/Makefile.inc
+include $(YOSYS_SRC)/passes/techmap/Makefile.inc
-include backends/verilog/Makefile.inc
-include backends/ilang/Makefile.inc
+include $(YOSYS_SRC)/backends/verilog/Makefile.inc
+include $(YOSYS_SRC)/backends/ilang/Makefile.inc
-include techlibs/common/Makefile.inc
+include $(YOSYS_SRC)/techlibs/common/Makefile.inc
endif
@@ -911,6 +949,14 @@ config-emcc: clean
echo 'ENABLE_READLINE := 0' >> Makefile.conf
echo 'ENABLE_ZLIB := 0' >> Makefile.conf
+config-wasi: clean
+ echo 'CONFIG := wasi' > Makefile.conf
+ echo 'ENABLE_TCL := 0' >> Makefile.conf
+ echo 'ENABLE_ABC := 0' >> Makefile.conf
+ echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
+ echo 'ENABLE_READLINE := 0' >> Makefile.conf
+ echo 'ENABLE_ZLIB := 0' >> Makefile.conf
+
config-mxe: clean
echo 'CONFIG := mxe' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
diff --git a/README.md b/README.md
index 0a81d8bb9..1e486c3ac 100644
--- a/README.md
+++ b/README.md
@@ -118,6 +118,13 @@ Tests are located in the tests subdirectory and can be executed using the test t
$ make test
+To use a separate (out-of-tree) build directory, provide a path to the Makefile.
+
+ $ mkdir build; cd build
+ $ make -f ../Makefile
+
+Out-of-tree builds require a clean source tree.
+
Getting Started
===============
@@ -388,7 +395,7 @@ Verilog Attributes and non-standard features
- The cell attribute ``wildcard_port_conns`` represents wildcard port
connections (SystemVerilog ``.*``). These are resolved to concrete
- connections to matching wires in ``hierarchy``.
+ connections to matching wires in ``hierarchy``.
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
the non-standard ``{* ... *}`` attribute syntax to set default attributes
diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc
index cac32a8da..e5a41b5c5 100644
--- a/backends/aiger/aiger.cc
+++ b/backends/aiger/aiger.cc
@@ -629,30 +629,30 @@ struct AigerWriter
int a = aig_map.at(sig[i]);
if (verbose_map)
- wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire));
+ wire_lines[a] += stringf("wire %d %d %s\n", a, wire->start_offset+i, log_id(wire));
if (wire->port_input) {
log_assert((a & 1) == 0);
- input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
+ input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire));
}
if (wire->port_output) {
int o = ordered_outputs.at(sig[i]);
- output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire));
+ output_lines[o] += stringf("output %d %d %s\n", o, wire->start_offset+i, log_id(wire));
}
if (init_inputs.count(sig[i])) {
int a = init_inputs.at(sig[i]);
log_assert((a & 1) == 0);
- init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
+ init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire));
}
if (ordered_latches.count(sig[i])) {
int l = ordered_latches.at(sig[i]);
if (zinit_mode && (aig_latchinit.at(l) == 1))
- latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire));
+ latch_lines[l] += stringf("invlatch %d %d %s\n", l, wire->start_offset+i, log_id(wire));
else
- latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire));
+ latch_lines[l] += stringf("latch %d %d %s\n", l, wire->start_offset+i, log_id(wire));
}
}
}
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index 3c7c745fe..1fb7210cb 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -725,13 +725,12 @@ struct XAigerWriter
if (input_bits.count(b)) {
int a = aig_map.at(b);
log_assert((a & 1) == 0);
- input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
+ input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire));
}
if (output_bits.count(b)) {
int o = ordered_outputs.at(b);
- int init = 2;
- output_lines[o] += stringf("output %d %d %s %d\n", o - GetSize(co_bits), i, log_id(wire), init);
+ output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, log_id(wire));
continue;
}
}
diff --git a/backends/cxxrtl/cxxrtl.cc b/backends/cxxrtl/cxxrtl.cc
index 237700b29..e7711962f 100644
--- a/backends/cxxrtl/cxxrtl.cc
+++ b/backends/cxxrtl/cxxrtl.cc
@@ -212,14 +212,14 @@ bool is_ff_cell(RTLIL::IdString type)
bool is_internal_cell(RTLIL::IdString type)
{
- return type[0] == '$' && !type.begins_with("$paramod\\");
+ return type[0] == '$' && !type.begins_with("$paramod");
}
bool is_cxxrtl_blackbox_cell(const RTLIL::Cell *cell)
{
RTLIL::Module *cell_module = cell->module->design->module(cell->type);
log_assert(cell_module != nullptr);
- return cell_module->get_bool_attribute(ID(cxxrtl.blackbox));
+ return cell_module->get_bool_attribute(ID(cxxrtl_blackbox));
}
enum class CxxrtlPortType {
@@ -231,14 +231,14 @@ enum class CxxrtlPortType {
CxxrtlPortType cxxrtl_port_type(const RTLIL::Cell *cell, RTLIL::IdString port)
{
RTLIL::Module *cell_module = cell->module->design->module(cell->type);
- if (cell_module == nullptr || !cell_module->get_bool_attribute(ID(cxxrtl.blackbox)))
+ if (cell_module == nullptr || !cell_module->get_bool_attribute(ID(cxxrtl_blackbox)))
return CxxrtlPortType::UNKNOWN;
RTLIL::Wire *cell_output_wire = cell_module->wire(port);
log_assert(cell_output_wire != nullptr);
- bool is_comb = cell_output_wire->get_bool_attribute(ID(cxxrtl.comb));
- bool is_sync = cell_output_wire->get_bool_attribute(ID(cxxrtl.sync));
+ bool is_comb = cell_output_wire->get_bool_attribute(ID(cxxrtl_comb));
+ bool is_sync = cell_output_wire->get_bool_attribute(ID(cxxrtl_sync));
if (is_comb && is_sync)
- log_cmd_error("Port `%s.%s' is marked as both `cxxrtl.comb` and `cxxrtl.sync`.\n",
+ log_cmd_error("Port `%s.%s' is marked as both `cxxrtl_comb` and `cxxrtl_sync`.\n",
log_id(cell_module), log_signal(cell_output_wire));
else if (is_comb)
return CxxrtlPortType::COMB;
@@ -606,7 +606,7 @@ struct CxxrtlWorker {
std::string mangle(const RTLIL::Module *module)
{
- return mangle_module_name(module->name, /*is_blackbox=*/module->get_bool_attribute(ID(cxxrtl.blackbox)));
+ return mangle_module_name(module->name, /*is_blackbox=*/module->get_bool_attribute(ID(cxxrtl_blackbox)));
}
std::string mangle(const RTLIL::Memory *memory)
@@ -634,19 +634,19 @@ struct CxxrtlWorker {
std::vector<std::string> template_param_names(const RTLIL::Module *module)
{
- if (!module->has_attribute(ID(cxxrtl.template)))
+ if (!module->has_attribute(ID(cxxrtl_template)))
return {};
- if (module->attributes.at(ID(cxxrtl.template)).flags != RTLIL::CONST_FLAG_STRING)
- log_cmd_error("Attribute `cxxrtl.template' of module `%s' is not a string.\n", log_id(module));
+ if (module->attributes.at(ID(cxxrtl_template)).flags != RTLIL::CONST_FLAG_STRING)
+ log_cmd_error("Attribute `cxxrtl_template' of module `%s' is not a string.\n", log_id(module));
- std::vector<std::string> param_names = split_by(module->get_string_attribute(ID(cxxrtl.template)), " \t");
+ std::vector<std::string> param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t");
for (const auto &param_name : param_names) {
// Various lowercase prefixes (p_, i_, cell_, ...) are used for member variables, so require
// parameters to start with an uppercase letter to avoid name conflicts. (This is the convention
// in both Verilog and C++, anyway.)
if (!isupper(param_name[0]))
- log_cmd_error("Attribute `cxxrtl.template' of module `%s' includes a parameter `%s', "
+ log_cmd_error("Attribute `cxxrtl_template' of module `%s' includes a parameter `%s', "
"which does not start with an uppercase letter.\n",
log_id(module), param_name.c_str());
}
@@ -677,7 +677,7 @@ struct CxxrtlWorker {
{
RTLIL::Module *cell_module = cell->module->design->module(cell->type);
log_assert(cell_module != nullptr);
- if (!cell_module->get_bool_attribute(ID(cxxrtl.blackbox)))
+ if (!cell_module->get_bool_attribute(ID(cxxrtl_blackbox)))
return "";
std::vector<std::string> param_names = template_param_names(cell_module);
@@ -726,12 +726,13 @@ struct CxxrtlWorker {
void dump_const_init(const RTLIL::Const &data, int width, int offset = 0, bool fixed_width = false)
{
+ const int CHUNK_SIZE = 32;
f << "{";
while (width > 0) {
- const int CHUNK_SIZE = 32;
- uint32_t chunk = data.extract(offset, width > CHUNK_SIZE ? CHUNK_SIZE : width).as_int();
+ int chunk_width = min(width, CHUNK_SIZE);
+ uint32_t chunk = data.extract(offset, chunk_width).as_int();
if (fixed_width)
- f << stringf("0x%08xu", chunk);
+ f << stringf("0x%.*xu", (3 + chunk_width) / 4, chunk);
else
f << stringf("%#xu", chunk);
if (width > CHUNK_SIZE)
@@ -1418,8 +1419,8 @@ struct CxxrtlWorker {
f << indent << "value<" << wire->width << "> " << mangle(wire) << ";\n";
} else {
std::string width;
- if (wire->module->has_attribute(ID(cxxrtl.blackbox)) && wire->has_attribute(ID(cxxrtl.width))) {
- width = wire->get_string_attribute(ID(cxxrtl.width));
+ if (wire->module->has_attribute(ID(cxxrtl_blackbox)) && wire->has_attribute(ID(cxxrtl_width))) {
+ width = wire->get_string_attribute(ID(cxxrtl_width));
} else {
width = std::to_string(wire->width);
}
@@ -1521,7 +1522,7 @@ struct CxxrtlWorker {
{
inc_indent();
f << indent << "bool converged = " << (eval_converges.at(module) ? "true" : "false") << ";\n";
- if (!module->get_bool_attribute(ID(cxxrtl.blackbox))) {
+ if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) {
for (auto wire : module->wires()) {
if (edge_wires[wire]) {
for (auto edge_type : edge_types) {
@@ -1573,10 +1574,10 @@ struct CxxrtlWorker {
f << indent << "prev_" << mangle(wire) << " = " << mangle(wire) << ";\n";
continue;
}
- if (!module->get_bool_attribute(ID(cxxrtl.blackbox)) || wire->port_id != 0)
+ if (!module->get_bool_attribute(ID(cxxrtl_blackbox)) || wire->port_id != 0)
f << indent << "changed |= " << mangle(wire) << ".commit();\n";
}
- if (!module->get_bool_attribute(ID(cxxrtl.blackbox))) {
+ if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) {
for (auto memory : module->memories) {
if (!writable_memories[memory.second])
continue;
@@ -1623,8 +1624,8 @@ struct CxxrtlWorker {
void dump_module_intf(RTLIL::Module *module)
{
dump_attrs(module);
- if (module->get_bool_attribute(ID(cxxrtl.blackbox))) {
- if (module->has_attribute(ID(cxxrtl.template)))
+ if (module->get_bool_attribute(ID(cxxrtl_blackbox))) {
+ if (module->has_attribute(ID(cxxrtl_template)))
f << indent << "template" << template_params(module, /*is_decl=*/true) << "\n";
f << indent << "struct " << mangle(module) << " : public module {\n";
inc_indent();
@@ -1686,7 +1687,7 @@ struct CxxrtlWorker {
dump_attrs(cell);
RTLIL::Module *cell_module = module->design->module(cell->type);
log_assert(cell_module != nullptr);
- if (cell_module->get_bool_attribute(ID(cxxrtl.blackbox))) {
+ if (cell_module->get_bool_attribute(ID(cxxrtl_blackbox))) {
f << indent << "std::unique_ptr<" << mangle(cell_module) << template_args(cell) << "> ";
f << mangle(cell) << " = " << mangle(cell_module) << template_args(cell);
f << "::create(" << escape_cxx_string(cell->name.str()) << ", ";
@@ -1711,7 +1712,7 @@ struct CxxrtlWorker {
void dump_module_impl(RTLIL::Module *module)
{
- if (module->get_bool_attribute(ID(cxxrtl.blackbox)))
+ if (module->get_bool_attribute(ID(cxxrtl_blackbox)))
return;
f << indent << "bool " << mangle(module) << "::eval() {\n";
dump_eval_method(module);
@@ -1730,9 +1731,9 @@ struct CxxrtlWorker {
for (auto module : design->modules()) {
if (!design->selected_module(module))
continue;
- if (module->get_bool_attribute(ID(cxxrtl.blackbox)))
+ if (module->get_bool_attribute(ID(cxxrtl_blackbox)))
modules.push_back(module); // cxxrtl blackboxes first
- if (module->get_blackbox_attribute() || module->get_bool_attribute(ID(cxxrtl.blackbox)))
+ if (module->get_blackbox_attribute() || module->get_bool_attribute(ID(cxxrtl_blackbox)))
continue;
topo_design.node(module);
@@ -1821,16 +1822,16 @@ struct CxxrtlWorker {
SigMap &sigmap = sigmaps[module];
sigmap.set(module);
- if (module->get_bool_attribute(ID(cxxrtl.blackbox))) {
+ if (module->get_bool_attribute(ID(cxxrtl_blackbox))) {
for (auto port : module->ports) {
RTLIL::Wire *wire = module->wire(port);
- if (wire->has_attribute(ID(cxxrtl.edge))) {
- RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl.edge)];
+ if (wire->has_attribute(ID(cxxrtl_edge))) {
+ RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)];
if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire))
- log_cmd_error("Attribute `cxxrtl.edge' of port `%s.%s' is not a string with one character per bit.\n",
+ log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' is not a string with one character per bit.\n",
log_id(module), log_signal(wire));
- std::string edges = wire->get_string_attribute(ID(cxxrtl.edge));
+ std::string edges = wire->get_string_attribute(ID(cxxrtl_edge));
for (int i = 0; i < GetSize(wire); i++) {
RTLIL::SigSpec wire_sig = wire;
switch (edges[i]) {
@@ -1839,7 +1840,7 @@ struct CxxrtlWorker {
case 'n': register_edge_signal(sigmap, wire_sig[i], RTLIL::STn); break;
case 'a': register_edge_signal(sigmap, wire_sig[i], RTLIL::STe); break;
default:
- log_cmd_error("Attribute `cxxrtl.edge' of port `%s.%s' contains specifiers "
+ log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' contains specifiers "
"other than '-', 'p', 'n', or 'a'.\n",
log_id(module), log_signal(wire));
}
@@ -1868,12 +1869,12 @@ struct CxxrtlWorker {
RTLIL::Module *cell_module = design->module(cell->type);
if (cell_module &&
cell_module->get_blackbox_attribute() &&
- !cell_module->get_bool_attribute(ID(cxxrtl.blackbox)))
+ !cell_module->get_bool_attribute(ID(cxxrtl_blackbox)))
log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", log_id(cell->type));
if (cell_module &&
- cell_module->get_bool_attribute(ID(cxxrtl.blackbox)) &&
- cell_module->get_bool_attribute(ID(cxxrtl.template)))
+ cell_module->get_bool_attribute(ID(cxxrtl_blackbox)) &&
+ cell_module->get_bool_attribute(ID(cxxrtl_template)))
blackbox_specializations[cell_module].insert(template_args(cell));
FlowGraph::Node *node = flow.add_node(cell);
@@ -2064,7 +2065,7 @@ struct CxxrtlWorker {
has_sync_init = has_packed_mem = false;
for (auto module : design->modules()) {
- if (module->get_blackbox_attribute() && !module->has_attribute(ID(cxxrtl.blackbox)))
+ if (module->get_blackbox_attribute() && !module->has_attribute(ID(cxxrtl_blackbox)))
continue;
if (!design->selected_whole_module(module))
@@ -2155,12 +2156,12 @@ struct CxxrtlBackend : public Backend {
log("For example, the following Verilog code defines a CXXRTL black box interface for\n");
log("a synchronous debug sink:\n");
log("\n");
- log(" (* cxxrtl.blackbox *)\n");
+ log(" (* cxxrtl_blackbox *)\n");
log(" module debug(...);\n");
- log(" (* cxxrtl.edge = \"p\" *) input clk;\n");
+ log(" (* cxxrtl_edge = \"p\" *) input clk;\n");
log(" input en;\n");
log(" input [7:0] i_data;\n");
- log(" (* cxxrtl.sync *) output [7:0] o_data;\n");
+ log(" (* cxxrtl_sync *) output [7:0] o_data;\n");
log(" endmodule\n");
log("\n");
log("For this HDL interface, this backend will generate the following C++ interface:\n");
@@ -2205,13 +2206,13 @@ struct CxxrtlBackend : public Backend {
log("port widths. For example, the following Verilog code defines a CXXRTL black box\n");
log("interface for a configurable width debug sink:\n");
log("\n");
- log(" (* cxxrtl.blackbox, cxxrtl.template = \"WIDTH\" *)\n");
+ log(" (* cxxrtl_blackbox, cxxrtl_template = \"WIDTH\" *)\n");
log(" module debug(...);\n");
log(" parameter WIDTH = 8;\n");
- log(" (* cxxrtl.edge = \"p\" *) input clk;\n");
+ log(" (* cxxrtl_edge = \"p\" *) input clk;\n");
log(" input en;\n");
- log(" (* cxxrtl.width = \"WIDTH\" *) input [WIDTH - 1:0] i_data;\n");
- log(" (* cxxrtl.width = \"WIDTH\" *) output [WIDTH - 1:0] o_data;\n");
+ log(" (* cxxrtl_width = \"WIDTH\" *) input [WIDTH - 1:0] i_data;\n");
+ log(" (* cxxrtl_width = \"WIDTH\" *) output [WIDTH - 1:0] o_data;\n");
log(" endmodule\n");
log("\n");
log("For this parametric HDL interface, this backend will generate the following C++\n");
@@ -2245,27 +2246,27 @@ struct CxxrtlBackend : public Backend {
log("\n");
log("The following attributes are recognized by this backend:\n");
log("\n");
- log(" cxxrtl.blackbox\n");
+ log(" cxxrtl_blackbox\n");
log(" only valid on modules. if specified, the module contents are ignored,\n");
log(" and the generated code includes only the module interface and a factory\n");
log(" function, which will be called to instantiate the module.\n");
log("\n");
- log(" cxxrtl.edge\n");
+ log(" cxxrtl_edge\n");
log(" only valid on inputs of black boxes. must be one of \"p\", \"n\", \"a\".\n");
log(" if specified on signal `clk`, the generated code includes edge detectors\n");
log(" `posedge_p_clk()` (if \"p\"), `negedge_p_clk()` (if \"n\"), or both (if\n");
log(" \"a\"), simplifying implementation of clocked black boxes.\n");
log("\n");
- log(" cxxrtl.template\n");
+ log(" cxxrtl_template\n");
log(" only valid on black boxes. must contain a space separated sequence of\n");
log(" identifiers that have a corresponding black box parameters. for each\n");
log(" of them, the generated code includes a `size_t` template parameter.\n");
log("\n");
- log(" cxxrtl.width\n");
+ log(" cxxrtl_width\n");
log(" only valid on ports of black boxes. must be a constant expression, which\n");
log(" is directly inserted into generated code.\n");
log("\n");
- log(" cxxrtl.comb, cxxrtl.sync\n");
+ log(" cxxrtl_comb, cxxrtl_sync\n");
log(" only valid on outputs of black boxes. if specified, indicates that every\n");
log(" bit of the output port is driven, correspondingly, by combinatorial or\n");
log(" synchronous logic. this knowledge is used for scheduling optimizations.\n");
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 92cf92fa8..6fda92d73 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -784,7 +784,7 @@ void AigerReader::post_process()
ff->attributes[ID::abc9_mergeability] = mergeability[i];
}
- dict<RTLIL::IdString, int> wideports_cache;
+ dict<RTLIL::IdString, std::pair<int,int>> wideports_cache;
if (!map_filename.empty()) {
std::ifstream mf(map_filename);
@@ -799,11 +799,12 @@ void AigerReader::post_process()
log_assert(wire->port_input);
log_debug("Renaming input %s", log_id(wire));
+ RTLIL::Wire *existing = nullptr;
if (index == 0) {
// Cope with the fact that a CI might be identical
// to a PI (necessary due to ABC); in those cases
// simply connect the latter to the former
- RTLIL::Wire* existing = module->wire(escaped_s);
+ existing = module->wire(escaped_s);
if (!existing)
module->rename(wire, escaped_s);
else {
@@ -812,20 +813,29 @@ void AigerReader::post_process()
}
log_debug(" -> %s\n", log_id(escaped_s));
}
- else if (index > 0) {
- std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
- RTLIL::Wire* existing = module->wire(indexed_name);
- if (!existing) {
+ else {
+ RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
+ existing = module->wire(indexed_name);
+ if (!existing)
module->rename(wire, indexed_name);
- if (wideports)
- wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);
- }
else {
module->connect(wire, existing);
wire->port_input = false;
}
log_debug(" -> %s\n", log_id(indexed_name));
}
+
+ if (wideports && !existing) {
+ auto r = wideports_cache.insert(escaped_s);
+ if (r.second) {
+ r.first->second.first = index;
+ r.first->second.second = index;
+ }
+ else {
+ r.first->second.first = std::min(r.first->second.first, index);
+ r.first->second.second = std::max(r.first->second.second, index);
+ }
+ }
}
else if (type == "output") {
log_assert(static_cast<unsigned>(variable + co_count) < outputs.size());
@@ -834,14 +844,14 @@ void AigerReader::post_process()
log_assert(wire->port_output);
log_debug("Renaming output %s", log_id(wire));
+ RTLIL::Wire *existing;
if (index == 0) {
// Cope with the fact that a CO might be identical
// to a PO (necessary due to ABC); in those cases
// simply connect the latter to the former
- RTLIL::Wire* existing = module->wire(escaped_s);
- if (!existing) {
+ existing = module->wire(escaped_s);
+ if (!existing)
module->rename(wire, escaped_s);
- }
else {
wire->port_output = false;
existing->port_output = true;
@@ -850,14 +860,11 @@ void AigerReader::post_process()
}
log_debug(" -> %s\n", log_id(escaped_s));
}
- else if (index > 0) {
- std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
- RTLIL::Wire* existing = module->wire(indexed_name);
- if (!existing) {
+ else {
+ RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
+ existing = module->wire(indexed_name);
+ if (!existing)
module->rename(wire, indexed_name);
- if (wideports)
- wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);
- }
else {
wire->port_output = false;
existing->port_output = true;
@@ -865,10 +872,18 @@ void AigerReader::post_process()
}
log_debug(" -> %s\n", log_id(indexed_name));
}
- int init;
- mf >> init;
- if (init < 2)
- wire->attributes[ID::init] = init;
+
+ if (wideports && !existing) {
+ auto r = wideports_cache.insert(escaped_s);
+ if (r.second) {
+ r.first->second.first = index;
+ r.first->second.second = index;
+ }
+ else {
+ r.first->second.first = std::min(r.first->second.first, index);
+ r.first->second.second = std::max(r.first->second.second, index);
+ }
+ }
}
else if (type == "box") {
RTLIL::Cell* cell = module->cell(stringf("$box%d", variable));
@@ -882,7 +897,8 @@ void AigerReader::post_process()
for (auto &wp : wideports_cache) {
auto name = wp.first;
- int width = wp.second + 1;
+ int min = wp.second.first;
+ int max = wp.second.second;
RTLIL::Wire *wire = module->wire(name);
if (wire)
@@ -891,7 +907,7 @@ void AigerReader::post_process()
// Do not make ports with a mix of input/output into
// wide ports
bool port_input = false, port_output = false;
- for (int i = 0; i < width; i++) {
+ for (int i = min; i <= max; i++) {
RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
RTLIL::Wire *other_wire = module->wire(other_name);
if (other_wire) {
@@ -900,20 +916,21 @@ void AigerReader::post_process()
}
}
- wire = module->addWire(name, width);
+ wire = module->addWire(name, max-min+1);
+ wire->start_offset = min;
wire->port_input = port_input;
wire->port_output = port_output;
- for (int i = 0; i < width; i++) {
- RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
+ for (int i = min; i <= max; i++) {
+ RTLIL::IdString other_name = stringf("%s[%d]", name.c_str(), i);
RTLIL::Wire *other_wire = module->wire(other_name);
if (other_wire) {
other_wire->port_input = false;
other_wire->port_output = false;
if (wire->port_input)
- module->connect(other_wire, SigSpec(wire, i));
+ module->connect(other_wire, SigSpec(wire, i-min));
else
- module->connect(SigSpec(wire, i), other_wire);
+ module->connect(SigSpec(wire, i-min), other_wire);
}
}
}
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 733556621..6a9af3f57 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -946,6 +946,7 @@ RTLIL::Const AstNode::realAsConst(int width)
// create a new AstModule from an AST_MODULE AST node
static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false)
{
+ log_assert(current_scope.empty());
log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
if (defer)
@@ -1117,6 +1118,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
}
ignoreThisSignalsInInitial = RTLIL::SigSpec();
+ current_scope.clear();
}
else {
for (auto &attr : ast->attributes) {
@@ -1229,11 +1231,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
// process enum/other declarations
(*it)->simplify(true, false, false, 1, -1, false, false);
design->verilog_packages.push_back((*it)->clone());
+ current_scope.clear();
}
else {
// must be global definition
(*it)->simplify(false, false, false, 1, -1, false, false); //process enum/other declarations
design->verilog_globals.push_back((*it)->clone());
+ current_scope.clear();
}
}
}
diff --git a/frontends/rpc/Makefile.inc b/frontends/rpc/Makefile.inc
index 7b270b6fe..fa1d068f9 100644
--- a/frontends/rpc/Makefile.inc
+++ b/frontends/rpc/Makefile.inc
@@ -1,3 +1,3 @@
-ifneq ($(CONFIG),emcc)
+ifeq ($(DISABLE_SPAWN),0)
OBJS += frontends/rpc/rpc_frontend.o
endif
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index 519151310..fe4bda68e 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -149,7 +149,7 @@ RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj)
return s;
}
-void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj)
+void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj, Netlist *nl)
{
MapIter mi;
Att *attr;
@@ -163,6 +163,68 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
continue;
attributes[RTLIL::escape_id(attr->Key())] = RTLIL::Const(std::string(attr->Value()));
}
+
+ if (nl) {
+ auto type_range = nl->GetTypeRange(obj->Name());
+ if (!type_range)
+ return;
+ if (!type_range->IsTypeEnum())
+ return;
+ if (nl->IsFromVhdl() && strcmp(type_range->GetTypeName(), "STD_LOGIC") == 0)
+ return;
+ auto type_name = type_range->GetTypeName();
+ if (!type_name)
+ return;
+ attributes.emplace(ID::wiretype, RTLIL::escape_id(type_name));
+
+ MapIter mi;
+ const char *k, *v;
+ FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mi, &k, &v) {
+ if (nl->IsFromVerilog()) {
+ // Expect <decimal>'b<binary>
+ auto p = strchr(v, '\'');
+ if (p) {
+ if (*(p+1) != 'b')
+ p = nullptr;
+ else
+ for (auto q = p+2; *q != '\0'; q++)
+ if (*q != '0' && *q != '1') {
+ p = nullptr;
+ break;
+ }
+ }
+ if (p == nullptr)
+ log_error("Expected TypeRange value '%s' to be of form <decimal>'b<binary>.\n", v);
+ attributes.emplace(stringf("\\enum_value_%s", p+2), RTLIL::escape_id(k));
+ }
+ else if (nl->IsFromVhdl()) {
+ // Expect "<binary>"
+ auto p = v;
+ if (p) {
+ if (*p != '"')
+ p = nullptr;
+ else {
+ auto *q = p+1;
+ for (; *q != '"'; q++)
+ if (*q != '0' && *q != '1') {
+ p = nullptr;
+ break;
+ }
+ if (p && *(q+1) != '\0')
+ p = nullptr;
+ }
+ }
+ if (p == nullptr)
+ log_error("Expected TypeRange value '%s' to be of form \"<binary>\".\n", v);
+ auto l = strlen(p);
+ auto q = (char*)malloc(l+1-2);
+ strncpy(q, p+1, l-2);
+ q[l-2] = '\0';
+ attributes.emplace(stringf("\\enum_value_%s", q), RTLIL::escape_id(k));
+ free(q);
+ }
+ }
+ }
}
RTLIL::SigSpec VerificImporter::operatorInput(Instance *inst)
@@ -845,7 +907,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
log(" importing port %s.\n", port->Name());
RTLIL::Wire *wire = module->addWire(RTLIL::escape_id(port->Name()));
- import_attributes(wire->attributes, port);
+ import_attributes(wire->attributes, port, nl);
wire->port_id = nl->IndexOf(port) + 1;
@@ -872,7 +934,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
RTLIL::Wire *wire = module->addWire(RTLIL::escape_id(portbus->Name()), portbus->Size());
wire->start_offset = min(portbus->LeftIndex(), portbus->RightIndex());
- import_attributes(wire->attributes, portbus);
+ import_attributes(wire->attributes, portbus, nl);
if (portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_IN)
wire->port_input = true;
@@ -1021,7 +1083,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
log(" importing net %s as %s.\n", net->Name(), log_id(wire_name));
RTLIL::Wire *wire = module->addWire(wire_name);
- import_attributes(wire->attributes, net);
+ import_attributes(wire->attributes, net, nl);
net_map[net] = wire;
}
@@ -1046,7 +1108,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
RTLIL::Wire *wire = module->addWire(wire_name, netbus->Size());
wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex());
- import_attributes(wire->attributes, netbus);
+ import_attributes(wire->attributes, netbus, nl);
RTLIL::Const initval = Const(State::Sx, GetSize(wire));
bool initval_valid = false;
diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h
index 2ccfcd42c..f168a2588 100644
--- a/frontends/verific/verific.h
+++ b/frontends/verific/verific.h
@@ -79,7 +79,7 @@ struct VerificImporter
RTLIL::SigBit net_map_at(Verific::Net *net);
RTLIL::IdString new_verific_id(Verific::DesignObj *obj);
- void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, Verific::DesignObj *obj);
+ void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, Verific::DesignObj *obj, Verific::Netlist *nl = nullptr);
RTLIL::SigSpec operatorInput(Verific::Instance *inst);
RTLIL::SigSpec operatorInput1(Verific::Instance *inst);
diff --git a/kernel/constids.inc b/kernel/constids.inc
index 68a5782fd..27b652e24 100644
--- a/kernel/constids.inc
+++ b/kernel/constids.inc
@@ -29,6 +29,7 @@ X(B)
X(BI)
X(blackbox)
X(B_SIGNED)
+X(bugpoint_keep)
X(B_WIDTH)
X(C)
X(cells_not_processed)
@@ -199,6 +200,7 @@ X(wand)
X(whitebox)
X(WIDTH)
X(wildcard_port_conns)
+X(wiretype)
X(wor)
X(WORDS)
X(WR_ADDR)
diff --git a/kernel/driver.cc b/kernel/driver.cc
index 5f0959776..57ed7b8b4 100644
--- a/kernel/driver.cc
+++ b/kernel/driver.cc
@@ -155,6 +155,19 @@ int yosys_history_offset = 0;
std::string yosys_history_file;
#endif
+#if defined(__wasm)
+extern "C" {
+ // FIXME: WASI does not currently support exceptions.
+ void* __cxa_allocate_exception(size_t thrown_size) throw() {
+ return malloc(thrown_size);
+ }
+ bool __cxa_uncaught_exception() throw();
+ void __cxa_throw(void* thrown_exception, struct std::type_info * tinfo, void (*dest)(void*)) {
+ std::terminate();
+ }
+}
+#endif
+
void yosys_atexit()
{
#if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE)
@@ -587,9 +600,11 @@ int main(int argc, char **argv)
ru_buffer.ru_utime.tv_usec += ru_buffer_children.ru_utime.tv_usec;
ru_buffer.ru_stime.tv_sec += ru_buffer_children.ru_stime.tv_sec;
ru_buffer.ru_stime.tv_usec += ru_buffer_children.ru_stime.tv_usec;
+#if defined(__linux__) || defined(__FreeBSD__)
ru_buffer.ru_maxrss = std::max(ru_buffer.ru_maxrss, ru_buffer_children.ru_maxrss);
+#endif
}
-# if defined(__linux__) || defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
meminfo = stringf(", MEM: %.2f MB peak",
ru_buffer.ru_maxrss / 1024.0);
#endif
diff --git a/kernel/register.cc b/kernel/register.cc
index 925d0d776..02974e534 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -238,6 +238,7 @@ void Pass::call(RTLIL::Design *design, std::string command)
return;
if (tok[0] == '!') {
+#if !defined(YOSYS_DISABLE_SPAWN)
cmd_buf = command.substr(command.find('!') + 1);
while (!cmd_buf.empty() && (cmd_buf.back() == ' ' || cmd_buf.back() == '\t' ||
cmd_buf.back() == '\r' || cmd_buf.back() == '\n'))
@@ -247,6 +248,9 @@ void Pass::call(RTLIL::Design *design, std::string command)
if (retCode != 0)
log_cmd_error("Shell command returned error code %d.\n", retCode);
return;
+#else
+ log_cmd_error("Shell is not available.\n");
+#endif
}
while (!tok.empty()) {
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 2aefe30b1..196e301b6 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -2619,16 +2619,15 @@ void RTLIL::Cell::setParam(RTLIL::IdString paramname, RTLIL::Const value)
const RTLIL::Const &RTLIL::Cell::getParam(RTLIL::IdString paramname) const
{
- static const RTLIL::Const empty;
const auto &it = parameters.find(paramname);
if (it != parameters.end())
return it->second;
if (module && module->design) {
RTLIL::Module *m = module->design->module(type);
if (m)
- return m->parameter_default_values.at(paramname, empty);
+ return m->parameter_default_values.at(paramname);
}
- return empty;
+ throw std::out_of_range("Cell::getParam()");
}
void RTLIL::Cell::sort()
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index 01131601f..2ec3dca0c 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -45,8 +45,10 @@
# include <unistd.h>
# include <dirent.h>
# include <sys/types.h>
-# include <sys/wait.h>
# include <sys/stat.h>
+# if !defined(YOSYS_DISABLE_SPAWN)
+# include <sys/wait.h>
+# endif
#endif
#if !defined(_WIN32) && defined(YOSYS_ENABLE_GLOB)
@@ -336,16 +338,13 @@ bool patmatch(const char *pattern, const char *string)
return false;
}
+#if !defined(YOSYS_DISABLE_SPAWN)
int run_command(const std::string &command, std::function<void(const std::string&)> process_line)
{
if (!process_line)
return system(command.c_str());
-#ifdef EMSCRIPTEN
- FILE *f = nullptr;
-#else
FILE *f = popen(command.c_str(), "r");
-#endif
if (f == nullptr)
return -1;
@@ -368,10 +367,16 @@ int run_command(const std::string &command, std::function<void(const std::string
return WEXITSTATUS(ret);
#endif
}
+#endif
std::string make_temp_file(std::string template_str)
{
-#ifdef _WIN32
+#if defined(__wasm)
+ size_t pos = template_str.rfind("XXXXXX");
+ log_assert(pos != std::string::npos);
+ static size_t index = 0;
+ template_str.replace(pos, 6, stringf("%06zu", index++));
+#elif defined(_WIN32)
if (template_str.rfind("/tmp/", 0) == 0) {
# ifdef __MINGW32__
char longpath[MAX_PATH + 1];
@@ -420,10 +425,14 @@ std::string make_temp_file(std::string template_str)
std::string make_temp_dir(std::string template_str)
{
-#ifdef _WIN32
+#if defined(_WIN32)
template_str = make_temp_file(template_str);
mkdir(template_str.c_str());
return template_str;
+#elif defined(__wasm)
+ template_str = make_temp_file(template_str);
+ mkdir(template_str.c_str(), 0777);
+ return template_str;
#else
# ifndef NDEBUG
size_t pos = template_str.rfind("XXXXXX");
@@ -806,7 +815,7 @@ std::string proc_self_dirname()
path += char(shortpath[i]);
return path;
}
-#elif defined(EMSCRIPTEN)
+#elif defined(EMSCRIPTEN) || defined(__wasm)
std::string proc_self_dirname()
{
return "/";
@@ -815,7 +824,7 @@ std::string proc_self_dirname()
#error "Don't know how to determine process executable base path!"
#endif
-#ifdef EMSCRIPTEN
+#if defined(EMSCRIPTEN) || defined(__wasm)
std::string proc_share_dirname()
{
return "/share/";
diff --git a/kernel/yosys.h b/kernel/yosys.h
index ed48eec09..af1e376b1 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -264,7 +264,9 @@ int readsome(std::istream &f, char *s, int n);
std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false);
std::vector<std::string> split_tokens(const std::string &text, const char *sep = " \t\r\n");
bool patmatch(const char *pattern, const char *string);
+#if !defined(YOSYS_DISABLE_SPAWN)
int run_command(const std::string &command, std::function<void(const std::string&)> process_line = std::function<void(const std::string&)>());
+#endif
std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX");
std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX");
bool check_file_exists(std::string filename, bool is_exec = false);
diff --git a/libs/ezsat/ezminisat.cc b/libs/ezsat/ezminisat.cc
index 4be5fd493..ac4defac3 100644
--- a/libs/ezsat/ezminisat.cc
+++ b/libs/ezsat/ezminisat.cc
@@ -29,11 +29,12 @@
#include <limits.h>
#include <stdint.h>
-#include <csignal>
#include <cinttypes>
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__wasm)
+# include <csignal>
# include <unistd.h>
+# define HAS_ALARM
#endif
#include "../minisat/Solver.h"
@@ -84,7 +85,7 @@ bool ezMiniSAT::eliminated(int idx)
}
#endif
-#ifndef _WIN32
+#if defined(HAS_ALARM)
ezMiniSAT *ezMiniSAT::alarmHandlerThis = NULL;
clock_t ezMiniSAT::alarmHandlerTimeout = 0;
@@ -183,7 +184,7 @@ contradiction:
#endif
}
-#ifndef _WIN32
+#if defined(HAS_ALARM)
struct sigaction sig_action;
struct sigaction old_sig_action;
int old_alarm_timeout = 0;
@@ -202,7 +203,7 @@ contradiction:
bool foundSolution = minisatSolver->solve(assumps);
-#ifndef _WIN32
+#if defined(HAS_ALARM)
if (solverTimeout > 0) {
if (alarmHandlerTimeout == 0)
solverTimoutStatus = true;
diff --git a/libs/minisat/00_PATCH_wasm.patch b/libs/minisat/00_PATCH_wasm.patch
new file mode 100644
index 000000000..0bcff7d77
--- /dev/null
+++ b/libs/minisat/00_PATCH_wasm.patch
@@ -0,0 +1,34 @@
+--- System.cc
++++ System.cc
+@@ -101,7 +101,7 @@ double Minisat::memUsedPeak(bool) { return 0; }
+ #endif
+
+
+-#if !defined(_MSC_VER) && !defined(__MINGW32__)
++#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm)
+ void Minisat::limitMemory(uint64_t max_mem_mb)
+ {
+ // FIXME: OpenBSD does not support RLIMIT_AS. Not sure how well RLIMIT_DATA works instead.
+@@ -133,7 +133,7 @@ void Minisat::limitMemory(uint64_t /*max_mem_mb*/)
+ #endif
+
+
+-#if !defined(_MSC_VER) && !defined(__MINGW32__)
++#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm)
+ void Minisat::limitTime(uint32_t max_cpu_time)
+ {
+ if (max_cpu_time != 0){
+@@ -156,9 +156,13 @@ void Minisat::limitTime(uint32_t /*max_cpu_time*/)
+
+ void Minisat::sigTerm(void handler(int))
+ {
++#if defined(__wasm)
++ (void)handler;
++#else
+ signal(SIGINT, handler);
+ signal(SIGTERM,handler);
+ #ifdef SIGXCPU
+ signal(SIGXCPU,handler);
+ #endif
++#endif
+ }
diff --git a/libs/minisat/00_UPDATE.sh b/libs/minisat/00_UPDATE.sh
index ea26215ab..51107e450 100755
--- a/libs/minisat/00_UPDATE.sh
+++ b/libs/minisat/00_UPDATE.sh
@@ -16,4 +16,4 @@ patch -p0 < 00_PATCH_mkLit_default_arg.patch
patch -p0 < 00_PATCH_remove_zlib.patch
patch -p0 < 00_PATCH_no_fpu_control.patch
patch -p0 < 00_PATCH_typofixes.patch
-
+patch -p0 < 00_PATCH_wasm.patch
diff --git a/libs/minisat/System.cc b/libs/minisat/System.cc
index 1921a1d71..345be8c4c 100644
--- a/libs/minisat/System.cc
+++ b/libs/minisat/System.cc
@@ -101,7 +101,7 @@ double Minisat::memUsedPeak(bool) { return 0; }
#endif
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm)
void Minisat::limitMemory(uint64_t max_mem_mb)
{
// FIXME: OpenBSD does not support RLIMIT_AS. Not sure how well RLIMIT_DATA works instead.
@@ -133,7 +133,7 @@ void Minisat::limitMemory(uint64_t /*max_mem_mb*/)
#endif
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm)
void Minisat::limitTime(uint32_t max_cpu_time)
{
if (max_cpu_time != 0){
@@ -156,9 +156,13 @@ void Minisat::limitTime(uint32_t /*max_cpu_time*/)
void Minisat::sigTerm(void handler(int))
{
+#if defined(__wasm)
+ (void)handler;
+#else
signal(SIGINT, handler);
signal(SIGTERM,handler);
#ifdef SIGXCPU
signal(SIGXCPU,handler);
#endif
+#endif
}
diff --git a/manual/CHAPTER_Auxprogs.tex b/manual/CHAPTER_Auxprogs.tex
index 724d37f0b..f09b18f76 100644
--- a/manual/CHAPTER_Auxprogs.tex
+++ b/manual/CHAPTER_Auxprogs.tex
@@ -19,7 +19,8 @@ for details.
\section{yosys-abc}
-This is a unmodified copy of ABC \citeweblink{ABC}. Not all versions of Yosys
-work with all versions of ABC. So Yosys comes with its own yosys-abc to avoid
+This is a fork of ABC \citeweblink{ABC} with a small set of custom modifications
+that have not yet been accepted upstream. Not all versions of Yosys work with
+all versions of ABC. So Yosys comes with its own yosys-abc to avoid
compatibility issues between the two.
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 60f20fa6d..a88980eaf 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -1,5 +1,7 @@
+ifeq ($(DISABLE_SPAWN),0)
OBJS += passes/cmds/exec.o
+endif
OBJS += passes/cmds/add.o
OBJS += passes/cmds/delete.o
OBJS += passes/cmds/design.o
@@ -32,6 +34,8 @@ OBJS += passes/cmds/chformal.o
OBJS += passes/cmds/chtype.o
OBJS += passes/cmds/blackbox.o
OBJS += passes/cmds/ltp.o
+ifeq ($(DISABLE_SPAWN),0)
OBJS += passes/cmds/bugpoint.o
+endif
OBJS += passes/cmds/scratchpad.o
OBJS += passes/cmds/logger.o
diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc
index a75927393..00aac596f 100644
--- a/passes/cmds/bugpoint.cc
+++ b/passes/cmds/bugpoint.cc
@@ -30,23 +30,21 @@ struct BugpointPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" bugpoint [options]\n");
+ log(" bugpoint [options] -script <filename>\n");
log("\n");
- log("This command minimizes testcases that crash Yosys. It removes an arbitrary part\n");
- log("of the design and recursively invokes Yosys with a given script, repeating these\n");
- log("steps while it can find a smaller design that still causes a crash. Once this\n");
- log("command finishes, it replaces the current design with the smallest testcase it\n");
- log("was able to produce.\n");
+ log("This command minimizes the current design that is known to crash Yosys with the\n");
+ log("given script into a smaller testcase. It does this by removing an arbitrary part\n");
+ log("of the design and recursively invokes a new Yosys process with this modified design\n");
+ log("and the same script, repeating these steps while it can find a smaller design that\n");
+ log("still causes a crash. Once this command finishes, it replaces the current design\n");
+ log("with the smallest testcase it was able to produce.\n");
log("\n");
- log("It is possible to specify the kinds of design part that will be removed. If none\n");
- log("are specified, all parts of design will be removed.\n");
+ log(" -script <filename>\n");
+ log(" use this script to crash Yosys. required.\n");
log("\n");
log(" -yosys <filename>\n");
log(" use this Yosys binary. if not specified, `yosys` is used.\n");
log("\n");
- log(" -script <filename>\n");
- log(" use this script to crash Yosys. required.\n");
- log("\n");
log(" -grep <string>\n");
log(" only consider crashes that place this string in the log file.\n");
log("\n");
@@ -60,14 +58,21 @@ struct BugpointPass : public Pass {
log(" finishing. produces smaller and more useful testcases, but may fail to\n");
log(" produce any testcase at all if the crash is related to dangling wires.\n");
log("\n");
+ log("It is possible to constrain which parts of the design will be considered for\n");
+ log("removal. Unless one or more of the following options are specified, all parts\n");
+ log("will be considered.\n");
+ log("\n");
log(" -modules\n");
- log(" try to remove modules.\n");
+ log(" try to remove modules. modules with a (* bugpoint_keep *) attribute\n");
+ log(" will be skipped.\n");
log("\n");
log(" -ports\n");
- log(" try to remove module ports.\n");
+ log(" try to remove module ports. ports with a (* bugpoint_keep *) attribute\n");
+ log(" will be skipped (useful for clocks, resets, etc.)\n");
log("\n");
log(" -cells\n");
- log(" try to remove cells.\n");
+ log(" try to remove cells. cells with a (* bugpoint_keep *) attribute will\n");
+ log(" be skipped.\n");
log("\n");
log(" -connections\n");
log(" try to reconnect ports to 'x.\n");
@@ -139,9 +144,12 @@ struct BugpointPass : public Pass {
if (module->get_blackbox_attribute())
continue;
+ if (module->get_bool_attribute(ID::bugpoint_keep))
+ continue;
+
if (index++ == seed)
{
- log("Trying to remove module %s.\n", module->name.c_str());
+ log_header(design, "Trying to remove module %s.\n", log_id(module));
removed_module = module;
break;
}
@@ -160,18 +168,21 @@ struct BugpointPass : public Pass {
for (auto wire : mod->wires())
{
+ if (!wire->port_id)
+ continue;
+
if (!stage2 && wire->get_bool_attribute(ID($bugpoint)))
continue;
- if (wire->port_input || wire->port_output)
+ if (wire->get_bool_attribute(ID::bugpoint_keep))
+ continue;
+
+ if (index++ == seed)
{
- if (index++ == seed)
- {
- log("Trying to remove module port %s.\n", log_signal(wire));
- wire->port_input = wire->port_output = false;
- mod->fixup_ports();
- return design_copy;
- }
+ log_header(design, "Trying to remove module port %s.\n", log_id(wire));
+ wire->port_input = wire->port_output = false;
+ mod->fixup_ports();
+ return design_copy;
}
}
}
@@ -183,12 +194,16 @@ struct BugpointPass : public Pass {
if (mod->get_blackbox_attribute())
continue;
+
Cell *removed_cell = nullptr;
for (auto cell : mod->cells())
{
+ if (cell->get_bool_attribute(ID::bugpoint_keep))
+ continue;
+
if (index++ == seed)
{
- log("Trying to remove cell %s.%s.\n", mod->name.c_str(), cell->name.c_str());
+ log_header(design, "Trying to remove cell %s.%s.\n", log_id(mod), log_id(cell));
removed_cell = cell;
break;
}
@@ -219,7 +234,7 @@ struct BugpointPass : public Pass {
if (index++ == seed)
{
- log("Trying to remove cell port %s.%s.%s.\n", mod->name.c_str(), cell->name.c_str(), it.first.c_str());
+ log_header(design, "Trying to remove cell port %s.%s.%s.\n", log_id(mod), log_id(cell), log_id(it.first));
RTLIL::SigSpec port_x(State::Sx, port.size());
cell->unsetPort(it.first);
cell->setPort(it.first, port_x);
@@ -228,7 +243,7 @@ struct BugpointPass : public Pass {
if (!stage2 && (cell->input(it.first) || cell->output(it.first)) && index++ == seed)
{
- log("Trying to expose cell port %s.%s.%s as module port.\n", mod->name.c_str(), cell->name.c_str(), it.first.c_str());
+ log_header(design, "Trying to expose cell port %s.%s.%s as module port.\n", log_id(mod), log_id(cell), log_id(it.first));
RTLIL::Wire *wire = mod->addWire(NEW_ID, port.size());
wire->set_bool_attribute(ID($bugpoint));
wire->port_input = cell->input(it.first);
@@ -260,7 +275,7 @@ struct BugpointPass : public Pass {
{
if (index++ == seed)
{
- log("Trying to remove assign %s %s in %s.%s.\n", log_signal((*it).first), log_signal((*it).second), mod->name.c_str(), pr.first.c_str());
+ log_header(design, "Trying to remove assign %s %s in %s.%s.\n", log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first));
cs->actions.erase(it);
return design_copy;
}
@@ -286,7 +301,7 @@ struct BugpointPass : public Pass {
{
if (index++ == seed)
{
- log("Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal((*it).first), log_signal((*it).second), mod->name.c_str(), pr.first.c_str());
+ log_header(design, "Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first));
sy->actions.erase(it);
return design_copy;
}
@@ -304,6 +319,9 @@ struct BugpointPass : public Pass {
bool fast = false, clean = false;
bool modules = false, ports = false, cells = false, connections = false, assigns = false, updates = false, has_part = false;
+ log_header(design, "Executing BUGPOINT pass (minimize testcases).\n");
+ log_push();
+
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
@@ -447,6 +465,8 @@ struct BugpointPass : public Pass {
design->add(module->clone());
delete crashing_design;
}
+
+ log_pop();
}
} BugpointPass;
diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc
index 628ac4c5e..89d27c9aa 100644
--- a/passes/cmds/cover.cc
+++ b/passes/cmds/cover.cc
@@ -101,8 +101,8 @@ struct CoverPass : public Pass {
const std::string &filename = args[++argidx];
FILE *f = nullptr;
if (args[argidx-1] == "-d") {
- #ifdef _WIN32
- log_cmd_error("The 'cover -d' option is not supported on win32.\n");
+ #if defined(_WIN32) || defined(__wasm)
+ log_cmd_error("The 'cover -d' option is not supported on this platform.\n");
#else
char filename_buffer[4096];
snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", filename.c_str(), getpid());
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index c04ff438a..6e728c16f 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -630,8 +630,10 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp
std::string arg_mod, arg_memb;
std::unordered_map<std::string, bool> arg_mod_found;
std::unordered_map<std::string, bool> arg_memb_found;
- auto isalpha = [](const char &x) { return ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z')); };
- bool prefixed = GetSize(arg) >= 2 && isalpha(arg[0]) && arg[1] == ':';
+
+ auto isprefixed = [](const string &s) {
+ return GetSize(s) >= 2 && ((s[0] >= 'a' && s[0] <= 'z') || (s[0] >= 'A' && s[0] <= 'Z')) && s[1] == ':';
+ };
if (arg.size() == 0)
return;
@@ -759,31 +761,40 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp
return;
}
+ bool select_blackboxes = false;
+ if (arg.substr(0, 1) == "=") {
+ arg = arg.substr(1);
+ select_blackboxes = true;
+ }
+
if (!design->selected_active_module.empty()) {
arg_mod = design->selected_active_module;
arg_memb = arg;
- if (!prefixed) arg_memb_found[arg_memb] = false;
+ if (!isprefixed(arg_memb))
+ arg_memb_found[arg_memb] = false;
} else
- if (prefixed && arg[0] >= 'a' && arg[0] <= 'z') {
+ if (isprefixed(arg) && arg[0] >= 'a' && arg[0] <= 'z') {
arg_mod = "*", arg_memb = arg;
} else {
size_t pos = arg.find('/');
if (pos == std::string::npos) {
arg_mod = arg;
- if (!prefixed) arg_mod_found[arg_mod] = false;
+ if (!isprefixed(arg_mod))
+ arg_mod_found[arg_mod] = false;
} else {
arg_mod = arg.substr(0, pos);
- if (!prefixed) arg_mod_found[arg_mod] = false;
+ if (!isprefixed(arg_mod))
+ arg_mod_found[arg_mod] = false;
arg_memb = arg.substr(pos+1);
- bool arg_memb_prefixed = GetSize(arg_memb) >= 2 && isalpha(arg_memb[0]) && arg_memb[1] == ':';
- if (!arg_memb_prefixed) arg_memb_found[arg_memb] = false;
+ if (!isprefixed(arg_memb))
+ arg_memb_found[arg_memb] = false;
}
}
work_stack.push_back(RTLIL::Selection());
RTLIL::Selection &sel = work_stack.back();
- if (arg == "*" && arg_mod == "*") {
+ if (arg == "*" && arg_mod == "*" && select_blackboxes) {
select_filter_active_mod(design, work_stack.back());
return;
}
@@ -791,6 +802,9 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp
sel.full_selection = false;
for (auto mod : design->modules())
{
+ if (!select_blackboxes && mod->get_blackbox_attribute())
+ continue;
+
if (arg_mod.compare(0, 2, "A:") == 0) {
if (!match_attr(mod->attributes, arg_mod.substr(2)))
continue;
@@ -1104,6 +1118,9 @@ struct SelectPass : public Pass {
log(" <obj_pattern>\n");
log(" select the specified object(s) from the current module\n");
log("\n");
+ log("By default, patterns will not match black/white-box modules or their");
+ log("contents. To include such objects, prefix the pattern with '='.\n");
+ log("\n");
log("A <mod_pattern> can be a module name, wildcard expression (*, ?, [..])\n");
log("matching module names, or one of the following:\n");
log("\n");
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index 155ed0fcd..fa922454a 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -682,7 +682,7 @@ struct ShowPass : public Pass {
std::vector<std::pair<std::string, RTLIL::Selection>> color_selections;
std::vector<std::pair<std::string, RTLIL::Selection>> label_selections;
-#if defined(EMSCRIPTEN) || defined(_WIN32)
+#if defined(_WIN32) || defined(YOSYS_DISABLE_SPAWN)
std::string format = "dot";
std::string prefix = "show";
#else
@@ -849,10 +849,15 @@ struct ShowPass : public Pass {
std::string cmd = stringf(DOT_CMD, format.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str(), out_file.c_str());
#undef DOT_CMD
log("Exec: %s\n", cmd.c_str());
- if (run_command(cmd) != 0)
- log_cmd_error("Shell command failed!\n");
+ #if !defined(YOSYS_DISABLE_SPAWN)
+ if (run_command(cmd) != 0)
+ log_cmd_error("Shell command failed!\n");
+ #endif
}
+ #if defined(YOSYS_DISABLE_SPAWN)
+ log_assert(viewer_exe.empty() && !format.empty());
+ #else
if (!viewer_exe.empty()) {
#ifdef _WIN32
// system()/cmd.exe does not understand single quotes nor
@@ -876,6 +881,7 @@ struct ShowPass : public Pass {
if (run_command(cmd) != 0)
log_cmd_error("Shell command failed!\n");
}
+ #endif
if (flag_pause) {
#ifdef YOSYS_ENABLE_READLINE
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 2b35ace5e..0f5bff680 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -682,25 +682,37 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
+ bool is_signed = cell->getParam(ID::A_SIGNED).as_bool();
bool sub = cell->type == ID($sub);
+ int minsz = GetSize(sig_y);
+ minsz = std::min(minsz, GetSize(sig_a));
+ minsz = std::min(minsz, GetSize(sig_b));
+
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)
+ for (i = 0; i < minsz; i++) {
+ RTLIL::SigBit b = sig_b[i];
+ RTLIL::SigBit a = sig_a[i];
+ if (b == State::S0)
module->connect(sig_y[i], a);
else if (sub && b == State::S1 && a == State::S1)
module->connect(sig_y[i], State::S0);
- else if (!sub && a == State::S0 && b != State::Sx)
+ else if (!sub && a == State::S0)
module->connect(sig_y[i], b);
else
break;
}
if (i > 0) {
cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str());
- cell->setPort(ID::A, sig_a.extract_end(i));
- cell->setPort(ID::B, sig_b.extract_end(i));
+ log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module));
+ SigSpec new_a = sig_a.extract_end(i);
+ SigSpec new_b = sig_b.extract_end(i);
+ if (new_a.empty() && is_signed)
+ new_a = sig_a[i-1];
+ if (new_b.empty() && is_signed)
+ new_b = sig_b[i-1];
+ cell->setPort(ID::A, new_a);
+ cell->setPort(ID::B, new_b);
cell->setPort(ID::Y, sig_y.extract_end(i));
cell->fixup_parameters();
did_something = true;
@@ -716,6 +728,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
RTLIL::SigSpec sig_x = cell->getPort(ID::X);
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
RTLIL::SigSpec sig_co = cell->getPort(ID::CO);
+ bool is_signed = cell->getParam(ID::A_SIGNED).as_bool();
if (sig_bi != State::S0 && sig_bi != State::S1)
goto skip_fine_alu;
@@ -725,16 +738,20 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
bool bi = sig_bi == State::S1;
bool ci = sig_ci == State::S1;
+ int minsz = GetSize(sig_y);
+ minsz = std::min(minsz, GetSize(sig_a));
+ minsz = std::min(minsz, GetSize(sig_b));
+
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 == ((bi ^ ci) ? State::S1 : State::S0) && a != State::Sx) {
+ for (i = 0; i < minsz; i++) {
+ RTLIL::SigBit b = sig_b[i];
+ RTLIL::SigBit a = sig_a[i];
+ if (b == ((bi ^ ci) ? State::S1 : State::S0)) {
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 (a == (ci ? State::S1 : State::S0) && b != State::Sx) {
+ else if (a == (ci ? State::S1 : State::S0)) {
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);
@@ -744,8 +761,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (i > 0) {
cover("opt.opt_expr.fine.$alu");
- cell->setPort(ID::A, sig_a.extract_end(i));
- cell->setPort(ID::B, sig_b.extract_end(i));
+ log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module));
+ SigSpec new_a = sig_a.extract_end(i);
+ SigSpec new_b = sig_b.extract_end(i);
+ if (new_a.empty() && is_signed)
+ new_a = sig_a[i-1];
+ if (new_b.empty() && is_signed)
+ new_b = sig_b[i-1];
+ cell->setPort(ID::A, new_a);
+ cell->setPort(ID::B, new_b);
cell->setPort(ID::X, sig_x.extract_end(i));
cell->setPort(ID::Y, sig_y.extract_end(i));
cell->setPort(ID::CO, sig_co.extract_end(i));
diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc
index bfddfd0eb..f16cc4a0b 100644
--- a/passes/pmgen/ice40_dsp.cc
+++ b/passes/pmgen/ice40_dsp.cc
@@ -73,11 +73,11 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
// SB_MAC16 Input Interface
SigSpec A = st.sigA;
- A.extend_u0(16, st.mul->parameters.at(ID::A_SIGNED, State::S0).as_bool());
+ A.extend_u0(16, st.mul->getParam(ID::A_SIGNED).as_bool());
log_assert(GetSize(A) == 16);
SigSpec B = st.sigB;
- B.extend_u0(16, st.mul->parameters.at(ID::B_SIGNED, State::S0).as_bool());
+ B.extend_u0(16, st.mul->getParam(ID::B_SIGNED).as_bool());
log_assert(GetSize(B) == 16);
SigSpec CD = st.sigCD;
@@ -248,8 +248,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
cell->setParam(ID(BOTADDSUB_CARRYSELECT), Const(0, 2));
cell->setParam(ID(MODE_8x8), State::S0);
- cell->setParam(ID::A_SIGNED, st.mul->parameters.at(ID::A_SIGNED, State::S0).as_bool());
- cell->setParam(ID::B_SIGNED, st.mul->parameters.at(ID::B_SIGNED, State::S0).as_bool());
+ cell->setParam(ID::A_SIGNED, st.mul->getParam(ID::A_SIGNED).as_bool());
+ cell->setParam(ID::B_SIGNED, st.mul->getParam(ID::B_SIGNED).as_bool());
if (st.ffO) {
if (st.o_lo)
diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg
index 9d649cb98..2456a49dc 100644
--- a/passes/pmgen/ice40_dsp.pmg
+++ b/passes/pmgen/ice40_dsp.pmg
@@ -65,7 +65,7 @@ code sigA sigB sigH
endcode
code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
- if (mul->type != \SB_MAC16 || !param(mul, \A_REG, State::S0).as_bool()) {
+ if (mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool()) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
@@ -86,7 +86,7 @@ code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
endcode
code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol
- if (mul->type != \SB_MAC16 || !param(mul, \B_REG, State::S0).as_bool()) {
+ if (mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool()) {
argQ = sigB;
subpattern(in_dffe);
if (dff) {
@@ -109,7 +109,7 @@ endcode
code argD ffFJKG sigH clock clock_pol
if (nusers(sigH) == 2 &&
(mul->type != \SB_MAC16 ||
- (!param(mul, \TOP_8x8_MULT_REG, State::S0).as_bool() && !param(mul, \BOT_8x8_MULT_REG, State::S0).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1, State::S0).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1, State::S0).as_bool()))) {
+ (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool()))) {
argD = sigH;
subpattern(out_dffe);
if (dff) {
@@ -148,7 +148,7 @@ endcode
code argD ffH sigH sigO clock clock_pol
if (ffFJKG && nusers(sigH) == 2 &&
- (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2, State::S0).as_bool())) {
+ (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) {
argD = sigH;
subpattern(out_dffe);
if (dff) {
@@ -179,7 +179,7 @@ reject_ffH: ;
endcode
match add
- if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT, State::S0).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT, State::S0).as_int() == 3)
+ if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT).as_int() == 3)
select add->type.in($add)
choice <IdString> AB {\A, \B}
@@ -205,7 +205,7 @@ code sigCD sigO cd_signed
if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
reject;
// If accumulator, check adder width and signedness
- if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED, State::S0).as_bool() != param(add, \A_SIGNED).as_bool()))
+ if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(add, \A_SIGNED).as_bool()))
reject;
sigO = port(add, \Y);
@@ -229,7 +229,7 @@ endcode
code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo
if (mul->type != \SB_MAC16 ||
// Ensure that register is not already used
- ((param(mul, \TOPOUTPUT_SELECT, 0).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT, 0).as_int() != 1) &&
+ ((param(mul, \TOPOUTPUT_SELECT).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT).as_int() != 1) &&
// Ensure that OLOADTOP/OLOADBOT is unused or zero
(port(mul, \OLOADTOP, State::S0).is_fully_zero() && port(mul, \OLOADBOT, State::S0).is_fully_zero()))) {
@@ -280,7 +280,7 @@ endcode
code argQ ffCD ffCDholdmux ffCDholdpol ffCDrstpol sigCD clock clock_pol
if (!sigCD.empty() && sigCD != sigO &&
- (mul->type != \SB_MAC16 || (!param(mul, \C_REG, State::S0).as_bool() && !param(mul, \D_REG, State::S0).as_bool()))) {
+ (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) {
argQ = sigCD;
subpattern(in_dffe);
if (dff) {
@@ -532,7 +532,7 @@ endcode
match ff
select ff->type.in($dff)
- // DSP48E1 does not support clock inversion
+ // SB_MAC16 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
slice offset GetSize(port(ff, \D))
diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg
index af47ab111..d40f073c9 100644
--- a/passes/pmgen/xilinx_dsp.pmg
+++ b/passes/pmgen/xilinx_dsp.pmg
@@ -95,7 +95,7 @@ code sigA sigB sigC sigD sigM clock
sigD = port(dsp, \D, SigSpec());
SigSpec P = port(dsp, \P);
- if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") {
+ if (param(dsp, \USE_MULT).decode_string() == "MULTIPLY") {
// Only care about those bits that are used
int i;
for (i = GetSize(P)-1; i >= 0; i--)
@@ -120,7 +120,7 @@ endcode
// reset functionality, using a subpattern discussed above)
// If matched, treat 'A' input as input of ADREG
code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock
- if (param(dsp, \ADREG, 1).as_int() == 0) {
+ if (param(dsp, \ADREG).as_int() == 0) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
@@ -144,7 +144,7 @@ endcode
match preAdd
if sigD.empty() || sigD.is_fully_zero()
// Ensure that preAdder not already used
- if param(dsp, \USE_DPORT, Const("FALSE")).decode_string() == "FALSE"
+ if param(dsp, \USE_DPORT).decode_string() == "FALSE"
if port(dsp, \INMODE, Const(0, 5)).is_fully_zero()
select preAdd->type.in($add)
@@ -176,7 +176,7 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem
// Only search for ffA2 if there was a pre-adder
// (otherwise ffA2 would have been matched as ffAD)
if (preAdd) {
- if (param(dsp, \AREG, 1).as_int() == 0) {
+ if (param(dsp, \AREG).as_int() == 0) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
@@ -237,7 +237,7 @@ endcode
// (5) Match 'B' input for B2REG
// If B2REG, then match 'B' input for B1REG
code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock ffB1 ffB1cemux ffB1rstmux ffB1cepol
- if (param(dsp, \BREG, 1).as_int() == 0) {
+ if (param(dsp, \BREG).as_int() == 0) {
argQ = sigB;
subpattern(in_dffe);
if (dff) {
@@ -287,7 +287,7 @@ endcode
// (6) Match 'D' input for DREG
code argQ ffD ffDcemux ffDrstmux ffDcepol ffDrstpol sigD clock
- if (param(dsp, \DREG, 1).as_int() == 0) {
+ if (param(dsp, \DREG).as_int() == 0) {
argQ = sigD;
subpattern(in_dffe);
if (dff) {
@@ -308,7 +308,7 @@ endcode
// (7) Match 'P' output that exclusively drives an MREG
code argD ffM ffMcemux ffMrstmux ffMcepol ffMrstpol sigM sigP clock
- if (param(dsp, \MREG, 1).as_int() == 0 && nusers(sigM) == 2) {
+ if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) {
argD = sigM;
subpattern(out_dffe);
if (dff) {
@@ -363,7 +363,7 @@ endcode
// (9) Match 'P' output that exclusively drives a PREG
code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol sigP clock
- if (param(dsp, \PREG, 1).as_int() == 0) {
+ if (param(dsp, \PREG).as_int() == 0) {
int users = 2;
// If ffMcemux and no postAdd new-value net must have three users: ffMcemux, ffM and ffPcemux
if (ffMcemux && !postAdd) users++;
@@ -424,7 +424,7 @@ endcode
// to implement this function
match overflow
if ffP
- if param(dsp, \USE_PATTERN_DETECT, Const("NO_PATDET")).decode_string() == "NO_PATDET"
+ if param(dsp, \USE_PATTERN_DETECT).decode_string() == "NO_PATDET"
select overflow->type.in($ge)
select GetSize(port(overflow, \Y)) <= 48
select port(overflow, \B).is_fully_const()
diff --git a/passes/pmgen/xilinx_dsp_CREG.pmg b/passes/pmgen/xilinx_dsp_CREG.pmg
index b20e4f458..42d4d1b9b 100644
--- a/passes/pmgen/xilinx_dsp_CREG.pmg
+++ b/passes/pmgen/xilinx_dsp_CREG.pmg
@@ -42,7 +42,7 @@ udata <bool> dffcepol dffrstpol
// and (b) uses the 'C' port
match dsp
select dsp->type.in(\DSP48A, \DSP48A1, \DSP48E1)
- select param(dsp, \CREG, 1).as_int() == 0
+ select param(dsp, \CREG).as_int() == 0
select nusers(port(dsp, \C, SigSpec())) > 1
endmatch
@@ -61,7 +61,7 @@ code sigC sigP clock
SigSpec P = port(dsp, \P);
if (!dsp->type.in(\DSP48E1) ||
- param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") {
+ param(dsp, \USE_MULT).decode_string() == "MULTIPLY") {
// Only care about those bits that are used
int i;
for (i = GetSize(P)-1; i >= 0; i--)
diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg
index b14a1ee0a..8babb88e6 100644
--- a/passes/pmgen/xilinx_dsp_cascade.pmg
+++ b/passes/pmgen/xilinx_dsp_cascade.pmg
@@ -188,7 +188,7 @@ arg next
// driven by the 'P' output of the previous DSP cell, and (c) has its
// 'PCIN' port unused
match nextP
- select !param(nextP, \CREG, State::S1).as_bool()
+ select !nextP->type.in(\DSP48E1) || !param(nextP, \CREG).as_bool()
select (nextP->type.in(\DSP48A, \DSP48A1) && port(nextP, \OPMODE, Const(0, 8)).extract(2,2) == Const::from_string("11")) || (nextP->type.in(\DSP48E1) && port(nextP, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011"))
select nusers(port(nextP, \C, SigSpec())) > 1
select nusers(port(nextP, \PCIN, SigSpec())) == 0
@@ -201,7 +201,7 @@ endmatch
match nextP_shift17
if !nextP
select nextP_shift17->type.in(\DSP48E1)
- select !param(nextP_shift17, \CREG, State::S1).as_bool()
+ select !param(nextP_shift17, \CREG).as_bool()
select port(nextP_shift17, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011")
select nusers(port(nextP_shift17, \C, SigSpec())) > 1
select nusers(port(nextP_shift17, \PCIN, SigSpec())) == 0
@@ -242,10 +242,10 @@ code argQ clock AREG
if (next && next->type.in(\DSP48E1)) {
Cell *prev = std::get<0>(chain.back());
- if (param(next, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT" &&
+ if (param(next, \A_INPUT).decode_string() == "DIRECT" &&
port(next, \ACIN, SigSpec()).is_fully_zero() &&
nusers(port(prev, \ACOUT, SigSpec())) <= 1) {
- if (param(prev, \AREG, 2) == 0) {
+ if (param(prev, \AREG) == 0) {
if (port(prev, \A) == port(next, \A))
AREG = 0;
}
@@ -259,9 +259,9 @@ code argQ clock AREG
if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTA, State::S0))
goto reject_AREG;
IdString CEA;
- if (param(prev, \AREG, 2) == 1)
+ if (param(prev, \AREG) == 1)
CEA = \CEA2;
- else if (param(prev, \AREG, 2) == 2)
+ else if (param(prev, \AREG) == 2)
CEA = \CEA1;
else log_abort();
if (!dffcemux && port(prev, CEA, State::S0) != State::S1)
@@ -282,11 +282,11 @@ code argQ clock BREG
BREG = -1;
if (next) {
Cell *prev = std::get<0>(chain.back());
- if (param(next, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT" &&
+ if ((next->type != \DSP48E1 || param(next, \B_INPUT).decode_string() == "DIRECT") &&
port(next, \BCIN, SigSpec()).is_fully_zero() &&
nusers(port(prev, \BCOUT, SigSpec())) <= 1) {
- if ((next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG, 0) == 0 && param(prev, \B1REG, 1) == 0) ||
- (next->type.in(\DSP48E1) && param(prev, \BREG, 2) == 0)) {
+ if ((next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG) == 0 && param(prev, \B1REG) == 0) ||
+ (next->type.in(\DSP48E1) && param(prev, \BREG) == 0)) {
if (port(prev, \B) == port(next, \B))
BREG = 0;
}
@@ -303,9 +303,9 @@ code argQ clock BREG
if (next->type.in(\DSP48A, \DSP48A1))
CEB = \CEB;
else if (next->type.in(\DSP48E1)) {
- if (param(prev, \BREG, 2) == 1)
+ if (param(prev, \BREG) == 1)
CEB = \CEB2;
- else if (param(prev, \BREG, 2) == 2)
+ else if (param(prev, \BREG) == 2)
CEB = \CEB1;
else log_abort();
}
@@ -315,7 +315,7 @@ code argQ clock BREG
if (dffcemux && port(dffcemux, \S) != port(prev, CEB, State::S0))
goto reject_BREG;
if (dffD == unextend(port(prev, \B))) {
- if (next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG, 0) != 0)
+ if (next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG) != 0)
goto reject_BREG;
BREG = 1;
}
diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc
index 24b525b93..b99653fb3 100644
--- a/passes/pmgen/xilinx_srl.cc
+++ b/passes/pmgen/xilinx_srl.cc
@@ -48,7 +48,7 @@ void run_fixed(xilinx_srl_pm &pm)
initval.append(State::Sx);
}
else if (cell->type.in(ID(FDRE), ID(FDRE_1))) {
- if (cell->parameters.at(ID::INIT, State::S0).as_bool())
+ if (cell->getParam(ID::INIT).as_bool())
initval.append(State::S1);
else
initval.append(State::S0);
@@ -71,7 +71,7 @@ void run_fixed(xilinx_srl_pm &pm)
else if (first_cell->type.in(ID($_DFF_N_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1)))
c->setParam(ID(CLKPOL), 0);
else if (first_cell->type.in(ID(FDRE))) {
- if (!first_cell->parameters.at(ID(IS_C_INVERTED), State::S0).as_bool())
+ if (!first_cell->getParam(ID(IS_C_INVERTED)).as_bool())
c->setParam(ID(CLKPOL), 1);
else
c->setParam(ID(CLKPOL), 0);
diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg
index 535b3dfdc..80f0a27c2 100644
--- a/passes/pmgen/xilinx_srl.pmg
+++ b/passes/pmgen/xilinx_srl.pmg
@@ -13,8 +13,8 @@ endcode
match first
select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)
select !first->has_keep_attr()
- select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED, State::S0).as_bool()
- select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED, State::S0).as_bool()
+ select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED).as_bool()
+ select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED).as_bool()
select !first->type.in(\FDRE, \FDRE_1) || port(first, \R, State::S0).is_fully_zero()
filter !non_first_cells.count(first)
generate
@@ -84,8 +84,8 @@ arg en_port
match first
select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)
select !first->has_keep_attr()
- select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED, State::S0).as_bool()
- select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED, State::S0).as_bool()
+ select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED).as_bool()
+ select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED).as_bool()
select !first->type.in(\FDRE, \FDRE_1) || port(first, \R, State::S0).is_fully_zero()
endmatch
@@ -111,9 +111,9 @@ match next
index <SigBit> port(next, \Q) === port(first, \D)
filter port(next, clk_port) == port(first, clk_port)
filter en_port == IdString() || port(next, en_port) == port(first, en_port)
- filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED, State::S0).as_bool() == param(first, \IS_C_INVERTED, State::S0).as_bool()
- filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED, State::S0).as_bool() == param(first, \IS_D_INVERTED, State::S0).as_bool()
- filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED, State::S0).as_bool() == param(first, \IS_R_INVERTED, State::S0).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()
filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R, State::S0).is_fully_zero()
endmatch
@@ -138,9 +138,9 @@ match next
index <SigBit> port(next, \Q) === port(chain.back(), \D)
filter port(next, clk_port) == port(first, clk_port)
filter en_port == IdString() || port(next, en_port) == port(first, en_port)
- filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED, State::S0).as_bool() == param(first, \IS_C_INVERTED, State::S0).as_bool()
- filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED, State::S0).as_bool() == param(first, \IS_D_INVERTED, State::S0).as_bool()
- filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED, State::S0).as_bool() == param(first, \IS_R_INVERTED, State::S0).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()
+ filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()
filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R, State::S0).is_fully_zero()
generate
Cell *cell = module->addCell(NEW_ID, chain.back()->type);
diff --git a/passes/sat/Makefile.inc b/passes/sat/Makefile.inc
index a928c57de..7118c1563 100644
--- a/passes/sat/Makefile.inc
+++ b/passes/sat/Makefile.inc
@@ -13,5 +13,6 @@ OBJS += passes/sat/fmcombine.o
OBJS += passes/sat/mutate.o
OBJS += passes/sat/cutpoint.o
OBJS += passes/sat/fminit.o
+ifeq ($(DISABLE_SPAWN),0)
OBJS += passes/sat/qbfsat.o
-
+endif
diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc
index 981271770..d99ca1b53 100644
--- a/passes/sat/qbfsat.cc
+++ b/passes/sat/qbfsat.cc
@@ -49,15 +49,15 @@ struct QbfSolutionType {
};
struct QbfSolveOptions {
- bool specialize, specialize_from_file, write_solution, nocleanup, dump_final_smt2, assume_outputs;
+ bool specialize, specialize_from_file, write_solution, nocleanup, dump_final_smt2, assume_outputs, assume_neg;
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) {};
+ nocleanup(false), dump_final_smt2(false), assume_outputs(false), assume_neg(false),
+ sat(false), unsat(false), show_smtbmc(false), argidx(0) {};
};
void recover_solution(QbfSolutionType &sol) {
@@ -98,11 +98,8 @@ dict<std::string, std::string> get_hole_loc_name_map(RTLIL::Module *module, cons
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
+ if (pos != sol.hole_to_value.end() && cell->type.in("$anyconst", "$anyseq")) {
+ log_assert(hole_loc_to_name.find(pos->first) == hole_loc_to_name.end());
hole_loc_to_name[pos->first] = cell->getPort(ID::Y).as_wire()->name.str();
}
}
@@ -242,7 +239,7 @@ void allconstify_inputs(RTLIL::Module *module, const pool<std::string> &input_wi
module->fixup_ports();
}
-void assume_miter_outputs(RTLIL::Module *module) {
+void assume_miter_outputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
std::vector<RTLIL::Wire *> wires_to_assume;
for (auto w : module->wires())
if (w->port_output && w->width == 1)
@@ -257,7 +254,14 @@ void assume_miter_outputs(RTLIL::Module *module) {
log("\n");
}
- for(auto i = 0; wires_to_assume.size() > 1; ++i) {
+ if (opt.assume_neg) {
+ for (unsigned int i = 0; i < wires_to_assume.size(); ++i) {
+ RTLIL::SigSpec n_wire = module->LogicNot(wires_to_assume[i]->name.str() + "__n__qbfsat", wires_to_assume[i], false, wires_to_assume[i]->get_src_attribute());
+ wires_to_assume[i] = n_wire.as_wire();
+ }
+ }
+
+ 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;
@@ -371,6 +375,10 @@ QbfSolveOptions parse_args(const std::vector<std::string> &args) {
opt.assume_outputs = true;
continue;
}
+ else if (args[opt.argidx] == "-assume-negative-polarity") {
+ opt.assume_neg = true;
+ continue;
+ }
else if (args[opt.argidx] == "-sat") {
opt.sat = true;
continue;
@@ -464,6 +472,11 @@ struct QbfSatPass : public Pass {
log(" -assume-outputs\n");
log(" Add an $assume cell for the conjunction of all one-bit module output wires.\n");
log("\n");
+ log(" -assume-negative-polarity\n");
+ log(" When adding $assume cells for one-bit module output wires, assume they are\n");
+ log(" negative polarity signals and should always be low, for example like the\n");
+ log(" miters created with the `miter` command.\n");
+ log("\n");
log(" -sat\n");
log(" Generate an error if the solver does not return \"sat\".\n");
log("\n");
@@ -512,7 +525,7 @@ struct QbfSatPass : public Pass {
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);
+ assume_miter_outputs(module, opt);
QbfSolutionType ret = qbf_solve(module, opt);
Pass::call(design, "design -pop");
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 766b954df..1802ba0de 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -57,7 +57,7 @@ passes/techmap/techmap.inc: techlibs/common/techmap.v
passes/techmap/techmap.o: passes/techmap/techmap.inc
-ifneq ($(CONFIG),emcc)
+ifeq ($(DISABLE_SPAWN),0)
TARGETS += $(PROGRAM_PREFIX)yosys-filterlib$(EXE)
EXTRA_OBJS += passes/techmap/filterlib.o
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index aff0baa44..fae8b2426 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -771,7 +771,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (abc_script[i] == ';' && abc_script[i+1] == ' ')
abc_script[i+1] = '\n';
- FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt");
+ std::string buffer = stringf("%s/abc.script", tempdir_name.c_str());
+ FILE *f = fopen(buffer.c_str(), "wt");
+ if (f == nullptr)
+ log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
fprintf(f, "%s\n", abc_script.c_str());
fclose(f);
@@ -807,7 +810,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
handle_loops();
- std::string buffer = stringf("%s/input.blif", tempdir_name.c_str());
+ buffer = stringf("%s/input.blif", tempdir_name.c_str());
f = fopen(buffer.c_str(), "wt");
if (f == nullptr)
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
@@ -1541,11 +1544,15 @@ struct AbcPass : public Pass {
size_t argidx, g_argidx;
bool g_arg_from_cmd = false;
+#if defined(__wasm)
+ const char *pwd = ".";
+#else
char pwd [PATH_MAX];
if (!getcwd(pwd, sizeof(pwd))) {
log_cmd_error("getcwd failed: %s\n", strerror(errno));
log_abort();
}
+#endif
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
if (arg == "-exe" && argidx+1 < args.size()) {
diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc
index 18618ff91..0bf547921 100644
--- a/passes/techmap/abc9_exe.cc
+++ b/passes/techmap/abc9_exe.cc
@@ -219,6 +219,17 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
for (size_t pos = abc9_script.find("{R}"); pos != std::string::npos; pos = abc9_script.find("{R}", pos))
abc9_script = abc9_script.substr(0, pos) + R + abc9_script.substr(pos+3);
+ if (design->scratchpad_get_bool("abc9.nomfs"))
+ for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos))
+ abc9_script = abc9_script.erase(pos, strlen("&mfs"));
+ else {
+ auto s = stringf("&write -n %s/output.aig; ", tempdir_name.c_str());
+ for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) {
+ abc9_script = abc9_script.insert(pos, s);
+ pos += GetSize(s) + strlen("&mfs");
+ }
+ }
+
abc9_script += stringf("; &ps -l; &write -n %s/output.aig", tempdir_name.c_str());
if (design->scratchpad_get_bool("abc9.verify")) {
if (dff_mode)
@@ -272,8 +283,12 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
free(abc9_argv[2]);
free(abc9_argv[3]);
#endif
- if (ret != 0)
- log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
+ if (ret != 0) {
+ if (check_file_exists(stringf("%s/output.aig", tempdir_name.c_str())))
+ log_warning("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
+ else
+ log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
+ }
}
struct Abc9ExePass : public Pass {
@@ -405,11 +420,15 @@ struct Abc9ExePass : public Pass {
}
size_t argidx;
+#if defined(__wasm)
+ const char *pwd = ".";
+#else
char pwd [PATH_MAX];
if (!getcwd(pwd, sizeof(pwd))) {
log_cmd_error("getcwd failed: %s\n", strerror(errno));
log_abort();
}
+#endif
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
if (arg == "-exe" && argidx+1 < args.size()) {
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc
index 78c902866..1345188a4 100644
--- a/passes/techmap/abc9_ops.cc
+++ b/passes/techmap/abc9_ops.cc
@@ -741,8 +741,10 @@ void reintegrate(RTLIL::Module *module)
if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module));
- for (auto w : mapped_mod->wires())
- module->addWire(remap_name(w->name), GetSize(w));
+ for (auto w : mapped_mod->wires()) {
+ auto nw = module->addWire(remap_name(w->name), GetSize(w));
+ nw->start_offset = w->start_offset;
+ }
dict<IdString,std::vector<IdString>> box_ports;
@@ -989,7 +991,7 @@ void reintegrate(RTLIL::Module *module)
wire->attributes.erase(ID::abc9_scc);
RTLIL::Wire *remap_wire = module->wire(remap_name(port));
- RTLIL::SigSpec signal(wire, 0, GetSize(remap_wire));
+ RTLIL::SigSpec signal(wire, remap_wire->start_offset-wire->start_offset, GetSize(remap_wire));
log_assert(GetSize(signal) >= GetSize(remap_wire));
RTLIL::SigSig conn;
diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc
index e4ee4991f..217151e96 100644
--- a/techlibs/ecp5/Makefile.inc
+++ b/techlibs/ecp5/Makefile.inc
@@ -2,6 +2,15 @@
OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \
techlibs/ecp5/ecp5_gsr.o
+GENFILES += techlibs/ecp5/bram_init_1_2_4.vh
+GENFILES += techlibs/ecp5/bram_init_9_18_36.vh
+GENFILES += techlibs/ecp5/bram_conn_1.vh
+GENFILES += techlibs/ecp5/bram_conn_2.vh
+GENFILES += techlibs/ecp5/bram_conn_4.vh
+GENFILES += techlibs/ecp5/bram_conn_9.vh
+GENFILES += techlibs/ecp5/bram_conn_18.vh
+GENFILES += techlibs/ecp5/bram_conn_36.vh
+
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_ff.vh))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_io.vh))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
diff --git a/techlibs/ecp5/ecp5_ffinit.cc b/techlibs/ecp5/ecp5_ffinit.cc
index e85bee64e..ba72bd0c6 100644
--- a/techlibs/ecp5/ecp5_ffinit.cc
+++ b/techlibs/ecp5/ecp5_ffinit.cc
@@ -106,9 +106,7 @@ struct Ecp5FfinitPass : public Pass {
SigBit bit_d = sigmap(sig_d[0]);
SigBit bit_q = sigmap(sig_q[0]);
- std::string regset = "RESET";
- if (cell->hasParam(ID(REGSET)))
- regset = cell->getParam(ID(REGSET)).decode_string();
+ std::string regset = cell->getParam(ID(REGSET)).decode_string();
State resetState;
if (regset == "SET")
resetState = State::S1;
@@ -135,9 +133,7 @@ struct Ecp5FfinitPass : public Pass {
}
if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) {
- std::string srmode = "LSR_OVER_CE";
- if (cell->hasParam(ID(SRMODE)))
- srmode = cell->getParam(ID(SRMODE)).decode_string();
+ std::string srmode = cell->getParam(ID(SRMODE)).decode_string();
if (srmode == "ASYNC") {
log("Async reset value %c for FF cell %s inconsistent with init value %c.\n",
resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0');
@@ -154,9 +150,7 @@ struct Ecp5FfinitPass : public Pass {
cell->setPort(ID(LSR), State::S0);
if(cell->hasPort(ID(CE))) {
- std::string cemux = "CE";
- if (cell->hasParam(ID(CEMUX)))
- cemux = cell->getParam(ID(CEMUX)).decode_string();
+ std::string cemux = cell->getParam(ID(CEMUX)).decode_string();
SigSpec sig_ce = cell->getPort(ID(CE));
if (GetSize(sig_ce) >= 1) {
SigBit bit_ce = sigmap(sig_ce[0]);
diff --git a/techlibs/ecp5/ecp5_gsr.cc b/techlibs/ecp5/ecp5_gsr.cc
index d1503f71f..3d3f8e1c1 100644
--- a/techlibs/ecp5/ecp5_gsr.cc
+++ b/techlibs/ecp5/ecp5_gsr.cc
@@ -114,9 +114,9 @@ struct Ecp5GsrPass : public Pass {
{
if (cell->type != ID(TRELLIS_FF))
continue;
- if (!cell->hasParam(ID(GSR)) || cell->getParam(ID(GSR)).decode_string() != "ENABLED")
+ if (cell->getParam(ID(GSR)).decode_string() != "ENABLED")
continue;
- if (!cell->hasParam(ID(SRMODE)) || cell->getParam(ID(SRMODE)).decode_string() != "ASYNC")
+ if (cell->getParam(ID(SRMODE)).decode_string() != "ASYNC")
continue;
SigSpec sig_lsr = cell->getPort(ID(LSR));
if (GetSize(sig_lsr) < 1)
diff --git a/techlibs/gowin/Makefile.inc b/techlibs/gowin/Makefile.inc
index fe5d9d6e6..0756e3bcf 100644
--- a/techlibs/gowin/Makefile.inc
+++ b/techlibs/gowin/Makefile.inc
@@ -2,6 +2,7 @@
OBJS += techlibs/gowin/synth_gowin.o
OBJS += techlibs/gowin/determine_init.o
+GENFILES += techlibs/gowin/bram_init_16.vh
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_map.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_sim.v))
@@ -11,8 +12,6 @@ $(eval $(call add_share_file,share/gowin,techlibs/gowin/brams.txt))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams_map.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams.txt))
-
-
$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_init3.vh))
EXTRA_OBJS += techlibs/gowin/brams_init.mk
diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc
index 66204c8fc..bbf233aeb 100644
--- a/techlibs/intel_alm/Makefile.inc
+++ b/techlibs/intel_alm/Makefile.inc
@@ -15,9 +15,6 @@ $(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/c
$(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/quartus_rename.v b/techlibs/intel_alm/common/quartus_rename.v
index d9961c174..ac0fe12aa 100644
--- a/techlibs/intel_alm/common/quartus_rename.v
+++ b/techlibs/intel_alm/common/quartus_rename.v
@@ -1,3 +1,10 @@
+`ifdef cyclonev
+`define LCELL cyclonev_lcell_comb
+`endif
+`ifdef cyclone10gx
+`define LCELL cyclone10gx_lcell_comb
+`endif
+
module __MISTRAL_VCC(output Q);
MISTRAL_ALUT2 #(.LUT(4'b1111)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q));
@@ -17,3 +24,59 @@ 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
+
+
+module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q);
+parameter [63:0] LUT = 64'h0000_0000_0000_0000;
+
+`LCELL #(.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 [31:0] LUT = 32'h0000_0000;
+
+`LCELL #(.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 [15:0] LUT = 16'h0000;
+
+`LCELL #(.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 [7:0] LUT = 8'h00;
+
+`LCELL #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q));
+
+endmodule
+
+
+module MISTRAL_ALUT2(input A, B, output Q);
+parameter [3:0] LUT = 4'h0;
+
+`LCELL #(.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;
+
+`LCELL #(.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/cyclone10gx/quartus_rename.v b/techlibs/intel_alm/cyclone10gx/quartus_rename.v
deleted file mode 100644
index 3fbc508ed..000000000
--- a/techlibs/intel_alm/cyclone10gx/quartus_rename.v
+++ /dev/null
@@ -1,54 +0,0 @@
-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
deleted file mode 100644
index 6eff375e1..000000000
--- a/techlibs/intel_alm/cyclonev/quartus_rename.v
+++ /dev/null
@@ -1,54 +0,0 @@
-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
index 47aa11500..200b0cdd1 100644
--- a/techlibs/intel_alm/synth_intel_alm.cc
+++ b/techlibs/intel_alm/synth_intel_alm.cc
@@ -200,6 +200,8 @@ struct SynthIntelALMPass : public ScriptPass {
if (check_label("map_ffs")) {
run("dff2dffe -direct-match $_DFF_*");
+ // As mentioned in common/dff_sim.v, Intel flops power up to zero,
+ // so use `zinit` to add inverters where needed.
run("zinit");
run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v");
run("opt -full -undriven -mux_undef");
@@ -223,10 +225,17 @@ struct SynthIntelALMPass : public ScriptPass {
if (check_label("quartus")) {
if (quartus || help_mode) {
+ // Quartus ICEs if you have a wire which has `[]` in its name,
+ // which Yosys produces when building memories out of flops.
+ run("rename -hide w:*[* w:*]*");
+ // VQM mode does not support 'x, so replace those with zero.
run("setundef -zero");
+ // VQM mode does not support multi-bit constant assignments
+ // (e.g. 2'b00 is an error), so as a workaround use references
+ // to constant driver cells, which Quartus accepts.
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()));
+ // Rename from Yosys-internal MISTRAL_* cells to Quartus cells.
+ run(stringf("techmap -D %s -map +/intel_alm/common/quartus_rename.v", family_opt.c_str()));
}
}
diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc
index c608db883..c9d63c9f7 100644
--- a/techlibs/xilinx/xilinx_dffopt.cc
+++ b/techlibs/xilinx/xilinx_dffopt.cc
@@ -292,18 +292,21 @@ unmap:
LutData final_lut;
if (worthy_post_r) {
final_lut = lut_d_post_r;
- log(" Merging R LUT for %s/%s (%d -> %d)\n", log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second));
} else if (worthy_post_s) {
final_lut = lut_d_post_s;
- log(" Merging S LUT for %s/%s (%d -> %d)\n", log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second));
} else if (worthy_post_ce) {
final_lut = lut_d_post_ce;
- log(" Merging CE LUT for %s/%s (%d -> %d)\n", log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second));
} else {
// Nothing to do here.
continue;
}
+ std::string ports;
+ if (worthy_post_r) ports += " + R";
+ if (worthy_post_s) ports += " + S";
+ if (worthy_post_ce) ports += " + CE";
+ log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports.c_str(), log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second));
+
// Okay, we're doing it. Unmap ports.
if (worthy_post_r) {
cell->unsetParam(ID(IS_R_INVERTED));
diff --git a/tests/aiger/neg.ys b/tests/aiger/neg.ys
new file mode 100644
index 000000000..4c1edd8a4
--- /dev/null
+++ b/tests/aiger/neg.ys
@@ -0,0 +1,36 @@
+read_verilog <<EOT
+module top(input [31:-32] a, input [-65:-128] b, output [128:65] c);
+assign c = a & b;
+endmodule
+EOT
+select -assert-count 1 i:a
+select -assert-count 1 i:b
+select -assert-count 1 o:c
+select -assert-count 3 x:* s:64 %i
+design -save read
+
+!rm -rf neg.out
+!mkdir neg.out
+simplemap
+write_aiger -map neg.out/neg.map neg.out/neg.aig
+
+design -reset
+read_aiger -wideports -map neg.out/neg.map neg.out/neg.aig
+select -assert-count 1 i:a
+select -assert-count 1 i:b
+select -assert-count 1 o:c
+select -assert-count 3 x:* s:64 %i
+
+
+design -load read
+!rm -rf neg.out
+!mkdir neg.out
+simplemap
+write_xaiger -map neg.out/neg.map neg.out/neg.aig
+
+design -reset
+read_aiger -wideports -map neg.out/neg.map neg.out/neg.aig
+select -assert-count 1 i:a
+select -assert-count 1 i:b
+select -assert-count 1 o:c
+select -assert-count 3 x:* s:64 %i
diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh
index 8e932b091..de7bc68cf 100755
--- a/tests/aiger/run-test.sh
+++ b/tests/aiger/run-test.sh
@@ -52,3 +52,8 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports -seq 16 miter
" -l ${aig}.log
done
+
+for y in *.ys; do
+ echo "Running $y."
+ ../../yosys $y -ql ${y%.*}.log
+done
diff --git a/tests/arch/ice40/ice40_dsp.ys b/tests/arch/ice40/ice40_dsp.ys
index 250273859..b13e525fd 100644
--- a/tests/arch/ice40/ice40_dsp.ys
+++ b/tests/arch/ice40/ice40_dsp.ys
@@ -8,4 +8,5 @@ assign o4 = a * b;
SB_MAC16 m3 (.A(a), .B(b), .O(o5));
endmodule
EOT
+read_verilog -lib +/ice40/cells_sim.v
ice40_dsp
diff --git a/tests/arch/intel_alm/quartus_ice.ys b/tests/arch/intel_alm/quartus_ice.ys
new file mode 100644
index 000000000..4b9b54d10
--- /dev/null
+++ b/tests/arch/intel_alm/quartus_ice.ys
@@ -0,0 +1,12 @@
+read_verilog <<EOT
+// Verilog has syntax for raw identifiers, where you start it with \ and end it with a space.
+// This test crashes Quartus due to it parsing \a[10] as a wire slice and not a raw identifier.
+module top();
+ (* keep *) wire [31:0] \a[10] ;
+ (* keep *) wire b;
+ assign b = \a[10] [31];
+endmodule
+EOT
+
+synth_intel_alm -family cyclonev -quartus
+select -assert-none w:*[* w:*]*
diff --git a/tests/arch/xilinx/xilinx_dffopt.ys b/tests/arch/xilinx/xilinx_dffopt.ys
index dc036acfd..2c729832e 100644
--- a/tests/arch/xilinx/xilinx_dffopt.ys
+++ b/tests/arch/xilinx/xilinx_dffopt.ys
@@ -18,17 +18,17 @@ FDRE ff (.D(tmp[0]), .CE(tmp[1]), .R(tmp[2]), .Q(o[0]));
endmodule
EOT
-
+read_verilog -lib +/xilinx/cells_sim.v
design -save t0
equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt
design -load postopt
clean
+cd t0
select -assert-count 1 t:FDRE
select -assert-count 1 t:LUT6
-select -assert-count 3 t:LUT2
-select -assert-none t:FDRE t:LUT6 t:LUT2 %% t:* %D
+select -assert-none t:FDRE t:LUT6 %% t:* %D
design -load t0
@@ -36,9 +36,10 @@ equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim
design -load postopt
clean
+cd t0
select -assert-count 1 t:FDRE
select -assert-count 1 t:LUT4
-select -assert-count 3 t:LUT2
+select -assert-count 1 t:LUT2
select -assert-none t:FDRE t:LUT4 t:LUT2 %% t:* %D
design -reset
@@ -65,16 +66,17 @@ endmodule
EOT
+read_verilog -lib +/xilinx/cells_sim.v
design -save t0
equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt
design -load postopt
clean
+cd t0
select -assert-count 1 t:FDSE
select -assert-count 1 t:LUT6
-select -assert-count 3 t:LUT2
-select -assert-none t:FDSE t:LUT6 t:LUT2 %% t:* %D
+select -assert-none t:FDSE t:LUT6 %% t:* %D
design -load t0
@@ -82,9 +84,10 @@ equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim
design -load postopt
clean
+cd t0
select -assert-count 1 t:FDSE
select -assert-count 1 t:LUT4
-select -assert-count 3 t:LUT2
+select -assert-count 1 t:LUT2
select -assert-none t:FDSE t:LUT4 t:LUT2 %% t:* %D
design -reset
@@ -111,15 +114,17 @@ endmodule
EOT
+read_verilog -lib +/xilinx/cells_sim.v
design -save t0
equiv_opt -async2sync -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt
design -load postopt
clean
+cd t0
select -assert-count 1 t:FDCE
select -assert-count 1 t:LUT4
-select -assert-count 3 t:LUT2
+select -assert-count 1 t:LUT2
select -assert-none t:FDCE t:LUT4 t:LUT2 %% t:* %D
design -reset
@@ -145,16 +150,17 @@ endmodule
EOT
+read_verilog -lib +/xilinx/cells_sim.v
design -save t0
equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt
design -load postopt
clean
+cd t0
select -assert-count 1 t:FDSE
select -assert-count 1 t:LUT5
-select -assert-count 2 t:LUT2
-select -assert-none t:FDSE t:LUT5 t:LUT2 %% t:* %D
+select -assert-none t:FDSE t:LUT5 %% t:* %D
design -load t0
@@ -162,6 +168,7 @@ equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim
design -load postopt
clean
+cd t0
select -assert-count 1 t:FDSE
select -assert-count 2 t:LUT2
select -assert-none t:FDSE t:LUT2 %% t:* %D
@@ -191,16 +198,17 @@ endmodule
EOT
+read_verilog -lib +/xilinx/cells_sim.v
design -save t0
equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt
design -load postopt
clean
+cd t0
select -assert-count 1 t:FDRSE
select -assert-count 1 t:LUT6
-select -assert-count 4 t:LUT2
-select -assert-none t:FDRSE t:LUT6 t:LUT2 %% t:* %D
+select -assert-none t:FDRSE t:LUT6 %% t:* %D
design -load t0
@@ -208,9 +216,10 @@ equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim
design -load postopt
clean
+cd t0
select -assert-count 1 t:FDRSE
select -assert-count 1 t:LUT4
-select -assert-count 4 t:LUT2
+select -assert-count 1 t:LUT2
select -assert-none t:FDRSE t:LUT4 t:LUT2 %% t:* %D
design -reset
diff --git a/tests/arch/xilinx/xilinx_dsp.ys b/tests/arch/xilinx/xilinx_dsp.ys
index 3b9f52930..59d8296ab 100644
--- a/tests/arch/xilinx/xilinx_dsp.ys
+++ b/tests/arch/xilinx/xilinx_dsp.ys
@@ -8,4 +8,5 @@ assign o4 = a * b;
DSP48E1 m3 (.A(a), .B(b), .P(o5));
endmodule
EOT
+read_verilog -lib +/xilinx/cells_sim.v
xilinx_dsp
diff --git a/tests/opt/bug2010.ys b/tests/opt/bug2010.ys
new file mode 100644
index 000000000..cef820867
--- /dev/null
+++ b/tests/opt/bug2010.ys
@@ -0,0 +1,10 @@
+read_verilog <<EOT
+module test (
+ input signed [1:0] n,
+ output [3:0] dout
+);
+ assign dout = n + 4'sd 4;
+endmodule
+EOT
+
+equiv_opt -assert opt -fine
diff --git a/tests/select/blackboxes.ys b/tests/select/blackboxes.ys
new file mode 100644
index 000000000..9bfe92c6b
--- /dev/null
+++ b/tests/select/blackboxes.ys
@@ -0,0 +1,28 @@
+read_verilog -specify <<EOT
+module top(input a, b, output o);
+assign o = a & b;
+endmodule
+
+(* blackbox *)
+module bb(input a, b, output o);
+assign o = a | b;
+specify
+ (a => o) = 1;
+endspecify
+endmodule
+
+(* whitebox *)
+module wb(input a, b, output o);
+assign o = a ^ b;
+endmodule
+EOT
+clean
+
+select -assert-count 1 c:*
+select -assert-none t:* t:$and %d
+select -assert-count 3 w:*
+select -assert-count 4 *
+
+select -assert-count 3 =c:*
+select -assert-count 10 =w:*
+select -assert-count 13 =*
diff --git a/tests/various/bug2014.ys b/tests/various/bug2014.ys
new file mode 100644
index 000000000..10131fc43
--- /dev/null
+++ b/tests/various/bug2014.ys
@@ -0,0 +1,12 @@
+read_verilog <<EOT
+module test (
+ input signed [1:0] n,
+ output [3:0] dout
+);
+ assign dout = n + 4'sd 4;
+endmodule
+EOT
+
+alumacc
+select -assert-count 1 t:$alu
+equiv_opt -assert opt -fine