aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Zonenberg <azonenberg@drawersteak.com>2017-02-11 11:25:16 -0800
committerAndrew Zonenberg <azonenberg@drawersteak.com>2017-02-11 11:25:16 -0800
commit203b521a781ccc4c8dba05d2cc73e4625bcf2a8e (patch)
tree12efc580521210c43957c010a7fe5367606cb2f2
parent0d7e71f7abd49d1c95f0657993b55bb5f66317a1 (diff)
parentcdb6ceb8c63f2c38bdba3f66be7c444def43897e (diff)
downloadyosys-203b521a781ccc4c8dba05d2cc73e4625bcf2a8e.tar.gz
yosys-203b521a781ccc4c8dba05d2cc73e4625bcf2a8e.tar.bz2
yosys-203b521a781ccc4c8dba05d2cc73e4625bcf2a8e.zip
Merge https://github.com/cliffordwolf/yosys
-rw-r--r--Makefile51
-rw-r--r--README.md28
-rw-r--r--frontends/verific/verific.cc145
-rw-r--r--frontends/verilog/verilog_lexer.l20
-rw-r--r--frontends/verilog/verilog_parser.y15
-rw-r--r--kernel/log.cc7
-rw-r--r--kernel/log.h1
-rw-r--r--passes/opt/opt_expr.cc52
-rw-r--r--passes/opt/opt_merge.cc8
-rw-r--r--passes/opt/opt_rmdff.cc4
10 files changed, 273 insertions, 58 deletions
diff --git a/Makefile b/Makefile
index 320eec018..2773990a6 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/README.md b/README.md
index 396189d5f..7c4dbf0c5 100644
--- a/README.md
+++ b/README.md
@@ -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) {