mirror of https://github.com/YosysHQ/yosys.git
This commit is contained in:
commit
203b521a78
51
Makefile
51
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)
|
||||
|
|
28
README.md
28
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
// ---------------------------------------------------
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue