aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.editorconfig5
-rw-r--r--Makefile70
-rw-r--r--README.md9
-rw-r--r--backends/aiger/aiger.cc12
-rw-r--r--backends/aiger/xaiger.cc5
-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.cc96
-rw-r--r--frontends/verific/verific.h2
-rw-r--r--kernel/driver.cc17
-rw-r--r--kernel/log.cc7
-rw-r--r--kernel/log.h40
-rw-r--r--kernel/register.cc4
-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--passes/cmds/Makefile.inc4
-rw-r--r--passes/cmds/cover.cc4
-rw-r--r--passes/cmds/show.cc12
-rw-r--r--passes/opt/opt_expr.cc52
-rw-r--r--passes/sat/Makefile.inc3
-rw-r--r--passes/techmap/Makefile.inc2
-rw-r--r--passes/techmap/abc.cc11
-rw-r--r--passes/techmap/abc9_exe.cc4
-rw-r--r--passes/techmap/abc9_ops.cc8
-rw-r--r--techlibs/ecp5/Makefile.inc9
-rw-r--r--techlibs/gowin/Makefile.inc3
-rw-r--r--tests/aiger/neg.ys36
-rwxr-xr-xtests/aiger/run-test.sh5
-rw-r--r--tests/opt/bug2010.ys10
-rw-r--r--tests/various/bug2014.ys12
35 files changed, 477 insertions, 132 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/Makefile b/Makefile
index da8701355..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
@@ -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/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 89606a5bd..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;
@@ -1153,30 +1215,6 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
for (auto net : anyseq_nets)
module->connect(net_map_at(net), module->Anyseq(new_verific_id(net)));
- char *id_name;
- TypeRange *type_range;
- FOREACH_MAP_ITEM(nl->GetTypeRangeTable(), mi, &id_name, &type_range)
- {
- if (!type_range)
- continue;
- if (!type_range->IsTypeEnum())
- continue;
- auto wire = module->wire(RTLIL::escape_id(id_name));
- if (!wire) {
- if (net->IsUserDeclared())
- log_warning("Unable to find imported net '%s'.\n", net->Name());
- continue;
- }
- wire->set_string_attribute(ID::wiretype, type_range->GetTypeName());
-
- MapIter mj;
- char *k, *v;
- FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mj, &k, &v) {
- IdString key = stringf("\\enum_value_%s", v);
- wire->set_string_attribute(key, k);
- }
- }
-
pool<Instance*, hash_ptr_ops> sva_asserts;
pool<Instance*, hash_ptr_ops> sva_assumes;
pool<Instance*, hash_ptr_ops> sva_covers;
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/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/log.cc b/kernel/log.cc
index d84a4381e..a21ba480a 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -354,6 +354,9 @@ static void logv_error_with_prefix(const char *prefix,
if (check_expected_logs)
log_check_expected();
+
+ YS_DEBUGTRAP_IF_DEBUGGING;
+
#ifdef EMSCRIPTEN
log_files = backup_log_files;
throw 0;
@@ -673,7 +676,7 @@ void log_check_expected()
}
if (item.second.current_count != item.second.expected_count) {
log_warn_regexes.clear();
- log_error("Expected warning pattern '%s' found %d time(s), instead of %d time(s) !\n",
+ log_error("Expected warning pattern '%s' found %d time(s), instead of %d time(s) !\n",
item.second.pattern.c_str(), item.second.current_count, item.second.expected_count);
}
}
@@ -700,7 +703,7 @@ void log_check_expected()
_exit(0);
#else
_Exit(0);
- #endif
+ #endif
} else {
display_error_log_msg = false;
log_warn_regexes.clear();
diff --git a/kernel/log.h b/kernel/log.h
index 5478482ac..dee5d44d7 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -50,9 +50,12 @@
std::regex_constants::egrep)
#endif
-#ifndef _WIN32
+#if defined(_WIN32)
+# include <intrin.h>
+#else
# include <sys/time.h>
# include <sys/resource.h>
+# include <signal.h>
#endif
#if defined(_MSC_VER)
@@ -69,6 +72,41 @@ YOSYS_NAMESPACE_BEGIN
#define S__LINE__sub1(x) S__LINE__sub2(x)
#define S__LINE__ S__LINE__sub1(__LINE__)
+// YS_DEBUGTRAP is a macro that is functionally equivalent to a breakpoint
+// if the platform provides such functionality, and does nothing otherwise.
+// If no debugger is attached, it starts a just-in-time debugger if available,
+// and crashes the process otherwise.
+#if defined(_WIN32)
+# define YS_DEBUGTRAP __debugbreak()
+#else
+# ifndef __has_builtin
+// __has_builtin is a GCC/Clang extension; on a different compiler (or old enough GCC/Clang)
+// that does not have it, using __has_builtin(...) is a syntax error.
+# define __has_builtin(x) 0
+# endif
+# if __has_builtin(__builtin_debugtrap)
+# define YS_DEBUGTRAP __builtin_debugtrap()
+# elif defined(__unix__)
+# define YS_DEBUGTRAP raise(SIGTRAP)
+# else
+# define YS_DEBUGTRAP do {} while(0)
+# endif
+#endif
+
+// YS_DEBUGTRAP_IF_DEBUGGING is a macro that is functionally equivalent to a breakpoint
+// if a debugger is attached, and does nothing otherwise.
+#if defined(_WIN32)
+# define YS_DEBUGTRAP_IF_DEBUGGING do { if (IsDebuggerPresent()) DebugBreak(); } while(0)
+#elif defined(__unix__)
+// There is no reliable (or portable) *nix equivalent of IsDebuggerPresent(). However,
+// debuggers will stop when SIGTRAP is raised, even if the action is set to ignore.
+# define YS_DEBUGTRAP_IF_DEBUGGING do { \
+ sighandler_t old = signal(SIGTRAP, SIG_IGN); raise(SIGTRAP); signal(SIGTRAP, old); \
+ } while(0)
+#else
+# define YS_DEBUGTRAP_IF_DEBUGGING do {} while(0)
+#endif
+
struct log_cmd_error_exception { };
extern std::vector<FILE*> log_files;
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/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/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/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/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/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/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 bad91a224..0bf547921 100644
--- a/passes/techmap/abc9_exe.cc
+++ b/passes/techmap/abc9_exe.cc
@@ -420,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/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/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/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/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