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