This commit is contained in:
Andrew Zonenberg 2017-02-11 11:25:16 -08:00
commit 203b521a78
10 changed files with 273 additions and 58 deletions

View File

@ -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)

View File

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

View File

@ -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;

View File

@ -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; }

View File

@ -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 {

View File

@ -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
// ---------------------------------------------------

View File

@ -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) {

View File

@ -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;
}
}
}

View File

@ -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)

View File

@ -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) {