diff options
author | Andrew Zonenberg <azonenberg@drawersteak.com> | 2017-02-11 11:25:16 -0800 |
---|---|---|
committer | Andrew Zonenberg <azonenberg@drawersteak.com> | 2017-02-11 11:25:16 -0800 |
commit | 203b521a781ccc4c8dba05d2cc73e4625bcf2a8e (patch) | |
tree | 12efc580521210c43957c010a7fe5367606cb2f2 | |
parent | 0d7e71f7abd49d1c95f0657993b55bb5f66317a1 (diff) | |
parent | cdb6ceb8c63f2c38bdba3f66be7c444def43897e (diff) | |
download | yosys-203b521a781ccc4c8dba05d2cc73e4625bcf2a8e.tar.gz yosys-203b521a781ccc4c8dba05d2cc73e4625bcf2a8e.tar.bz2 yosys-203b521a781ccc4c8dba05d2cc73e4625bcf2a8e.zip |
Merge https://github.com/cliffordwolf/yosys
-rw-r--r-- | Makefile | 51 | ||||
-rw-r--r-- | README.md | 28 | ||||
-rw-r--r-- | frontends/verific/verific.cc | 145 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 20 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 15 | ||||
-rw-r--r-- | kernel/log.cc | 7 | ||||
-rw-r--r-- | kernel/log.h | 1 | ||||
-rw-r--r-- | passes/opt/opt_expr.cc | 52 | ||||
-rw-r--r-- | passes/opt/opt_merge.cc | 8 | ||||
-rw-r--r-- | passes/opt/opt_rmdff.cc | 4 |
10 files changed, 273 insertions, 58 deletions
@@ -53,27 +53,35 @@ all: top-all YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST))) VPATH := $(YOSYS_SRC) -CXXFLAGS += -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include -LDFLAGS += -L$(LIBDIR) -LDLIBS = -lstdc++ -lm +CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include +LDFLAGS := $(LDFLAGS) -L$(LIBDIR) +LDLIBS := $(LDLIBS) -lstdc++ -lm -PKG_CONFIG = pkg-config -SED = sed -BISON = bison +PKG_CONFIG ?= pkg-config +SED ?= sed +BISON ?= bison ifeq (Darwin,$(findstring Darwin,$(shell uname))) - # add macports/homebrew include and library path to search directories, don't use '-rdynamic' and '-lrt': - CXXFLAGS += -I/opt/local/include -I/usr/local/opt/readline/include - LDFLAGS += -L/opt/local/lib -L/usr/local/opt/readline/lib - # add homebrew's libffi include and library path - CXXFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --cflags libffi) - LDFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --libs libffi) - # use bison installed by homebrew if available - BISON = $(shell (brew list bison | grep -m1 "bin/bison") || echo bison) - SED = sed +# homebrew search paths +ifneq ($(shell which brew),) +BREW_PREFIX := $(shell brew --prefix)/opt +CXXFLAGS += -I$(BREW_PREFIX)/readline/include +LDFLAGS += -L$(BREW_PREFIX)/readline/lib +PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH) +PKG_CONFIG_PATH := $(BREW_PREFIX)/tcl-tk/lib/pkgconfig:$(PKG_CONFIG_PATH) +export PATH := $(BREW_PREFIX)/bison/bin:$(BREW_PREFIX)/gettext/bin:$(BREW_PREFIX)/flex/bin:$(PATH) + +# macports search paths +else ifneq ($(shell which port),) +PORT_PREFIX := $(patsubst %/bin/port,%,$(shell which port)) +CXXFLAGS += -I$(PORT_PREFIX)/include +LDFLAGS += -L$(PORT_PREFIX)/lib +PKG_CONFIG_PATH := $(PORT_PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH) +export PATH := $(PORT_PREFIX)/bin:$(PATH) +endif else - LDFLAGS += -rdynamic - LDLIBS += -lrt +LDFLAGS += -rdynamic +LDLIBS += -lrt endif YOSYS_VER := 0.7+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 61f6811.. | wc -l; }) @@ -210,15 +218,16 @@ endif endif ifeq ($(ENABLE_PLUGINS),1) -CXXFLAGS += -DYOSYS_ENABLE_PLUGINS $(shell $(PKG_CONFIG) --silence-errors --cflags libffi) -LDLIBS += $(shell $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi) -ldl +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) -ldl endif ifeq ($(ENABLE_TCL),1) TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')") TCL_INCLUDE ?= /usr/include/$(TCL_VERSION) -CXXFLAGS += -I$(TCL_INCLUDE) -DYOSYS_ENABLE_TCL -LDLIBS += -l$(TCL_VERSION) + +CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL +LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo -l$(TCL_VERSION)) endif ifeq ($(ENABLE_GPROF),1) @@ -40,14 +40,14 @@ Web Site More information and documentation can be found on the Yosys web site: http://www.clifford.at/yosys/ - -Getting Started -=============== +Setup +====== You need a C++ compiler with C++11 support (up-to-date CLANG or GCC is recommended) and some standard tools such as GNU Flex, GNU Bison, and GNU Make. TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile). Xdot (graphviz) is used by the ``show`` command in yosys to display schematics. + For example on Ubuntu Linux 16.04 LTS the following commands will install all prerequisites for building yosys: @@ -55,6 +55,13 @@ prerequisites for building yosys: libreadline-dev gawk tcl-dev libffi-dev git mercurial \ graphviz xdot pkg-config python3 +Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies: + + $ brew install bison flex gawk libffi \ + git mercurial graphviz pkg-config python3 + $ sudo port install bison flex readline gawk libffi \ + git mercurial graphviz pkgconfig python36 + There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well as a source distribution for Visual Studio. Visit the Yosys download page for more information: http://www.clifford.at/yosys/download.html @@ -80,6 +87,9 @@ To build Yosys simply type 'make' in this directory. Note that this also downloads, builds and installs ABC (using yosys-abc as executable name). +Getting Started +=============== + Yosys can be used with the interactive command shell, with synthesis scripts or with command line arguments. Let's perform a simple synthesis job using the interactive command shell: @@ -379,10 +389,13 @@ Non-standard or SystemVerilog features for formal verification to 0 otherwise. - The system task ``$anyconst`` evaluates to any constant value. This is - equivalent to declaring a reg as ``const rand``. + equivalent to declaring a reg as ``rand const``, but also works outside + of checkers. (Yosys also supports ``rand const`` outside checkers.) - The system task ``$anyseq`` evaluates to any value, possibly a different - value in each cycle. This is equivalent to declaring a reg as ``rand``. + value in each cycle. This is equivalent to declaring a reg as ``rand``, + but also works outside of checkers. (Yosys also supports ``rand`` + variables outside checkers.) - The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are supported in any clocked block. @@ -407,7 +420,10 @@ from SystemVerilog: - The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic`` and ``bit`` are supported. -- Declaring free variables with ``rand`` and ``const rand`` is supported. +- Declaring free variables with ``rand`` and ``rand const`` is supported. + +- Checkers without a port list that do not need to be instantiated (but instead + behave like a named block) are supported. - SystemVerilog packages are supported. Once a SystemVerilog file is read into a design with ``read_verilog``, all its packages are available to diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index f3b997dc5..bc0bd60fc 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -57,7 +57,7 @@ PRIVATE_NAMESPACE_BEGIN void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefile, const char *msg, va_list args) { - log("VERIFIC-%s [%s] ", + string message = stringf("VERIFIC-%s [%s] ", msg_type == VERIFIC_NONE ? "NONE" : msg_type == VERIFIC_ERROR ? "ERROR" : msg_type == VERIFIC_WARNING ? "WARNING" : @@ -65,10 +65,16 @@ void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefil msg_type == VERIFIC_INFO ? "INFO" : msg_type == VERIFIC_COMMENT ? "COMMENT" : msg_type == VERIFIC_PROGRAM_ERROR ? "PROGRAM_ERROR" : "UNKNOWN", message_id); + if (linefile) - log("%s:%d: ", LineFile::GetFileName(linefile), LineFile::GetLineNo(linefile)); - logv(msg, args); - log("\n"); + message += stringf("%s:%d: ", LineFile::GetFileName(linefile), LineFile::GetLineNo(linefile)); + + message += vstringf(msg, args); + + if (msg_type == VERIFIC_ERROR || msg_type == VERIFIC_WARNING || msg_type == VERIFIC_PROGRAM_ERROR) + log_warning("%s\n", message.c_str()); + else + log("%s\n", message.c_str()); } struct VerificImporter @@ -617,6 +623,10 @@ struct VerificImporter module->fixup_ports(); + dict<Net*, char, hash_ptr_ops> init_nets; + pool<Net*, hash_ptr_ops> anyconst_nets; + pool<Net*, hash_ptr_ops> anyseq_nets; + FOREACH_NET_OF_NETLIST(nl, mi, net) { if (net->IsRamNet()) @@ -643,9 +653,59 @@ struct VerificImporter memory->width = bits_in_word; memory->size = number_of_bits / bits_in_word; + + const char *ascii_initdata = net->GetWideInitialValue(); + if (ascii_initdata) { + while (*ascii_initdata != 0 && *ascii_initdata != '\'') + ascii_initdata++; + if (*ascii_initdata == '\'') + ascii_initdata++; + if (*ascii_initdata != 0) { + log_assert(*ascii_initdata == 'b'); + ascii_initdata++; + } + for (int word_idx = 0; word_idx < memory->size; word_idx++) { + Const initval = Const(State::Sx, memory->width); + bool initval_valid = false; + for (int bit_idx = memory->width-1; bit_idx >= 0; bit_idx--) { + if (*ascii_initdata == 0) + break; + if (*ascii_initdata == '0' || *ascii_initdata == '1') { + initval[bit_idx] = (*ascii_initdata == '0') ? State::S0 : State::S1; + initval_valid = true; + } + ascii_initdata++; + } + if (initval_valid) { + RTLIL::Cell *cell = module->addCell(NEW_ID, "$meminit"); + cell->parameters["\\WORDS"] = 1; + if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound()) + cell->setPort("\\ADDR", word_idx); + else + cell->setPort("\\ADDR", memory->size - word_idx - 1); + cell->setPort("\\DATA", initval); + cell->parameters["\\MEMID"] = RTLIL::Const(memory->name.str()); + cell->parameters["\\ABITS"] = 32; + cell->parameters["\\WIDTH"] = memory->width; + cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1); + } + } + } continue; } + if (net->GetInitialValue()) + init_nets[net] = net->GetInitialValue(); + + const char *rand_const_attr = net->GetAttValue(" rand_const"); + const char *rand_attr = net->GetAttValue(" rand"); + + if (rand_const_attr != nullptr && !strcmp(rand_const_attr, "1")) + anyconst_nets.insert(net); + + else if (rand_attr != nullptr && !strcmp(rand_attr, "1")) + anyseq_nets.insert(net); + if (net_map.count(net)) { // log(" skipping net %s.\n", net->Name()); continue; @@ -683,25 +743,94 @@ struct VerificImporter wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex()); import_attributes(wire->attributes, netbus); - for (int i = netbus->LeftIndex();; i += netbus->IsUp() ? +1 : -1) { - if (netbus->ElementAtIndex(i)) { + RTLIL::Const initval = Const(State::Sx, GetSize(wire)); + bool initval_valid = false; + + for (int i = netbus->LeftIndex();; i += netbus->IsUp() ? +1 : -1) + { + if (netbus->ElementAtIndex(i)) + { + int bitidx = i - wire->start_offset; net = netbus->ElementAtIndex(i); - RTLIL::SigBit bit(wire, i - wire->start_offset); + RTLIL::SigBit bit(wire, bitidx); + + if (init_nets.count(net)) { + if (init_nets.at(net) == '0') + initval.bits.at(bitidx) = State::S0; + if (init_nets.at(net) == '1') + initval.bits.at(bitidx) = State::S1; + initval_valid = true; + init_nets.erase(net); + } + if (net_map.count(net) == 0) net_map[net] = bit; else module->connect(bit, net_map.at(net)); } + if (i == netbus->RightIndex()) break; } + + if (initval_valid) + wire->attributes["\\init"] = initval; } else { // log(" skipping netbus %s.\n", netbus->Name()); } + + SigSpec anyconst_sig; + SigSpec anyseq_sig; + + for (int i = netbus->RightIndex();; i += netbus->IsUp() ? -1 : +1) { + net = netbus->ElementAtIndex(i); + if (net != nullptr && anyconst_nets.count(net)) { + anyconst_sig.append(net_map.at(net)); + anyconst_nets.erase(net); + } + if (net != nullptr && anyseq_nets.count(net)) { + anyseq_sig.append(net_map.at(net)); + anyseq_nets.erase(net); + } + if (i == netbus->LeftIndex()) + break; + } + + if (GetSize(anyconst_sig)) + module->connect(anyconst_sig, module->Anyconst(NEW_ID, GetSize(anyconst_sig))); + + if (GetSize(anyseq_sig)) + module->connect(anyseq_sig, module->Anyseq(NEW_ID, GetSize(anyseq_sig))); } + for (auto it : init_nets) + { + Const initval; + SigBit bit = net_map.at(it.first); + log_assert(bit.wire); + + if (bit.wire->attributes.count("\\init")) + initval = bit.wire->attributes.at("\\init"); + + while (GetSize(initval) < GetSize(bit.wire)) + initval.bits.push_back(State::Sx); + + if (it.second == '0') + initval.bits.at(bit.offset) = State::S0; + if (it.second == '1') + initval.bits.at(bit.offset) = State::S1; + + bit.wire->attributes["\\init"] = initval; + } + + for (auto net : anyconst_nets) + module->connect(net_map.at(net), module->Anyconst(NEW_ID)); + + for (auto net : anyseq_nets) + module->connect(net_map.at(net), module->Anyseq(NEW_ID)); + FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst) { if (inst->Type() == PRIM_SVA_POSEDGE) { @@ -733,7 +862,7 @@ struct VerificImporter SigBit outsig = net_map.at(out); log_assert(outsig.wire && GetSize(outsig.wire) == 1); - outsig.wire->attributes["\\init"] == Const(0, 1); + outsig.wire->attributes["\\init"] = Const(1, 1); module->addDff(NEW_ID, net_map.at(clk), net_map.at(in2), net_map.at(out)); continue; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 97af0ae2d..ff2fa5753 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -175,15 +175,17 @@ YOSYS_NAMESPACE_END "always_ff" { SV_KEYWORD(TOK_ALWAYS); } "always_latch" { SV_KEYWORD(TOK_ALWAYS); } -"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } -"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } -"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } -"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } -"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } -"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } -"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } -"logic" { SV_KEYWORD(TOK_REG); } -"bit" { SV_KEYWORD(TOK_REG); } +"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } +"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } +"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } +"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } +"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } +"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } +"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } +"checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); } +"endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); } +"logic" { SV_KEYWORD(TOK_REG); } +"bit" { SV_KEYWORD(TOK_REG); } "input" { return TOK_INPUT; } "output" { return TOK_OUTPUT; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 3eb03dfd8..1879ff441 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -116,7 +116,7 @@ static void free_attr(std::map<std::string, AstNode*> *al) %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME %token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF -%token TOK_RAND TOK_CONST +%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER %type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list @@ -465,7 +465,18 @@ module_body: module_body_stmt: task_func_decl | param_decl | localparam_decl | defparam_decl | wire_decl | assign_stmt | cell_stmt | - always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property; + always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl; + +checker_decl: + TOK_CHECKER TOK_ID ';' { + AstNode *node = new AstNode(AST_GENBLOCK); + node->str = *$2; + ast_stack.back()->children.push_back(node); + ast_stack.push_back(node); + } module_body TOK_ENDCHECKER { + delete $2; + ast_stack.pop_back(); + }; task_func_decl: attr TOK_DPI_FUNCTION TOK_ID TOK_ID { diff --git a/kernel/log.cc b/kernel/log.cc index cd16bb344..956d93fd1 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -488,6 +488,13 @@ void log_cell(RTLIL::Cell *cell, std::string indent) log("%s", buf.str().c_str()); } +void log_wire(RTLIL::Wire *wire, std::string indent) +{ + std::stringstream buf; + ILANG_BACKEND::dump_wire(buf, indent, wire); + log("%s", buf.str().c_str()); +} + // --------------------------------------------------- // This is the magic behind the code coverage counters // --------------------------------------------------- diff --git a/kernel/log.h b/kernel/log.h index 5b1729eb1..34b8ac3a5 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -90,6 +90,7 @@ template<typename T> static inline const char *log_id(T *obj) { void log_module(RTLIL::Module *module, std::string indent = ""); void log_cell(RTLIL::Cell *cell, std::string indent = ""); +void log_wire(RTLIL::Wire *wire, std::string indent = ""); #ifndef NDEBUG static inline void log_assert_worker(bool cond, const char *expr, const char *file, int line) { diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index b3f2e87ed..236908060 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -383,7 +383,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (detect_const_and || detect_const_or) { pool<SigBit> input_bits = assign_map(cell->getPort("\\A")).to_sigbit_pool(); - bool found_zero = false, found_one = false, found_inv = false; + bool found_zero = false, found_one = false, found_undef = false, found_inv = false, many_conconst = false; + SigBit non_const_input = State::Sm; if (cell->hasPort("\\B")) { vector<SigBit> more_bits = assign_map(cell->getPort("\\B")).to_sigbit_vector(); @@ -391,12 +392,20 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } for (auto bit : input_bits) { - if (bit == State::S0) - found_zero = true; - if (bit == State::S1) - found_one = true; - if (invert_map.count(bit) && input_bits.count(invert_map.at(bit))) - found_inv = true; + if (bit.wire) { + if (invert_map.count(bit) && input_bits.count(invert_map.at(bit))) + found_inv = true; + if (non_const_input != State::Sm) + many_conconst = true; + non_const_input = many_conconst ? State::Sm : bit; + } else { + if (bit == State::S0) + found_zero = true; + else if (bit == State::S1) + found_one = true; + else + found_undef = true; + } } if (detect_const_and && (found_zero || found_inv)) { @@ -410,6 +419,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons replace_cell(assign_map, module, cell, "const_or", "\\Y", RTLIL::State::S1); goto next_cell; } + + if (non_const_input != State::Sm && !found_undef) { + cover("opt.opt_expr.and_or_buffer"); + replace_cell(assign_map, module, cell, "and_or_buffer", "\\Y", non_const_input); + goto next_cell; + } } if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool", "$reduce_xor", "$reduce_xnor", "$neg") && @@ -1208,6 +1223,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons //width of the variable port int width; + int const_width; bool var_signed; @@ -1216,6 +1232,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons sigVar = cell->getPort("\\A"); sigConst = cell->getPort("\\B"); width = cell->parameters["\\A_WIDTH"].as_int(); + const_width = cell->parameters["\\B_WIDTH"].as_int(); var_signed = cell->parameters["\\A_SIGNED"].as_bool(); } else if (cell->type == "$gt" || cell->type == "$le") { @@ -1223,8 +1240,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons sigVar = cell->getPort("\\B"); sigConst = cell->getPort("\\A"); width = cell->parameters["\\B_WIDTH"].as_int(); + const_width = cell->parameters["\\A_WIDTH"].as_int(); var_signed = cell->parameters["\\B_SIGNED"].as_bool(); - } + } else + log_abort(); // replace a(signed) < 0 with the high bit of a if (sigConst.is_fully_const() && sigConst.is_fully_zero() && var_signed == true) @@ -1265,7 +1284,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } int const_bit_set = get_onehot_bit_index(sigConst); - if (const_bit_set >= 0) { + if (const_bit_set >= 0 && const_bit_set < width) { int bit_set = const_bit_set; RTLIL::SigSpec a_prime(RTLIL::State::S0, width - bit_set); for (int i = bit_set; i < width; i++) { @@ -1284,6 +1303,21 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons did_something = true; goto next_cell; } + else if(const_bit_set >= width && const_bit_set >= 0){ + RTLIL::SigSpec a_prime(RTLIL::State::S0, 1); + if(is_lt){ + a_prime[0] = RTLIL::State::S1; + log("Replacing %s cell `%s' (implementing unsigned X[%d:0] < %s[%d:0]) with constant 0.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1); + } + else{ + log("Replacing %s cell `%s' (implementing unsigned X[%d:0]>= %s[%d:0]) with constant 1.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1); + } + module->connect(cell->getPort("\\Y"), a_prime); + module->remove(cell); + did_something = true; + goto next_cell; + + } } } diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 97989d271..07e4dd39f 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -280,8 +280,12 @@ struct OptMergeWorker dff_init_map.set(module); for (auto &it : module->wires_) - if (it.second->attributes.count("\\init") != 0) - dff_init_map.add(it.second, it.second->attributes.at("\\init")); + if (it.second->attributes.count("\\init") != 0) { + Const initval = it.second->attributes.at("\\init"); + for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++) + if (initval[i] == State::S0 || initval[i] == State::S1) + dff_init_map.add(SigBit(it.second, i), initval[i]); + } bool did_something = true; while (did_something) diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 00094738c..0eefd6a86 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -244,7 +244,9 @@ struct OptRmdffPass : public Pass { { if (wire->attributes.count("\\init") != 0) { Const initval = wire->attributes.at("\\init"); - dff_init_map.add(wire, initval); + for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) + if (initval[i] == State::S0 || initval[i] == State::S1) + dff_init_map.add(SigBit(wire, i), initval[i]); for (int i = 0; i < GetSize(wire); i++) { SigBit wire_bit(wire, i), mapped_bit = assign_map(wire_bit); if (mapped_bit.wire) { |