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)))
|
YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))
|
||||||
VPATH := $(YOSYS_SRC)
|
VPATH := $(YOSYS_SRC)
|
||||||
|
|
||||||
CXXFLAGS += -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include
|
CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include
|
||||||
LDFLAGS += -L$(LIBDIR)
|
LDFLAGS := $(LDFLAGS) -L$(LIBDIR)
|
||||||
LDLIBS = -lstdc++ -lm
|
LDLIBS := $(LDLIBS) -lstdc++ -lm
|
||||||
|
|
||||||
PKG_CONFIG = pkg-config
|
PKG_CONFIG ?= pkg-config
|
||||||
SED = sed
|
SED ?= sed
|
||||||
BISON = bison
|
BISON ?= bison
|
||||||
|
|
||||||
ifeq (Darwin,$(findstring Darwin,$(shell uname)))
|
ifeq (Darwin,$(findstring Darwin,$(shell uname)))
|
||||||
# add macports/homebrew include and library path to search directories, don't use '-rdynamic' and '-lrt':
|
# homebrew search paths
|
||||||
CXXFLAGS += -I/opt/local/include -I/usr/local/opt/readline/include
|
ifneq ($(shell which brew),)
|
||||||
LDFLAGS += -L/opt/local/lib -L/usr/local/opt/readline/lib
|
BREW_PREFIX := $(shell brew --prefix)/opt
|
||||||
# add homebrew's libffi include and library path
|
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
|
||||||
CXXFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --cflags libffi)
|
LDFLAGS += -L$(BREW_PREFIX)/readline/lib
|
||||||
LDFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --libs libffi)
|
PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
|
||||||
# use bison installed by homebrew if available
|
PKG_CONFIG_PATH := $(BREW_PREFIX)/tcl-tk/lib/pkgconfig:$(PKG_CONFIG_PATH)
|
||||||
BISON = $(shell (brew list bison | grep -m1 "bin/bison") || echo bison)
|
export PATH := $(BREW_PREFIX)/bison/bin:$(BREW_PREFIX)/gettext/bin:$(BREW_PREFIX)/flex/bin:$(PATH)
|
||||||
SED = sed
|
|
||||||
|
# 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
|
else
|
||||||
LDFLAGS += -rdynamic
|
LDFLAGS += -rdynamic
|
||||||
LDLIBS += -lrt
|
LDLIBS += -lrt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
YOSYS_VER := 0.7+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 61f6811.. | wc -l; })
|
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
|
endif
|
||||||
|
|
||||||
ifeq ($(ENABLE_PLUGINS),1)
|
ifeq ($(ENABLE_PLUGINS),1)
|
||||||
CXXFLAGS += -DYOSYS_ENABLE_PLUGINS $(shell $(PKG_CONFIG) --silence-errors --cflags libffi)
|
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags libffi) -DYOSYS_ENABLE_PLUGINS
|
||||||
LDLIBS += $(shell $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi) -ldl
|
LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi) -ldl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(ENABLE_TCL),1)
|
ifeq ($(ENABLE_TCL),1)
|
||||||
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
|
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
|
||||||
TCL_INCLUDE ?= /usr/include/$(TCL_VERSION)
|
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
|
endif
|
||||||
|
|
||||||
ifeq ($(ENABLE_GPROF),1)
|
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:
|
More information and documentation can be found on the Yosys web site:
|
||||||
http://www.clifford.at/yosys/
|
http://www.clifford.at/yosys/
|
||||||
|
|
||||||
|
Setup
|
||||||
Getting Started
|
======
|
||||||
===============
|
|
||||||
|
|
||||||
You need a C++ compiler with C++11 support (up-to-date CLANG or GCC is
|
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.
|
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).
|
TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile).
|
||||||
Xdot (graphviz) is used by the ``show`` command in yosys to display schematics.
|
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
|
For example on Ubuntu Linux 16.04 LTS the following commands will install all
|
||||||
prerequisites for building yosys:
|
prerequisites for building yosys:
|
||||||
|
|
||||||
|
@ -55,6 +55,13 @@ prerequisites for building yosys:
|
||||||
libreadline-dev gawk tcl-dev libffi-dev git mercurial \
|
libreadline-dev gawk tcl-dev libffi-dev git mercurial \
|
||||||
graphviz xdot pkg-config python3
|
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
|
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
|
as a source distribution for Visual Studio. Visit the Yosys download page for
|
||||||
more information: http://www.clifford.at/yosys/download.html
|
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
|
Note that this also downloads, builds and installs ABC (using yosys-abc
|
||||||
as executable name).
|
as executable name).
|
||||||
|
|
||||||
|
Getting Started
|
||||||
|
===============
|
||||||
|
|
||||||
Yosys can be used with the interactive command shell, with
|
Yosys can be used with the interactive command shell, with
|
||||||
synthesis scripts or with command line arguments. Let's perform
|
synthesis scripts or with command line arguments. Let's perform
|
||||||
a simple synthesis job using the interactive command shell:
|
a simple synthesis job using the interactive command shell:
|
||||||
|
@ -379,10 +389,13 @@ Non-standard or SystemVerilog features for formal verification
|
||||||
to 0 otherwise.
|
to 0 otherwise.
|
||||||
|
|
||||||
- The system task ``$anyconst`` evaluates to any constant value. This is
|
- 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
|
- 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
|
- The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are
|
||||||
supported in any clocked block.
|
supported in any clocked block.
|
||||||
|
@ -407,7 +420,10 @@ from SystemVerilog:
|
||||||
- The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic``
|
- The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic``
|
||||||
and ``bit`` are supported.
|
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
|
- SystemVerilog packages are supported. Once a SystemVerilog file is read
|
||||||
into a design with ``read_verilog``, all its packages are available to
|
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)
|
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_NONE ? "NONE" :
|
||||||
msg_type == VERIFIC_ERROR ? "ERROR" :
|
msg_type == VERIFIC_ERROR ? "ERROR" :
|
||||||
msg_type == VERIFIC_WARNING ? "WARNING" :
|
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_INFO ? "INFO" :
|
||||||
msg_type == VERIFIC_COMMENT ? "COMMENT" :
|
msg_type == VERIFIC_COMMENT ? "COMMENT" :
|
||||||
msg_type == VERIFIC_PROGRAM_ERROR ? "PROGRAM_ERROR" : "UNKNOWN", message_id);
|
msg_type == VERIFIC_PROGRAM_ERROR ? "PROGRAM_ERROR" : "UNKNOWN", message_id);
|
||||||
|
|
||||||
if (linefile)
|
if (linefile)
|
||||||
log("%s:%d: ", LineFile::GetFileName(linefile), LineFile::GetLineNo(linefile));
|
message += stringf("%s:%d: ", LineFile::GetFileName(linefile), LineFile::GetLineNo(linefile));
|
||||||
logv(msg, args);
|
|
||||||
log("\n");
|
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
|
struct VerificImporter
|
||||||
|
@ -617,6 +623,10 @@ struct VerificImporter
|
||||||
|
|
||||||
module->fixup_ports();
|
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)
|
FOREACH_NET_OF_NETLIST(nl, mi, net)
|
||||||
{
|
{
|
||||||
if (net->IsRamNet())
|
if (net->IsRamNet())
|
||||||
|
@ -643,9 +653,59 @@ struct VerificImporter
|
||||||
|
|
||||||
memory->width = bits_in_word;
|
memory->width = bits_in_word;
|
||||||
memory->size = number_of_bits / 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;
|
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)) {
|
if (net_map.count(net)) {
|
||||||
// log(" skipping net %s.\n", net->Name());
|
// log(" skipping net %s.\n", net->Name());
|
||||||
continue;
|
continue;
|
||||||
|
@ -683,25 +743,94 @@ struct VerificImporter
|
||||||
wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex());
|
wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex());
|
||||||
import_attributes(wire->attributes, netbus);
|
import_attributes(wire->attributes, netbus);
|
||||||
|
|
||||||
for (int i = netbus->LeftIndex();; i += netbus->IsUp() ? +1 : -1) {
|
RTLIL::Const initval = Const(State::Sx, GetSize(wire));
|
||||||
if (netbus->ElementAtIndex(i)) {
|
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);
|
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)
|
if (net_map.count(net) == 0)
|
||||||
net_map[net] = bit;
|
net_map[net] = bit;
|
||||||
else
|
else
|
||||||
module->connect(bit, net_map.at(net));
|
module->connect(bit, net_map.at(net));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == netbus->RightIndex())
|
if (i == netbus->RightIndex())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (initval_valid)
|
||||||
|
wire->attributes["\\init"] = initval;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// log(" skipping netbus %s.\n", netbus->Name());
|
// 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)
|
FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst)
|
||||||
{
|
{
|
||||||
if (inst->Type() == PRIM_SVA_POSEDGE) {
|
if (inst->Type() == PRIM_SVA_POSEDGE) {
|
||||||
|
@ -733,7 +862,7 @@ struct VerificImporter
|
||||||
|
|
||||||
SigBit outsig = net_map.at(out);
|
SigBit outsig = net_map.at(out);
|
||||||
log_assert(outsig.wire && GetSize(outsig.wire) == 1);
|
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));
|
module->addDff(NEW_ID, net_map.at(clk), net_map.at(in2), net_map.at(out));
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -175,15 +175,17 @@ YOSYS_NAMESPACE_END
|
||||||
"always_ff" { SV_KEYWORD(TOK_ALWAYS); }
|
"always_ff" { SV_KEYWORD(TOK_ALWAYS); }
|
||||||
"always_latch" { SV_KEYWORD(TOK_ALWAYS); }
|
"always_latch" { SV_KEYWORD(TOK_ALWAYS); }
|
||||||
|
|
||||||
"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
|
"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
|
||||||
"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
|
"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
|
||||||
"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
|
"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
|
||||||
"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); }
|
"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); }
|
||||||
"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); }
|
"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); }
|
||||||
"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); }
|
"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); }
|
||||||
"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }
|
"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }
|
||||||
"logic" { SV_KEYWORD(TOK_REG); }
|
"checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); }
|
||||||
"bit" { SV_KEYWORD(TOK_REG); }
|
"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; }
|
"input" { return TOK_INPUT; }
|
||||||
"output" { return TOK_OUTPUT; }
|
"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_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
|
||||||
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME
|
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME
|
||||||
%token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
|
%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> 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
|
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
|
||||||
|
@ -465,7 +465,18 @@ module_body:
|
||||||
|
|
||||||
module_body_stmt:
|
module_body_stmt:
|
||||||
task_func_decl | param_decl | localparam_decl | defparam_decl | wire_decl | assign_stmt | cell_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:
|
task_func_decl:
|
||||||
attr TOK_DPI_FUNCTION TOK_ID TOK_ID {
|
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());
|
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
|
// 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_module(RTLIL::Module *module, std::string indent = "");
|
||||||
void log_cell(RTLIL::Cell *cell, std::string indent = "");
|
void log_cell(RTLIL::Cell *cell, std::string indent = "");
|
||||||
|
void log_wire(RTLIL::Wire *wire, std::string indent = "");
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static inline void log_assert_worker(bool cond, const char *expr, const char *file, int line) {
|
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)
|
if (detect_const_and || detect_const_or)
|
||||||
{
|
{
|
||||||
pool<SigBit> input_bits = assign_map(cell->getPort("\\A")).to_sigbit_pool();
|
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")) {
|
if (cell->hasPort("\\B")) {
|
||||||
vector<SigBit> more_bits = assign_map(cell->getPort("\\B")).to_sigbit_vector();
|
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) {
|
for (auto bit : input_bits) {
|
||||||
if (bit == State::S0)
|
if (bit.wire) {
|
||||||
found_zero = true;
|
if (invert_map.count(bit) && input_bits.count(invert_map.at(bit)))
|
||||||
if (bit == State::S1)
|
found_inv = true;
|
||||||
found_one = true;
|
if (non_const_input != State::Sm)
|
||||||
if (invert_map.count(bit) && input_bits.count(invert_map.at(bit)))
|
many_conconst = true;
|
||||||
found_inv = 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)) {
|
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);
|
replace_cell(assign_map, module, cell, "const_or", "\\Y", RTLIL::State::S1);
|
||||||
goto next_cell;
|
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") &&
|
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
|
//width of the variable port
|
||||||
int width;
|
int width;
|
||||||
|
int const_width;
|
||||||
|
|
||||||
bool var_signed;
|
bool var_signed;
|
||||||
|
|
||||||
|
@ -1216,6 +1232,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
sigVar = cell->getPort("\\A");
|
sigVar = cell->getPort("\\A");
|
||||||
sigConst = cell->getPort("\\B");
|
sigConst = cell->getPort("\\B");
|
||||||
width = cell->parameters["\\A_WIDTH"].as_int();
|
width = cell->parameters["\\A_WIDTH"].as_int();
|
||||||
|
const_width = cell->parameters["\\B_WIDTH"].as_int();
|
||||||
var_signed = cell->parameters["\\A_SIGNED"].as_bool();
|
var_signed = cell->parameters["\\A_SIGNED"].as_bool();
|
||||||
} else
|
} else
|
||||||
if (cell->type == "$gt" || cell->type == "$le") {
|
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");
|
sigVar = cell->getPort("\\B");
|
||||||
sigConst = cell->getPort("\\A");
|
sigConst = cell->getPort("\\A");
|
||||||
width = cell->parameters["\\B_WIDTH"].as_int();
|
width = cell->parameters["\\B_WIDTH"].as_int();
|
||||||
|
const_width = cell->parameters["\\A_WIDTH"].as_int();
|
||||||
var_signed = cell->parameters["\\B_SIGNED"].as_bool();
|
var_signed = cell->parameters["\\B_SIGNED"].as_bool();
|
||||||
}
|
} else
|
||||||
|
log_abort();
|
||||||
|
|
||||||
// replace a(signed) < 0 with the high bit of a
|
// replace a(signed) < 0 with the high bit of a
|
||||||
if (sigConst.is_fully_const() && sigConst.is_fully_zero() && var_signed == true)
|
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);
|
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;
|
int bit_set = const_bit_set;
|
||||||
RTLIL::SigSpec a_prime(RTLIL::State::S0, width - bit_set);
|
RTLIL::SigSpec a_prime(RTLIL::State::S0, width - bit_set);
|
||||||
for (int i = bit_set; i < width; i++) {
|
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;
|
did_something = true;
|
||||||
goto next_cell;
|
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);
|
dff_init_map.set(module);
|
||||||
for (auto &it : module->wires_)
|
for (auto &it : module->wires_)
|
||||||
if (it.second->attributes.count("\\init") != 0)
|
if (it.second->attributes.count("\\init") != 0) {
|
||||||
dff_init_map.add(it.second, it.second->attributes.at("\\init"));
|
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;
|
bool did_something = true;
|
||||||
while (did_something)
|
while (did_something)
|
||||||
|
|
|
@ -244,7 +244,9 @@ struct OptRmdffPass : public Pass {
|
||||||
{
|
{
|
||||||
if (wire->attributes.count("\\init") != 0) {
|
if (wire->attributes.count("\\init") != 0) {
|
||||||
Const initval = wire->attributes.at("\\init");
|
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++) {
|
for (int i = 0; i < GetSize(wire); i++) {
|
||||||
SigBit wire_bit(wire, i), mapped_bit = assign_map(wire_bit);
|
SigBit wire_bit(wire, i), mapped_bit = assign_map(wire_bit);
|
||||||
if (mapped_bit.wire) {
|
if (mapped_bit.wire) {
|
||||||
|
|
Loading…
Reference in New Issue