mirror of https://github.com/YosysHQ/yosys.git
Merging with official repo
This commit is contained in:
commit
4d343fc1cd
56
Makefile
56
Makefile
|
@ -15,6 +15,7 @@ ENABLE_EDITLINE := 0
|
|||
ENABLE_VERIFIC := 0
|
||||
ENABLE_COVER := 1
|
||||
ENABLE_LIBYOSYS := 0
|
||||
ENABLE_PROTOBUF := 0
|
||||
|
||||
# other configuration flags
|
||||
ENABLE_GPROF := 0
|
||||
|
@ -22,6 +23,9 @@ ENABLE_DEBUG := 0
|
|||
ENABLE_NDEBUG := 0
|
||||
LINK_CURSES := 0
|
||||
LINK_TERMCAP := 0
|
||||
LINK_ABC := 0
|
||||
# Needed for environments that don't have proper thread support (i.e. emscripten)
|
||||
DISABLE_ABC_THREADS := 0
|
||||
|
||||
# clang sanitizers
|
||||
SANITIZER =
|
||||
|
@ -103,7 +107,7 @@ OBJS = kernel/version_$(GIT_REV).o
|
|||
# is just a symlink to your actual ABC working directory, as 'make mrproper'
|
||||
# will remove the 'abc' directory and you do not want to accidentally
|
||||
# delete your work on ABC..
|
||||
ABCREV = f23ea8e
|
||||
ABCREV = 6df1396
|
||||
ABCPULL = 1
|
||||
ABCURL ?= https://github.com/berkeley-abc/abc
|
||||
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
|
||||
|
@ -126,6 +130,7 @@ ifeq ($(CONFIG),clang)
|
|||
CXX = clang
|
||||
LD = clang++
|
||||
CXXFLAGS += -std=c++11 -Os
|
||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
|
||||
|
||||
ifneq ($(SANITIZER),)
|
||||
$(info [Clang Sanitizer] $(SANITIZER))
|
||||
|
@ -148,16 +153,19 @@ else ifeq ($(CONFIG),gcc)
|
|||
CXX = gcc
|
||||
LD = gcc
|
||||
CXXFLAGS += -std=c++11 -Os
|
||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
|
||||
|
||||
else ifeq ($(CONFIG),gcc-4.8)
|
||||
CXX = gcc-4.8
|
||||
LD = gcc-4.8
|
||||
CXXFLAGS += -std=c++11 -Os
|
||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
|
||||
|
||||
else ifeq ($(CONFIG),emcc)
|
||||
CXX = emcc
|
||||
LD = emcc
|
||||
CXXFLAGS := -std=c++11 $(filter-out -fPIC -ggdb,$(CXXFLAGS))
|
||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DABC_MEMALIGN=8"
|
||||
EMCCFLAGS := -Os -Wno-warn-absolute-paths
|
||||
EMCCFLAGS += --memory-init-file 0 --embed-file share -s NO_EXIT_RUNTIME=1
|
||||
EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt','_errmsg']"
|
||||
|
@ -171,6 +179,11 @@ EXE = .js
|
|||
TARGETS := $(filter-out yosys-config,$(TARGETS))
|
||||
EXTRA_TARGETS += yosysjs-$(YOSYS_VER).zip
|
||||
|
||||
ifeq ($(ENABLE_ABC),1)
|
||||
LINK_ABC := 1
|
||||
DISABLE_ABC_THREADS := 1
|
||||
endif
|
||||
|
||||
viz.js:
|
||||
wget -O viz.js.part https://github.com/mdaines/viz.js/releases/download/0.0.3/viz.js
|
||||
mv viz.js.part viz.js
|
||||
|
@ -192,8 +205,8 @@ CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_MXE_HACKS -Wno-attributes
|
|||
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
|
||||
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
|
||||
LDLIBS := $(filter-out -lrt,$(LDLIBS))
|
||||
ABCMKARGS += ARCHFLAGS="-DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
||||
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="$(CXX)" CXX="$(CXX)"
|
||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
||||
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1
|
||||
EXE = .exe
|
||||
|
||||
else ifeq ($(CONFIG),msys2)
|
||||
|
@ -203,8 +216,8 @@ CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
|
|||
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
|
||||
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
|
||||
LDLIBS := $(filter-out -lrt,$(LDLIBS))
|
||||
ABCMKARGS += ARCHFLAGS="-DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
||||
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=0 CC="i686-w64-mingw32-gcc" CXX="$(CXX)"
|
||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
||||
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=0
|
||||
EXE = .exe
|
||||
|
||||
else ifneq ($(CONFIG),none)
|
||||
|
@ -236,9 +249,15 @@ else
|
|||
ifeq ($(ENABLE_EDITLINE),1)
|
||||
CXXFLAGS += -DYOSYS_ENABLE_EDITLINE
|
||||
LDLIBS += -ledit -ltinfo -lbsd
|
||||
else
|
||||
ABCMKARGS += "ABC_USE_NO_READLINE=1"
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(DISABLE_ABC_THREADS),1)
|
||||
ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_PLUGINS),1)
|
||||
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)
|
||||
|
@ -288,10 +307,17 @@ endif
|
|||
|
||||
ifeq ($(ENABLE_ABC),1)
|
||||
CXXFLAGS += -DYOSYS_ENABLE_ABC
|
||||
ifeq ($(LINK_ABC),1)
|
||||
CXXFLAGS += -DYOSYS_LINK_ABC
|
||||
ifeq ($(DISABLE_ABC_THREADS),0)
|
||||
LDLIBS += -lpthread
|
||||
endif
|
||||
else
|
||||
ifeq ($(ABCEXTERNAL),)
|
||||
TARGETS += yosys-abc$(EXE)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_VERIFIC),1)
|
||||
VERIFIC_DIR ?= /usr/local/src/verific_lib_eval
|
||||
|
@ -300,6 +326,10 @@ CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABL
|
|||
LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VERIFIC_COMPONENTS)) -lz
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_PROTOBUF),1)
|
||||
LDLIBS += $(shell pkg-config --cflags --libs protobuf)
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_COVER),1)
|
||||
CXXFLAGS += -DYOSYS_ENABLE_COVER
|
||||
endif
|
||||
|
@ -411,6 +441,10 @@ include techlibs/common/Makefile.inc
|
|||
|
||||
endif
|
||||
|
||||
ifeq ($(LINK_ABC),1)
|
||||
OBJS += yosys-libabc.a
|
||||
endif
|
||||
|
||||
top-all: $(TARGETS) $(EXTRA_TARGETS)
|
||||
@echo ""
|
||||
@echo " Build successful."
|
||||
|
@ -455,7 +489,7 @@ yosys-config: misc/yosys-config.in
|
|||
-e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > yosys-config
|
||||
$(Q) chmod +x yosys-config
|
||||
|
||||
abc/abc-$(ABCREV)$(EXE):
|
||||
abc/abc-$(ABCREV)$(EXE) abc/libabc-$(ABCREV).a:
|
||||
$(P)
|
||||
ifneq ($(ABCREV),default)
|
||||
$(Q) if test -d abc/.hg; then \
|
||||
|
@ -472,15 +506,19 @@ ifneq ($(ABCREV),default)
|
|||
fi
|
||||
endif
|
||||
$(Q) rm -f abc/abc-[0-9a-f]*
|
||||
$(Q) cd abc && $(MAKE) $(S) $(ABCMKARGS) PROG="abc-$(ABCREV)$(EXE)" MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: "
|
||||
$(Q) cd abc && $(MAKE) $(S) $(ABCMKARGS) $(if $(filter %.a,$@),PROG="abc-$(ABCREV)",PROG="abc-$(ABCREV)$(EXE)") MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: " $(if $(filter %.a,$@),libabc-$(ABCREV).a)
|
||||
|
||||
ifeq ($(ABCREV),default)
|
||||
.PHONY: abc/abc-$(ABCREV)$(EXE)
|
||||
.PHONY: abc/libabc-$(ABCREV).a
|
||||
endif
|
||||
|
||||
yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE)
|
||||
$(P) cp abc/abc-$(ABCREV)$(EXE) yosys-abc$(EXE)
|
||||
|
||||
yosys-libabc.a: abc/libabc-$(ABCREV).a
|
||||
$(P) cp abc/libabc-$(ABCREV).a yosys-libabc.a
|
||||
|
||||
ifneq ($(SEED),)
|
||||
SEEDOPT="-S $(SEED)"
|
||||
else
|
||||
|
@ -564,7 +602,7 @@ clean:
|
|||
rm -rf share
|
||||
if test -d manual; then cd manual && sh clean.sh; fi
|
||||
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS)
|
||||
rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]*
|
||||
rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
|
||||
rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d
|
||||
rm -rf tests/asicworld/*.out tests/asicworld/*.log
|
||||
rm -rf tests/hana/*.out tests/hana/*.log
|
||||
|
@ -577,7 +615,7 @@ clean:
|
|||
|
||||
clean-abc:
|
||||
$(MAKE) -C abc DEP= clean
|
||||
rm -f yosys-abc$(EXE) abc/abc-[0-9a-f]*
|
||||
rm -f yosys-abc$(EXE) yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
|
||||
|
||||
mrproper: clean
|
||||
git clean -xdf
|
||||
|
|
10
README.md
10
README.md
|
@ -52,19 +52,19 @@ For example on Ubuntu Linux 16.04 LTS the following commands will install all
|
|||
prerequisites for building yosys:
|
||||
|
||||
$ sudo apt-get install build-essential clang bison flex \
|
||||
libreadline-dev gawk tcl-dev libffi-dev git mercurial \
|
||||
libreadline-dev gawk tcl-dev libffi-dev git \
|
||||
graphviz xdot pkg-config python3
|
||||
|
||||
Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies:
|
||||
|
||||
$ brew tap Homebrew/bundle && brew bundle
|
||||
$ sudo port install bison flex readline gawk libffi \
|
||||
git mercurial graphviz pkgconfig python36
|
||||
git graphviz pkgconfig python36
|
||||
|
||||
On FreeBSD use the following command to install all prerequisites:
|
||||
|
||||
# pkg install bison flex readline gawk libffi\
|
||||
git mercurial graphviz pkgconfig python3 python36 tcl-wrapper
|
||||
git graphviz pkgconfig python3 python36 tcl-wrapper
|
||||
|
||||
On FreeBSD system use gmake instead of make. To run tests use:
|
||||
% MAKE=gmake CC=cc gmake test
|
||||
|
@ -418,7 +418,9 @@ Non-standard or SystemVerilog features for formal verification
|
|||
supported in any clocked block.
|
||||
|
||||
- The syntax ``@($global_clock)`` can be used to create FFs that have no
|
||||
explicit clock input ($ff cells).
|
||||
explicit clock input ($ff cells). The same can be achieved by using
|
||||
``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>``
|
||||
is marked with the ``(* gclk *)`` Verilog attribute.
|
||||
|
||||
|
||||
Supported features from SystemVerilog
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
yosys.pb.cc
|
||||
yosys.pb.h
|
|
@ -0,0 +1,8 @@
|
|||
ifeq ($(ENABLE_PROTOBUF),1)
|
||||
|
||||
backends/protobuf/yosys.pb.cc backends/protobuf/yosys.pb.h: misc/yosys.proto
|
||||
$(Q) cd misc && protoc --cpp_out "../backends/protobuf" yosys.proto
|
||||
|
||||
OBJS += backends/protobuf/protobuf.o backends/protobuf/yosys.pb.o
|
||||
|
||||
endif
|
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||
* Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <google/protobuf/text_format.h>
|
||||
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/cellaigs.h"
|
||||
#include "kernel/log.h"
|
||||
#include "yosys.pb.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct ProtobufDesignSerializer
|
||||
{
|
||||
bool aig_mode_;
|
||||
bool use_selection_;
|
||||
yosys::pb::Design *pb_;
|
||||
|
||||
Design *design_;
|
||||
Module *module_;
|
||||
|
||||
SigMap sigmap_;
|
||||
int sigidcounter_;
|
||||
dict<SigBit, uint64_t> sigids_;
|
||||
pool<Aig> aig_models_;
|
||||
|
||||
|
||||
ProtobufDesignSerializer(bool use_selection, bool aig_mode) :
|
||||
aig_mode_(aig_mode), use_selection_(use_selection) { }
|
||||
|
||||
string get_name(IdString name)
|
||||
{
|
||||
return RTLIL::unescape_id(name);
|
||||
}
|
||||
|
||||
|
||||
void serialize_parameters(google::protobuf::Map<std::string, yosys::pb::Parameter> *out,
|
||||
const dict<IdString, Const> ¶meters)
|
||||
{
|
||||
for (auto ¶m : parameters) {
|
||||
std::string key = get_name(param.first);
|
||||
|
||||
|
||||
yosys::pb::Parameter pb_param;
|
||||
|
||||
if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) {
|
||||
pb_param.set_str(param.second.decode_string());
|
||||
} else if (GetSize(param.second.bits) > 64) {
|
||||
pb_param.set_str(param.second.as_string());
|
||||
} else {
|
||||
pb_param.set_int_(param.second.as_int());
|
||||
}
|
||||
|
||||
(*out)[key] = pb_param;
|
||||
}
|
||||
}
|
||||
|
||||
void get_bits(yosys::pb::BitVector *out, SigSpec sig)
|
||||
{
|
||||
for (auto bit : sigmap_(sig)) {
|
||||
auto sig = out->add_signal();
|
||||
|
||||
// Constant driver.
|
||||
if (bit.wire == nullptr) {
|
||||
if (bit == State::S0) sig->set_constant(sig->CONSTANT_DRIVER_LOW);
|
||||
else if (bit == State::S1) sig->set_constant(sig->CONSTANT_DRIVER_HIGH);
|
||||
else if (bit == State::Sz) sig->set_constant(sig->CONSTANT_DRIVER_Z);
|
||||
else sig->set_constant(sig->CONSTANT_DRIVER_X);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Signal - give it a unique identifier.
|
||||
if (sigids_.count(bit) == 0) {
|
||||
sigids_[bit] = sigidcounter_++;
|
||||
}
|
||||
sig->set_id(sigids_[bit]);
|
||||
}
|
||||
}
|
||||
|
||||
void serialize_module(yosys::pb::Module* out, Module *module)
|
||||
{
|
||||
module_ = module;
|
||||
log_assert(module_->design == design_);
|
||||
sigmap_.set(module_);
|
||||
sigids_.clear();
|
||||
sigidcounter_ = 0;
|
||||
|
||||
serialize_parameters(out->mutable_attribute(), module_->attributes);
|
||||
|
||||
for (auto n : module_->ports) {
|
||||
Wire *w = module->wire(n);
|
||||
if (use_selection_ && !module_->selected(w))
|
||||
continue;
|
||||
|
||||
yosys::pb::Module::Port pb_port;
|
||||
pb_port.set_direction(w->port_input ? w->port_output ?
|
||||
yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT : yosys::pb::DIRECTION_OUTPUT);
|
||||
get_bits(pb_port.mutable_bits(), w);
|
||||
(*out->mutable_port())[get_name(n)] = pb_port;
|
||||
}
|
||||
|
||||
for (auto c : module_->cells()) {
|
||||
if (use_selection_ && !module_->selected(c))
|
||||
continue;
|
||||
|
||||
yosys::pb::Module::Cell pb_cell;
|
||||
pb_cell.set_hide_name(c->name[0] == '$');
|
||||
pb_cell.set_type(get_name(c->type));
|
||||
|
||||
if (aig_mode_) {
|
||||
Aig aig(c);
|
||||
if (aig.name.empty())
|
||||
continue;
|
||||
pb_cell.set_model(aig.name);
|
||||
aig_models_.insert(aig);
|
||||
}
|
||||
serialize_parameters(pb_cell.mutable_parameter(), c->parameters);
|
||||
serialize_parameters(pb_cell.mutable_attribute(), c->attributes);
|
||||
|
||||
if (c->known()) {
|
||||
for (auto &conn : c->connections()) {
|
||||
yosys::pb::Direction direction = yosys::pb::DIRECTION_OUTPUT;
|
||||
if (c->input(conn.first))
|
||||
direction = c->output(conn.first) ? yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT;
|
||||
(*pb_cell.mutable_port_direction())[get_name(conn.first)] = direction;
|
||||
}
|
||||
}
|
||||
for (auto &conn : c->connections()) {
|
||||
yosys::pb::BitVector vec;
|
||||
get_bits(&vec, conn.second);
|
||||
(*pb_cell.mutable_connection())[get_name(conn.first)] = vec;
|
||||
}
|
||||
|
||||
(*out->mutable_cell())[get_name(c->name)] = pb_cell;
|
||||
}
|
||||
|
||||
for (auto w : module_->wires()) {
|
||||
if (use_selection_ && !module_->selected(w))
|
||||
continue;
|
||||
|
||||
auto netname = out->add_netname();
|
||||
netname->set_hide_name(w->name[0] == '$');
|
||||
get_bits(netname->mutable_bits(), w);
|
||||
serialize_parameters(netname->mutable_attributes(), w->attributes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void serialize_models(google::protobuf::Map<string, yosys::pb::Model> *models)
|
||||
{
|
||||
for (auto &aig : aig_models_) {
|
||||
yosys::pb::Model pb_model;
|
||||
for (auto &node : aig.nodes) {
|
||||
auto pb_node = pb_model.add_node();
|
||||
if (node.portbit >= 0) {
|
||||
if (node.inverter) {
|
||||
pb_node->set_type(pb_node->TYPE_NPORT);
|
||||
} else {
|
||||
pb_node->set_type(pb_node->TYPE_PORT);
|
||||
}
|
||||
auto port = pb_node->mutable_port();
|
||||
port->set_portname(log_id(node.portname));
|
||||
port->set_bitindex(node.portbit);
|
||||
} else if (node.left_parent < 0 && node.right_parent < 0) {
|
||||
if (node.inverter) {
|
||||
pb_node->set_type(pb_node->TYPE_TRUE);
|
||||
} else {
|
||||
pb_node->set_type(pb_node->TYPE_FALSE);
|
||||
}
|
||||
} else {
|
||||
if (node.inverter) {
|
||||
pb_node->set_type(pb_node->TYPE_NAND);
|
||||
} else {
|
||||
pb_node->set_type(pb_node->TYPE_AND);
|
||||
}
|
||||
auto gate = pb_node->mutable_gate();
|
||||
gate->set_left(node.left_parent);
|
||||
gate->set_right(node.right_parent);
|
||||
}
|
||||
for (auto &op : node.outports) {
|
||||
auto pb_op = pb_node->add_out_port();
|
||||
pb_op->set_name(log_id(op.first));
|
||||
pb_op->set_bit_index(op.second);
|
||||
}
|
||||
}
|
||||
(*models)[aig.name] = pb_model;
|
||||
}
|
||||
}
|
||||
|
||||
void serialize_design(yosys::pb::Design *pb, Design *design)
|
||||
{
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
pb_ = pb;
|
||||
pb_->Clear();
|
||||
pb_->set_creator(yosys_version_str);
|
||||
|
||||
design_ = design;
|
||||
design_->sort();
|
||||
|
||||
auto modules = use_selection_ ? design_->selected_modules() : design_->modules();
|
||||
for (auto mod : modules) {
|
||||
yosys::pb::Module pb_mod;
|
||||
serialize_module(&pb_mod, mod);
|
||||
(*pb->mutable_modules())[mod->name.str()] = pb_mod;
|
||||
}
|
||||
|
||||
serialize_models(pb_->mutable_models());
|
||||
}
|
||||
};
|
||||
|
||||
struct ProtobufBackend : public Backend {
|
||||
ProtobufBackend(): Backend("protobuf", "write design to a Protocol Buffer file") { }
|
||||
virtual void help()
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" write_protobuf [options] [filename]\n");
|
||||
log("\n");
|
||||
log("Write a JSON netlist of the current design.\n");
|
||||
log("\n");
|
||||
log(" -aig\n");
|
||||
log(" include AIG models for the different gate types\n");
|
||||
log("\n");
|
||||
log(" -text\n");
|
||||
log(" output protobuf in Text/ASCII representation\n");
|
||||
log("\n");
|
||||
log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
|
||||
log("Yosys source code distribution.\n");
|
||||
log("\n");
|
||||
}
|
||||
virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
|
||||
{
|
||||
bool aig_mode = false;
|
||||
bool text_mode = false;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
if (args[argidx] == "-aig") {
|
||||
aig_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-text") {
|
||||
text_mode = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx);
|
||||
|
||||
log_header(design, "Executing Protobuf backend.\n");
|
||||
|
||||
yosys::pb::Design pb;
|
||||
ProtobufDesignSerializer serializer(false, aig_mode);
|
||||
serializer.serialize_design(&pb, design);
|
||||
|
||||
if (text_mode) {
|
||||
string out;
|
||||
google::protobuf::TextFormat::PrintToString(pb, &out);
|
||||
*f << out;
|
||||
} else {
|
||||
pb.SerializeToOstream(f);
|
||||
}
|
||||
}
|
||||
} ProtobufBackend;
|
||||
|
||||
struct ProtobufPass : public Pass {
|
||||
ProtobufPass() : Pass("protobuf", "write design in Protobuf format") { }
|
||||
virtual void help()
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" protobuf [options] [selection]\n");
|
||||
log("\n");
|
||||
log("Write a JSON netlist of all selected objects.\n");
|
||||
log("\n");
|
||||
log(" -o <filename>\n");
|
||||
log(" write to the specified file.\n");
|
||||
log("\n");
|
||||
log(" -aig\n");
|
||||
log(" include AIG models for the different gate types\n");
|
||||
log("\n");
|
||||
log(" -text\n");
|
||||
log(" output protobuf in Text/ASCII representation\n");
|
||||
log("\n");
|
||||
log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
|
||||
log("Yosys source code distribution.\n");
|
||||
log("\n");
|
||||
}
|
||||
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
|
||||
{
|
||||
std::string filename;
|
||||
bool aig_mode = false;
|
||||
bool text_mode = false;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
if (args[argidx] == "-o" && argidx+1 < args.size()) {
|
||||
filename = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-aig") {
|
||||
aig_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-text") {
|
||||
text_mode = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
std::ostream *f;
|
||||
std::stringstream buf;
|
||||
|
||||
if (!filename.empty()) {
|
||||
std::ofstream *ff = new std::ofstream;
|
||||
ff->open(filename.c_str(), std::ofstream::trunc);
|
||||
if (ff->fail()) {
|
||||
delete ff;
|
||||
log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
|
||||
}
|
||||
f = ff;
|
||||
} else {
|
||||
f = &buf;
|
||||
}
|
||||
|
||||
yosys::pb::Design pb;
|
||||
ProtobufDesignSerializer serializer(true, aig_mode);
|
||||
serializer.serialize_design(&pb, design);
|
||||
|
||||
if (text_mode) {
|
||||
string out;
|
||||
google::protobuf::TextFormat::PrintToString(pb, &out);
|
||||
*f << out;
|
||||
} else {
|
||||
pb.SerializeToOstream(f);
|
||||
}
|
||||
|
||||
if (!filename.empty()) {
|
||||
delete f;
|
||||
} else {
|
||||
log("%s", buf.str().c_str());
|
||||
}
|
||||
}
|
||||
} ProtobufPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END;
|
|
@ -1,11 +1,12 @@
|
|||
|
||||
read_verilog counter.v
|
||||
read_verilog -lib cmos_cells.v
|
||||
|
||||
proc;; memory;; techmap;;
|
||||
|
||||
synth
|
||||
dfflibmap -liberty cmos_cells.lib
|
||||
abc -liberty cmos_cells.lib;;
|
||||
abc -liberty cmos_cells.lib
|
||||
opt_clean
|
||||
|
||||
stat -liberty cmos_cells.lib
|
||||
|
||||
# http://vlsiarch.ecen.okstate.edu/flows/MOSIS_SCMOS/latest/cadence/lib/tsmc025/signalstorm/osu025_stdcells.lib
|
||||
# dfflibmap -liberty osu025_stdcells.lib
|
||||
|
@ -13,4 +14,3 @@ abc -liberty cmos_cells.lib;;
|
|||
|
||||
write_verilog synth.v
|
||||
write_spice synth.sp
|
||||
|
||||
|
|
|
@ -223,12 +223,18 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
bool found_global_syncs = false;
|
||||
bool found_anyedge_syncs = false;
|
||||
for (auto child : always->children)
|
||||
{
|
||||
if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER &&
|
||||
child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk")) {
|
||||
found_global_syncs = true;
|
||||
}
|
||||
if (child->type == AST_EDGE) {
|
||||
if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->str == "\\$global_clock")
|
||||
found_global_syncs = true;
|
||||
else
|
||||
found_anyedge_syncs = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_anyedge_syncs) {
|
||||
if (found_global_syncs)
|
||||
|
@ -242,6 +248,9 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
bool found_clocked_sync = false;
|
||||
for (auto child : always->children)
|
||||
if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) {
|
||||
if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast &&
|
||||
child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk"))
|
||||
continue;
|
||||
found_clocked_sync = true;
|
||||
if (found_global_syncs || found_anyedge_syncs)
|
||||
log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum);
|
||||
|
@ -1291,6 +1300,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
|
||||
cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
|
||||
|
||||
if (!sign_hint)
|
||||
is_signed = false;
|
||||
|
||||
return RTLIL::SigSpec(wire);
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
|
|||
}
|
||||
|
||||
if (0 <= top && stack[top].type == 2) {
|
||||
if (next_token.type == '*' || next_token.type == '&' || next_token.type == 0 || next_token.type == '(')
|
||||
if (next_token.type == '*' || next_token.type == '&' || next_token.type == 0 || next_token.type == '(' || next_token.type == '!')
|
||||
return false;
|
||||
stack[top].type = 3;
|
||||
return true;
|
||||
|
|
|
@ -62,6 +62,7 @@ using namespace Verific;
|
|||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
int verific_verbose;
|
||||
bool verific_import_pending;
|
||||
string verific_error_msg;
|
||||
|
||||
void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefile, const char *msg, va_list args)
|
||||
|
@ -189,12 +190,12 @@ RTLIL::SigSpec VerificImporter::operatorInport(Instance *inst, const char *portn
|
|||
}
|
||||
}
|
||||
|
||||
RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst)
|
||||
RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst, const pool<Net*, hash_ptr_ops> *any_all_nets)
|
||||
{
|
||||
RTLIL::SigSpec sig;
|
||||
RTLIL::Wire *dummy_wire = NULL;
|
||||
for (int i = int(inst->OutputSize())-1; i >= 0; i--)
|
||||
if (inst->GetOutputBit(i)) {
|
||||
if (inst->GetOutputBit(i) && (!any_all_nets || !any_all_nets->count(inst->GetOutputBit(i)))) {
|
||||
sig.append(net_map_at(inst->GetOutputBit(i)));
|
||||
dummy_wire = NULL;
|
||||
} else {
|
||||
|
@ -244,7 +245,9 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
|
|||
}
|
||||
|
||||
if (inst->Type() == PRIM_BUF) {
|
||||
module->addBufGate(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
auto outnet = inst->GetOutput();
|
||||
if (!any_all_nets.count(outnet))
|
||||
module->addBufGate(inst_name, net_map_at(inst->GetInput()), net_map_at(outnet));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -394,6 +397,7 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
|
|||
#define IN1 operatorInput1(inst)
|
||||
#define IN2 operatorInput2(inst)
|
||||
#define OUT operatorOutput(inst)
|
||||
#define FILTERED_OUT operatorOutput(inst, &any_all_nets)
|
||||
#define SIGNED inst->View()->IsSigned()
|
||||
|
||||
if (inst->Type() == OPER_ADDER) {
|
||||
|
@ -525,7 +529,7 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
|
|||
}
|
||||
|
||||
if (inst->Type() == OPER_WIDE_BUF) {
|
||||
module->addPos(inst_name, IN, OUT, SIGNED);
|
||||
module->addPos(inst_name, IN, FILTERED_OUT, SIGNED);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -791,6 +795,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
dict<Net*, char, hash_ptr_ops> init_nets;
|
||||
pool<Net*, hash_ptr_ops> anyconst_nets, anyseq_nets;
|
||||
pool<Net*, hash_ptr_ops> allconst_nets, allseq_nets;
|
||||
any_all_nets.clear();
|
||||
|
||||
FOREACH_NET_OF_NETLIST(nl, mi, net)
|
||||
{
|
||||
|
@ -871,23 +876,30 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
const char *allconst_attr = net->GetAttValue("allconst");
|
||||
const char *allseq_attr = net->GetAttValue("allseq");
|
||||
|
||||
if (rand_const_attr != nullptr && !strcmp(rand_const_attr, "1"))
|
||||
if (rand_const_attr != nullptr && (!strcmp(rand_const_attr, "1") || !strcmp(rand_const_attr, "'1'"))) {
|
||||
anyconst_nets.insert(net);
|
||||
|
||||
else if (rand_attr != nullptr && !strcmp(rand_attr, "1"))
|
||||
any_all_nets.insert(net);
|
||||
}
|
||||
else if (rand_attr != nullptr && (!strcmp(rand_attr, "1") || !strcmp(rand_attr, "'1'"))) {
|
||||
anyseq_nets.insert(net);
|
||||
|
||||
else if (anyconst_attr != nullptr && !strcmp(anyconst_attr, "1"))
|
||||
any_all_nets.insert(net);
|
||||
}
|
||||
else if (anyconst_attr != nullptr && (!strcmp(anyconst_attr, "1") || !strcmp(anyconst_attr, "'1'"))) {
|
||||
anyconst_nets.insert(net);
|
||||
|
||||
else if (anyseq_attr != nullptr && !strcmp(anyseq_attr, "1"))
|
||||
any_all_nets.insert(net);
|
||||
}
|
||||
else if (anyseq_attr != nullptr && (!strcmp(anyseq_attr, "1") || !strcmp(anyseq_attr, "'1'"))) {
|
||||
anyseq_nets.insert(net);
|
||||
|
||||
else if (allconst_attr != nullptr && !strcmp(allconst_attr, "1"))
|
||||
any_all_nets.insert(net);
|
||||
}
|
||||
else if (allconst_attr != nullptr && (!strcmp(allconst_attr, "1") || !strcmp(allconst_attr, "'1'"))) {
|
||||
allconst_nets.insert(net);
|
||||
|
||||
else if (allseq_attr != nullptr && !strcmp(allseq_attr, "1"))
|
||||
any_all_nets.insert(net);
|
||||
}
|
||||
else if (allseq_attr != nullptr && (!strcmp(allseq_attr, "1") || !strcmp(allseq_attr, "'1'"))) {
|
||||
allseq_nets.insert(net);
|
||||
any_all_nets.insert(net);
|
||||
}
|
||||
|
||||
if (net_map.count(net)) {
|
||||
if (verific_verbose)
|
||||
|
@ -1064,7 +1076,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
}
|
||||
|
||||
if (inst->Type() == PRIM_BUF) {
|
||||
module->addBufGate(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
|
||||
auto outnet = inst->GetOutput();
|
||||
if (!any_all_nets.count(outnet))
|
||||
module->addBufGate(inst_name, net_map_at(inst->GetInput()), net_map_at(outnet));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1382,7 +1396,8 @@ VerificClocking::VerificClocking(VerificImporter *importer, Net *net, bool sva_a
|
|||
return;
|
||||
}
|
||||
|
||||
if (inst != nullptr && inst->Type() == PRIM_SVA_POSEDGE)
|
||||
// Use while() instead of if() to work around VIPER #13453
|
||||
while (inst != nullptr && inst->Type() == PRIM_SVA_POSEDGE)
|
||||
{
|
||||
net = inst->GetInput();
|
||||
inst = net->Driver();;
|
||||
|
@ -1456,6 +1471,10 @@ VerificClocking::VerificClocking(VerificImporter *importer, Net *net, bool sva_a
|
|||
|
||||
clock_net = net;
|
||||
clock_sig = importer->net_map_at(clock_net);
|
||||
|
||||
const char *gclk_attr = clock_net->GetAttValue("gclk");
|
||||
if (gclk_attr != nullptr && (!strcmp(gclk_attr, "1") || !strcmp(gclk_attr, "'1'")))
|
||||
gclk = true;
|
||||
}
|
||||
|
||||
Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const init_value)
|
||||
|
@ -1478,15 +1497,20 @@ Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const
|
|||
sig_d = module->Mux(NEW_ID, sig_q, sig_d, enable_sig);
|
||||
|
||||
if (disable_sig != State::S0) {
|
||||
log_assert(gclk == false);
|
||||
log_assert(GetSize(sig_q) == GetSize(init_value));
|
||||
return module->addAdff(name, clock_sig, disable_sig, sig_d, sig_q, init_value, posedge);
|
||||
}
|
||||
|
||||
if (gclk)
|
||||
return module->addFf(name, sig_d, sig_q);
|
||||
|
||||
return module->addDff(name, clock_sig, sig_d, sig_q, posedge);
|
||||
}
|
||||
|
||||
Cell *VerificClocking::addAdff(IdString name, RTLIL::SigSpec sig_arst, SigSpec sig_d, SigSpec sig_q, Const arst_value)
|
||||
{
|
||||
log_assert(gclk == false);
|
||||
log_assert(disable_sig == State::S0);
|
||||
|
||||
if (enable_sig != State::S1)
|
||||
|
@ -1497,6 +1521,7 @@ Cell *VerificClocking::addAdff(IdString name, RTLIL::SigSpec sig_arst, SigSpec s
|
|||
|
||||
Cell *VerificClocking::addDffsr(IdString name, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, SigSpec sig_d, SigSpec sig_q)
|
||||
{
|
||||
log_assert(gclk == false);
|
||||
log_assert(disable_sig == State::S0);
|
||||
|
||||
if (enable_sig != State::S1)
|
||||
|
@ -1589,11 +1614,71 @@ struct VerificExtNets
|
|||
}
|
||||
};
|
||||
|
||||
void verific_import(Design *design, std::string top)
|
||||
{
|
||||
std::set<Netlist*> nl_todo, nl_done;
|
||||
|
||||
{
|
||||
VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1);
|
||||
VeriLibrary *veri_lib = veri_file::GetLibrary("work", 1);
|
||||
|
||||
Array veri_libs, vhdl_libs;
|
||||
if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
|
||||
if (veri_lib) veri_libs.InsertLast(veri_lib);
|
||||
|
||||
Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs);
|
||||
Netlist *nl;
|
||||
int i;
|
||||
|
||||
FOREACH_ARRAY_ITEM(netlists, i, nl) {
|
||||
if (top.empty() || nl->Owner()->Name() == top)
|
||||
nl_todo.insert(nl);
|
||||
}
|
||||
|
||||
delete netlists;
|
||||
}
|
||||
|
||||
if (!verific_error_msg.empty())
|
||||
log_error("%s\n", verific_error_msg.c_str());
|
||||
|
||||
VerificExtNets worker;
|
||||
for (auto nl : nl_todo)
|
||||
worker.run(nl);
|
||||
|
||||
while (!nl_todo.empty()) {
|
||||
Netlist *nl = *nl_todo.begin();
|
||||
if (nl_done.count(nl) == 0) {
|
||||
VerificImporter importer(false, false, false, false, false, false);
|
||||
importer.import_netlist(design, nl, nl_todo);
|
||||
}
|
||||
nl_todo.erase(nl);
|
||||
nl_done.insert(nl);
|
||||
}
|
||||
|
||||
veri_file::Reset();
|
||||
vhdl_file::Reset();
|
||||
Libset::Reset();
|
||||
verific_import_pending = false;
|
||||
|
||||
if (!verific_error_msg.empty())
|
||||
log_error("%s\n", verific_error_msg.c_str());
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
#endif /* YOSYS_ENABLE_VERIFIC */
|
||||
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
bool check_noverific_env()
|
||||
{
|
||||
const char *e = getenv("YOSYS_NOVERIFIC");
|
||||
if (e == nullptr)
|
||||
return false;
|
||||
if (atoi(e) == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct VerificPass : public Pass {
|
||||
VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { }
|
||||
virtual void help()
|
||||
|
@ -1608,6 +1693,14 @@ struct VerificPass : public Pass {
|
|||
log("Files passed to different calls to this command are treated as belonging to\n");
|
||||
log("different compilation units.\n");
|
||||
log("\n");
|
||||
log("Additional -D<macro>[=<value>] options may be added after the option indicating\n");
|
||||
log("the language version (and before file names) to set additional verilog defines.\n");
|
||||
log("The macros SYNTHESIS and VERIFIC are defined implicitly.\n");
|
||||
log("\n");
|
||||
log("\n");
|
||||
log(" verific -formal <verilog-file>..\n");
|
||||
log("\n");
|
||||
log("Like -sv, but define FORMAL instead of SYNTHESIS.\n");
|
||||
log("\n");
|
||||
log(" verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
|
||||
log("\n");
|
||||
|
@ -1627,7 +1720,12 @@ struct VerificPass : public Pass {
|
|||
log("\n");
|
||||
log(" verific -vlog-define <macro>[=<value>]..\n");
|
||||
log("\n");
|
||||
log("Add Verilog defines. (The macros SYNTHESIS and VERIFIC are defined implicitly.)\n");
|
||||
log("Add Verilog defines.\n");
|
||||
log("\n");
|
||||
log("\n");
|
||||
log(" verific -vlog-undef <macro>..\n");
|
||||
log("\n");
|
||||
log("Remove Verilog defines previously set with -vlog-define.\n");
|
||||
log("\n");
|
||||
log("\n");
|
||||
log(" verific -import [options] <top-module>..\n");
|
||||
|
@ -1684,6 +1782,9 @@ struct VerificPass : public Pass {
|
|||
#ifdef YOSYS_ENABLE_VERIFIC
|
||||
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
|
||||
{
|
||||
if (check_noverific_env())
|
||||
log_cmd_error("This version of Yosys is built without Verific support.\n");
|
||||
|
||||
log_header(design, "Executing VERIFIC (loading SystemVerilog and VHDL designs using Verific).\n");
|
||||
|
||||
Message::SetConsoleOutput(0);
|
||||
|
@ -1694,8 +1795,6 @@ struct VerificPass : public Pass {
|
|||
RuntimeFlags::SetVar("veri_extract_dualport_rams", 0);
|
||||
RuntimeFlags::SetVar("veri_extract_multiport_rams", 1);
|
||||
RuntimeFlags::SetVar("db_infer_wide_operators", 1);
|
||||
veri_file::DefineCmdLineMacro("VERIFIC");
|
||||
veri_file::DefineCmdLineMacro("SYNTHESIS");
|
||||
|
||||
verific_verbose = 0;
|
||||
|
||||
|
@ -1740,8 +1839,16 @@ struct VerificPass : public Pass {
|
|||
goto check_error;
|
||||
}
|
||||
|
||||
if (GetSize(args) > argidx && args[argidx] == "-vlog-undef") {
|
||||
for (argidx++; argidx < GetSize(args); argidx++) {
|
||||
string name = args[argidx];
|
||||
veri_file::UndefineMacro(name.c_str());
|
||||
}
|
||||
goto check_error;
|
||||
}
|
||||
|
||||
if (GetSize(args) > argidx && (args[argidx] == "-vlog95" || args[argidx] == "-vlog2k" || args[argidx] == "-sv2005" ||
|
||||
args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv"))
|
||||
args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal"))
|
||||
{
|
||||
Array file_names;
|
||||
unsigned verilog_mode;
|
||||
|
@ -1754,17 +1861,38 @@ struct VerificPass : public Pass {
|
|||
verilog_mode = veri_file::SYSTEM_VERILOG_2005;
|
||||
else if (args[argidx] == "-sv2009")
|
||||
verilog_mode = veri_file::SYSTEM_VERILOG_2009;
|
||||
else if (args[argidx] == "-sv2012" || args[argidx] == "-sv")
|
||||
else if (args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal")
|
||||
verilog_mode = veri_file::SYSTEM_VERILOG;
|
||||
else
|
||||
log_abort();
|
||||
|
||||
for (argidx++; argidx < GetSize(args); argidx++)
|
||||
file_names.Insert(args[argidx].c_str());
|
||||
veri_file::DefineMacro("VERIFIC");
|
||||
veri_file::DefineMacro(args[argidx] == "-formal" ? "FORMAL" : "SYNTHESIS");
|
||||
|
||||
for (argidx++; argidx < GetSize(args) && GetSize(args[argidx]) >= 2 && args[argidx].substr(0, 2) == "-D"; argidx++) {
|
||||
std::string name = args[argidx].substr(2);
|
||||
if (args[argidx] == "-D") {
|
||||
if (++argidx >= GetSize(args))
|
||||
break;
|
||||
name = args[argidx];
|
||||
}
|
||||
size_t equal = name.find('=');
|
||||
if (equal != std::string::npos) {
|
||||
string value = name.substr(equal+1);
|
||||
name = name.substr(0, equal);
|
||||
veri_file::DefineMacro(name.c_str(), value.c_str());
|
||||
} else {
|
||||
veri_file::DefineMacro(name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
while (argidx < GetSize(args))
|
||||
file_names.Insert(args[argidx++].c_str());
|
||||
|
||||
if (!veri_file::AnalyzeMultipleFiles(&file_names, verilog_mode, "work", veri_file::MFCU))
|
||||
log_cmd_error("Reading Verilog/SystemVerilog sources failed.\n");
|
||||
|
||||
verific_import_pending = true;
|
||||
goto check_error;
|
||||
}
|
||||
|
||||
|
@ -1773,6 +1901,7 @@ struct VerificPass : public Pass {
|
|||
for (argidx++; argidx < GetSize(args); argidx++)
|
||||
if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_87))
|
||||
log_cmd_error("Reading `%s' in VHDL_87 mode failed.\n", args[argidx].c_str());
|
||||
verific_import_pending = true;
|
||||
goto check_error;
|
||||
}
|
||||
|
||||
|
@ -1781,6 +1910,7 @@ struct VerificPass : public Pass {
|
|||
for (argidx++; argidx < GetSize(args); argidx++)
|
||||
if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_93))
|
||||
log_cmd_error("Reading `%s' in VHDL_93 mode failed.\n", args[argidx].c_str());
|
||||
verific_import_pending = true;
|
||||
goto check_error;
|
||||
}
|
||||
|
||||
|
@ -1789,6 +1919,7 @@ struct VerificPass : public Pass {
|
|||
for (argidx++; argidx < GetSize(args); argidx++)
|
||||
if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_2K))
|
||||
log_cmd_error("Reading `%s' in VHDL_2K mode failed.\n", args[argidx].c_str());
|
||||
verific_import_pending = true;
|
||||
goto check_error;
|
||||
}
|
||||
|
||||
|
@ -1797,6 +1928,7 @@ struct VerificPass : public Pass {
|
|||
for (argidx++; argidx < GetSize(args); argidx++)
|
||||
if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_2008))
|
||||
log_cmd_error("Reading `%s' in VHDL_2008 mode failed.\n", args[argidx].c_str());
|
||||
verific_import_pending = true;
|
||||
goto check_error;
|
||||
}
|
||||
|
||||
|
@ -2007,6 +2139,7 @@ struct VerificPass : public Pass {
|
|||
veri_file::Reset();
|
||||
vhdl_file::Reset();
|
||||
Libset::Reset();
|
||||
verific_import_pending = false;
|
||||
goto check_error;
|
||||
}
|
||||
|
||||
|
@ -2024,5 +2157,114 @@ struct VerificPass : public Pass {
|
|||
#endif
|
||||
} VerificPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
struct ReadPass : public Pass {
|
||||
ReadPass() : Pass("read", "load HDL designs") { }
|
||||
virtual void help()
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" read {-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv|-formal} <verilog-file>..\n");
|
||||
log("\n");
|
||||
log("Load the specified Verilog/SystemVerilog files. (Full SystemVerilog support\n");
|
||||
log("is only available via Verific.)\n");
|
||||
log("\n");
|
||||
log("Additional -D<macro>[=<value>] options may be added after the option indicating\n");
|
||||
log("the language version (and before file names) to set additional verilog defines.\n");
|
||||
log("\n");
|
||||
log("\n");
|
||||
log(" read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
|
||||
log("\n");
|
||||
log("Load the specified VHDL files. (Requires Verific.)\n");
|
||||
log("\n");
|
||||
log("\n");
|
||||
log(" read -define <macro>[=<value>]..\n");
|
||||
log("\n");
|
||||
log("Set global Verilog/SystemVerilog defines.\n");
|
||||
log("\n");
|
||||
log("\n");
|
||||
log(" read -undef <macro>..\n");
|
||||
log("\n");
|
||||
log("Unset global Verilog/SystemVerilog defines.\n");
|
||||
log("\n");
|
||||
}
|
||||
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
|
||||
{
|
||||
if (args.size() < 2)
|
||||
log_cmd_error("Missing mode parameter.\n");
|
||||
|
||||
if (args.size() < 3)
|
||||
log_cmd_error("Missing file name parameter.\n");
|
||||
|
||||
#ifdef YOSYS_ENABLE_VERIFIC
|
||||
bool use_verific = !check_noverific_env();
|
||||
#else
|
||||
bool use_verific = false;
|
||||
#endif
|
||||
|
||||
if (args[1] == "-vlog95" || args[1] == "-vlog2k") {
|
||||
if (use_verific) {
|
||||
args[0] = "verific";
|
||||
} else {
|
||||
args[0] = "read_verilog";
|
||||
args.erase(args.begin()+1, args.begin()+2);
|
||||
}
|
||||
Pass::call(design, args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[1] == "-sv2005" || args[1] == "-sv2009" || args[1] == "-sv2012" || args[1] == "-sv" || args[1] == "-formal") {
|
||||
if (use_verific) {
|
||||
args[0] = "verific";
|
||||
} else {
|
||||
args[0] = "read_verilog";
|
||||
if (args[1] == "-formal")
|
||||
args.insert(args.begin()+1, std::string());
|
||||
args[1] = "-sv";
|
||||
}
|
||||
Pass::call(design, args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[1] == "-vhdl87" || args[1] == "-vhdl93" || args[1] == "-vhdl2k" || args[1] == "-vhdl2008" || args[1] == "-vhdl") {
|
||||
if (use_verific) {
|
||||
args[0] = "verific";
|
||||
Pass::call(design, args);
|
||||
} else {
|
||||
log_cmd_error("This version of Yosys is built without Verific support.\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[1] == "-define") {
|
||||
if (use_verific) {
|
||||
args[0] = "verific";
|
||||
args[1] = "-vlog-define";
|
||||
Pass::call(design, args);
|
||||
}
|
||||
args[0] = "verilog_defines";
|
||||
args.erase(args.begin()+1, args.begin()+2);
|
||||
for (int i = 1; i < GetSize(args); i++)
|
||||
args[i] = "-D" + args[i];
|
||||
Pass::call(design, args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[1] == "-undef") {
|
||||
if (use_verific) {
|
||||
args[0] = "verific";
|
||||
args[1] = "-vlog-undef";
|
||||
Pass::call(design, args);
|
||||
}
|
||||
args[0] = "verilog_defines";
|
||||
args.erase(args.begin()+1, args.begin()+2);
|
||||
for (int i = 1; i < GetSize(args); i++)
|
||||
args[i] = "-U" + args[i];
|
||||
Pass::call(design, args);
|
||||
return;
|
||||
}
|
||||
|
||||
log_cmd_error("Missing or unsupported mode parameter.\n");
|
||||
}
|
||||
} ReadPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
|
|
|
@ -25,6 +25,9 @@ YOSYS_NAMESPACE_BEGIN
|
|||
|
||||
extern int verific_verbose;
|
||||
|
||||
extern bool verific_import_pending;
|
||||
extern void verific_import(Design *design, std::string top = std::string());
|
||||
|
||||
extern pool<int> verific_sva_prims;
|
||||
|
||||
struct VerificImporter;
|
||||
|
@ -40,6 +43,7 @@ struct VerificClocking {
|
|||
SigBit enable_sig = State::S1;
|
||||
SigBit disable_sig = State::S0;
|
||||
bool posedge = true;
|
||||
bool gclk = false;
|
||||
|
||||
VerificClocking() { }
|
||||
VerificClocking(VerificImporter *importer, Verific::Net *net, bool sva_at_only = false);
|
||||
|
@ -65,6 +69,7 @@ struct VerificImporter
|
|||
|
||||
std::map<Verific::Net*, RTLIL::SigBit> net_map;
|
||||
std::map<Verific::Net*, Verific::Net*> sva_posedge_map;
|
||||
pool<Verific::Net*, hash_ptr_ops> any_all_nets;
|
||||
|
||||
bool mode_gates, mode_keep, mode_nosva, mode_names, mode_verific;
|
||||
bool mode_autocover;
|
||||
|
@ -79,7 +84,7 @@ struct VerificImporter
|
|||
RTLIL::SigSpec operatorInput1(Verific::Instance *inst);
|
||||
RTLIL::SigSpec operatorInput2(Verific::Instance *inst);
|
||||
RTLIL::SigSpec operatorInport(Verific::Instance *inst, const char *portname);
|
||||
RTLIL::SigSpec operatorOutput(Verific::Instance *inst);
|
||||
RTLIL::SigSpec operatorOutput(Verific::Instance *inst, const pool<Verific::Net*, hash_ptr_ops> *any_all_nets = nullptr);
|
||||
|
||||
bool import_netlist_instance_gates(Verific::Instance *inst, RTLIL::IdString inst_name);
|
||||
bool import_netlist_instance_cells(Verific::Instance *inst, RTLIL::IdString inst_name);
|
||||
|
|
|
@ -980,7 +980,6 @@ struct VerificSvaImporter
|
|||
bool mode_assume = false;
|
||||
bool mode_cover = false;
|
||||
bool mode_trigger = false;
|
||||
bool eventually = false;
|
||||
|
||||
Instance *net_to_ast_driver(Net *n)
|
||||
{
|
||||
|
@ -1487,6 +1486,70 @@ struct VerificSvaImporter
|
|||
fsm.getFirstAcceptReject(accept_p, reject_p);
|
||||
}
|
||||
|
||||
bool eventually_property(Net *&net, SigBit &trig)
|
||||
{
|
||||
Instance *inst = net_to_ast_driver(net);
|
||||
|
||||
if (inst == nullptr)
|
||||
return false;
|
||||
|
||||
if (clocking.cond_net != nullptr)
|
||||
trig = importer->net_map_at(clocking.cond_net);
|
||||
else
|
||||
trig = State::S1;
|
||||
|
||||
if (inst->Type() == PRIM_SVA_S_EVENTUALLY || inst->Type() == PRIM_SVA_EVENTUALLY)
|
||||
{
|
||||
if (mode_cover || mode_trigger)
|
||||
parser_error(inst);
|
||||
|
||||
net = inst->GetInput();
|
||||
clocking.cond_net = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (inst->Type() == PRIM_SVA_OVERLAPPED_IMPLICATION ||
|
||||
inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION)
|
||||
{
|
||||
Net *antecedent_net = inst->GetInput1();
|
||||
Net *consequent_net = inst->GetInput2();
|
||||
|
||||
Instance *consequent_inst = net_to_ast_driver(consequent_net);
|
||||
|
||||
if (consequent_inst->Type() != PRIM_SVA_S_EVENTUALLY && consequent_inst->Type() != PRIM_SVA_EVENTUALLY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode_cover || mode_trigger)
|
||||
parser_error(consequent_inst);
|
||||
|
||||
int node;
|
||||
|
||||
SvaFsm antecedent_fsm(clocking, trig);
|
||||
node = parse_sequence(antecedent_fsm, antecedent_fsm.createStartNode(), antecedent_net);
|
||||
if (inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION) {
|
||||
int next_node = antecedent_fsm.createNode();
|
||||
antecedent_fsm.createEdge(node, next_node);
|
||||
node = next_node;
|
||||
}
|
||||
antecedent_fsm.createLink(node, antecedent_fsm.acceptNode);
|
||||
|
||||
trig = antecedent_fsm.getAccept();
|
||||
net = consequent_inst->GetInput();
|
||||
clocking.cond_net = nullptr;
|
||||
|
||||
if (verific_verbose) {
|
||||
log(" Eventually Antecedent FSM:\n");
|
||||
antecedent_fsm.dump();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void parse_property(Net *net, SigBit *accept_p, SigBit *reject_p)
|
||||
{
|
||||
Instance *inst = net_to_ast_driver(net);
|
||||
|
@ -1620,10 +1683,46 @@ struct VerificSvaImporter
|
|||
}
|
||||
else
|
||||
{
|
||||
if (mode_assert || mode_assume) {
|
||||
parse_property(clocking.body_net, nullptr, &reject_bit);
|
||||
} else {
|
||||
parse_property(clocking.body_net, &accept_bit, nullptr);
|
||||
Net *net = clocking.body_net;
|
||||
SigBit trig;
|
||||
|
||||
if (eventually_property(net, trig))
|
||||
{
|
||||
SigBit sig_a, sig_en = trig;
|
||||
parse_property(net, &sig_a, nullptr);
|
||||
|
||||
// add final FF stage
|
||||
|
||||
SigBit sig_a_q, sig_en_q;
|
||||
|
||||
if (clocking.body_net == nullptr) {
|
||||
sig_a_q = sig_a;
|
||||
sig_en_q = sig_en;
|
||||
} else {
|
||||
sig_a_q = module->addWire(NEW_ID);
|
||||
sig_en_q = module->addWire(NEW_ID);
|
||||
clocking.addDff(NEW_ID, sig_a, sig_a_q, State::S0);
|
||||
clocking.addDff(NEW_ID, sig_en, sig_en_q, State::S0);
|
||||
}
|
||||
|
||||
// generate fair/live cell
|
||||
|
||||
RTLIL::Cell *c = nullptr;
|
||||
|
||||
if (mode_assert) c = module->addLive(root_name, sig_a_q, sig_en_q);
|
||||
if (mode_assume) c = module->addFair(root_name, sig_a_q, sig_en_q);
|
||||
|
||||
importer->import_attributes(c->attributes, root);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode_assert || mode_assume) {
|
||||
parse_property(net, nullptr, &reject_bit);
|
||||
} else {
|
||||
parse_property(net, &accept_bit, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -183,8 +183,9 @@ static std::string next_token(bool pass_newline = false)
|
|||
const char *ok = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789";
|
||||
if (ch == '`' || strchr(ok, ch) != NULL)
|
||||
{
|
||||
char first = ch;
|
||||
ch = next_char();
|
||||
if (ch == '"') {
|
||||
if (first == '`' && (ch == '"' || ch == '`')) {
|
||||
token += ch;
|
||||
} else do {
|
||||
if (strchr(ok, ch) == NULL) {
|
||||
|
@ -244,6 +245,7 @@ static bool try_expand_macro(std::set<std::string> &defines_with_args,
|
|||
args.push_back(std::string());
|
||||
while (1)
|
||||
{
|
||||
skip_spaces();
|
||||
tok = next_token(true);
|
||||
if (tok == ")" || tok == "}" || tok == "]")
|
||||
level--;
|
||||
|
@ -264,6 +266,9 @@ static bool try_expand_macro(std::set<std::string> &defines_with_args,
|
|||
}
|
||||
insert_input(defines_map[name]);
|
||||
return true;
|
||||
} else if (tok == "``") {
|
||||
// Swallow `` in macro expansion
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,20 +85,37 @@ USING_YOSYS_NAMESPACE
|
|||
#ifdef EMSCRIPTEN
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h>
|
||||
# include <emscripten.h>
|
||||
|
||||
extern "C" int main(int, char**);
|
||||
extern "C" void run(const char*);
|
||||
extern "C" const char *errmsg();
|
||||
extern "C" const char *prompt();
|
||||
|
||||
int main(int, char**)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
EM_ASM(
|
||||
if (ENVIRONMENT_IS_NODE)
|
||||
{
|
||||
FS.mkdir('/hostcwd');
|
||||
FS.mount(NODEFS, { root: '.' }, '/hostcwd');
|
||||
FS.mkdir('/hostfs');
|
||||
FS.mount(NODEFS, { root: '/' }, '/hostfs');
|
||||
}
|
||||
);
|
||||
|
||||
mkdir("/work", 0777);
|
||||
chdir("/work");
|
||||
log_files.push_back(stdout);
|
||||
log_error_stderr = true;
|
||||
yosys_banner();
|
||||
yosys_setup();
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
// Run the first argument as a script file
|
||||
run_frontend(argv[1], "script", 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void run(const char *command)
|
||||
|
|
|
@ -739,7 +739,7 @@ std::string proc_self_dirname()
|
|||
#ifdef EMSCRIPTEN
|
||||
std::string proc_share_dirname()
|
||||
{
|
||||
return "/share";
|
||||
return "/share/";
|
||||
}
|
||||
#else
|
||||
std::string proc_share_dirname()
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
//
|
||||
// yosys -- Yosys Open SYnthesis Suite
|
||||
//
|
||||
// Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
/// Protobuf definition of Yosys RTLIL dump/restore format for RTL designs.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package yosys.pb;
|
||||
|
||||
// Port direction.
|
||||
enum Direction {
|
||||
DIRECTION_INVALID = 0;
|
||||
DIRECTION_INPUT = 1;
|
||||
DIRECTION_OUTPUT = 2;
|
||||
DIRECTION_INOUT = 3;
|
||||
}
|
||||
|
||||
// A freeform parameter/attribute value.
|
||||
message Parameter {
|
||||
oneof value {
|
||||
int64 int = 1;
|
||||
string str = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// A signal in the design - either a unique identifier for one, or a constant
|
||||
// driver (low or high).
|
||||
message Signal {
|
||||
// A constant signal driver in the design.
|
||||
enum ConstantDriver {
|
||||
CONSTANT_DRIVER_INVALID = 0;
|
||||
CONSTANT_DRIVER_LOW = 1;
|
||||
CONSTANT_DRIVER_HIGH = 2;
|
||||
CONSTANT_DRIVER_Z = 3;
|
||||
CONSTANT_DRIVER_X = 4;
|
||||
}
|
||||
oneof type {
|
||||
// Signal uniquely identified by ID number.
|
||||
int64 id = 1;
|
||||
// Constant driver.
|
||||
ConstantDriver constant = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// A vector of signals.
|
||||
message BitVector {
|
||||
repeated Signal signal = 1;
|
||||
}
|
||||
|
||||
// A netlist module.
|
||||
message Module {
|
||||
// Freeform attributes.
|
||||
map<string, Parameter> attribute = 1;
|
||||
|
||||
// Named ports in this module.
|
||||
message Port {
|
||||
Direction direction = 1;
|
||||
BitVector bits = 2;
|
||||
}
|
||||
map<string, Port> port = 2;
|
||||
|
||||
// Named cells in this module.
|
||||
message Cell {
|
||||
// Set to true when the name of this cell is automatically created and
|
||||
// likely not of interest for a regular user.
|
||||
bool hide_name = 1;
|
||||
string type = 2;
|
||||
// Set if this module has an AIG model available.
|
||||
string model = 3;
|
||||
// Freeform parameters.
|
||||
map<string, Parameter> parameter = 4;
|
||||
// Freeform attributes.
|
||||
map<string, Parameter> attribute = 5;
|
||||
|
||||
/// Ports of the cell.
|
||||
// Direction of the port, if interface is known.
|
||||
map<string, Direction> port_direction = 6;
|
||||
// Connection of named port to signal(s).
|
||||
map<string, BitVector> connection = 7;
|
||||
}
|
||||
map<string, Cell> cell = 3;
|
||||
|
||||
// Nets in this module.
|
||||
message Netname {
|
||||
// Set to true when the name of this net is automatically created and
|
||||
// likely not of interest for a regular user.
|
||||
bool hide_name = 1;
|
||||
// Signal(s) that make up this net.
|
||||
BitVector bits = 2;
|
||||
// Freeform attributes.
|
||||
map<string, Parameter> attributes = 3;
|
||||
}
|
||||
repeated Netname netname = 4;
|
||||
}
|
||||
|
||||
// And-Inverter-Graph model.
|
||||
message Model {
|
||||
message Node {
|
||||
// Type of AIG node - or, what its' value is.
|
||||
enum Type {
|
||||
TYPE_INVALID = 0;
|
||||
// The node's value is the value of the specified input port bit.
|
||||
TYPE_PORT = 1;
|
||||
// The node's value is the inverted value of the specified input
|
||||
// port bit.
|
||||
TYPE_NPORT = 2;
|
||||
// The node's value is the ANDed value of specified nodes.
|
||||
TYPE_AND = 3;
|
||||
// The node's value is the NANDed value of specified nodes.
|
||||
TYPE_NAND = 4;
|
||||
// The node's value is a constant 1.
|
||||
TYPE_TRUE = 5;
|
||||
// The node's value is a constant 0.
|
||||
TYPE_FALSE = 6;
|
||||
};
|
||||
Type type = 1;
|
||||
|
||||
message Port {
|
||||
// Name of port.
|
||||
string portname = 1;
|
||||
// Bit index in port.
|
||||
int64 bitindex = 2;
|
||||
}
|
||||
message Gate {
|
||||
// Node index of left side of operation.
|
||||
int64 left = 1;
|
||||
// Node index of right side of operation.
|
||||
int64 right = 2;
|
||||
}
|
||||
oneof node {
|
||||
// Set for PORT, NPORT
|
||||
Port port = 2;
|
||||
// Set for AND, NAND.
|
||||
Gate gate = 3;
|
||||
}
|
||||
|
||||
// Set when the node drives given output port(s).
|
||||
message OutPort {
|
||||
// Name of port.
|
||||
string name = 1;
|
||||
// Bit index in port.
|
||||
int64 bit_index = 2;
|
||||
}
|
||||
repeated OutPort out_port = 4;
|
||||
}
|
||||
|
||||
// List of AIG nodes - each is explicitely numbered by its' index in this
|
||||
// array.
|
||||
repeated Node node = 1;
|
||||
}
|
||||
|
||||
// A Yosys design netlist dumped from RTLIL.
|
||||
message Design {
|
||||
// Human-readable freeform 'remark' string.
|
||||
string creator = 1;
|
||||
// List of named modules in design.
|
||||
map<string, Module> modules = 2;
|
||||
// List of named AIG models in design (if AIG export enabled).
|
||||
map<string, Model> models = 3;
|
||||
}
|
|
@ -23,6 +23,13 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/log.h"
|
||||
|
||||
#define MODE_ZERO 0
|
||||
#define MODE_ONE 1
|
||||
#define MODE_UNDEF 2
|
||||
#define MODE_RANDOM 3
|
||||
#define MODE_ANYSEQ 4
|
||||
#define MODE_ANYCONST 5
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -97,30 +104,32 @@ struct SetundefWorker
|
|||
|
||||
RTLIL::State next_bit()
|
||||
{
|
||||
if (next_bit_mode == 0)
|
||||
if (next_bit_mode == MODE_ZERO)
|
||||
return RTLIL::State::S0;
|
||||
|
||||
if (next_bit_mode == 1)
|
||||
if (next_bit_mode == MODE_ONE)
|
||||
return RTLIL::State::S1;
|
||||
|
||||
if (next_bit_mode == 2)
|
||||
log_abort();
|
||||
|
||||
if (next_bit_mode == 4)
|
||||
if (next_bit_mode == MODE_UNDEF)
|
||||
return RTLIL::State::Sx;
|
||||
|
||||
// xorshift32
|
||||
next_bit_state ^= next_bit_state << 13;
|
||||
next_bit_state ^= next_bit_state >> 17;
|
||||
next_bit_state ^= next_bit_state << 5;
|
||||
log_assert(next_bit_state != 0);
|
||||
if (next_bit_mode == MODE_RANDOM)
|
||||
{
|
||||
// xorshift32
|
||||
next_bit_state ^= next_bit_state << 13;
|
||||
next_bit_state ^= next_bit_state >> 17;
|
||||
next_bit_state ^= next_bit_state << 5;
|
||||
log_assert(next_bit_state != 0);
|
||||
|
||||
return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1;
|
||||
return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1;
|
||||
}
|
||||
|
||||
log_abort();
|
||||
}
|
||||
|
||||
void operator()(RTLIL::SigSpec &sig)
|
||||
{
|
||||
if (next_bit_mode == 2) {
|
||||
if (next_bit_mode == MODE_ANYSEQ || next_bit_mode == MODE_ANYCONST) {
|
||||
siglist.push_back(&sig);
|
||||
return;
|
||||
}
|
||||
|
@ -145,7 +154,7 @@ struct SetundefPass : public Pass {
|
|||
log(" also set undriven nets to constant values\n");
|
||||
log("\n");
|
||||
log(" -expose\n");
|
||||
log(" also expose undriven nets as inputs\n");
|
||||
log(" also expose undriven nets as inputs (use with -undriven)\n");
|
||||
log("\n");
|
||||
log(" -zero\n");
|
||||
log(" replace with bits cleared (0)\n");
|
||||
|
@ -159,6 +168,9 @@ struct SetundefPass : public Pass {
|
|||
log(" -anyseq\n");
|
||||
log(" replace with $anyseq drivers (for formal)\n");
|
||||
log("\n");
|
||||
log(" -anyconst\n");
|
||||
log(" replace with $anyconst drivers (for formal)\n");
|
||||
log("\n");
|
||||
log(" -random <seed>\n");
|
||||
log(" replace with random bits using the specified integer als seed\n");
|
||||
log(" value for the random number generator.\n");
|
||||
|
@ -191,25 +203,31 @@ struct SetundefPass : public Pass {
|
|||
}
|
||||
if (args[argidx] == "-zero") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 0;
|
||||
worker.next_bit_mode = MODE_ZERO;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-one") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 1;
|
||||
worker.next_bit_mode = MODE_ONE;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-anyseq") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 2;
|
||||
worker.next_bit_mode = MODE_ANYSEQ;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-anyconst") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = MODE_ANYCONST;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-undef") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 4;
|
||||
worker.next_bit_mode = MODE_UNDEF;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
|
@ -219,7 +237,7 @@ struct SetundefPass : public Pass {
|
|||
}
|
||||
if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 3;
|
||||
worker.next_bit_mode = MODE_RANDOM;
|
||||
worker.next_bit_state = atoi(args[++argidx].c_str()) + 1;
|
||||
for (int i = 0; i < 10; i++)
|
||||
worker.next_bit();
|
||||
|
@ -232,7 +250,10 @@ struct SetundefPass : public Pass {
|
|||
if (expose_mode && !undriven_mode)
|
||||
log_cmd_error("Option -expose must be used with option -undriven.\n");
|
||||
if (!got_value)
|
||||
log_cmd_error("One of the options -zero, -one, -anyseq, or -random <seed> must be specified.\n");
|
||||
log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, or -random <seed> must be specified.\n");
|
||||
|
||||
if (init_mode && (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST))
|
||||
log_cmd_error("The options -init and -anyseq / -anyconst are exclusive.\n");
|
||||
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
|
@ -419,7 +440,7 @@ struct SetundefPass : public Pass {
|
|||
|
||||
module->rewrite_sigspecs(worker);
|
||||
|
||||
if (worker.next_bit_mode == 2)
|
||||
if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)
|
||||
{
|
||||
vector<SigSpec*> siglist;
|
||||
siglist.swap(worker.siglist);
|
||||
|
@ -436,7 +457,10 @@ struct SetundefPass : public Pass {
|
|||
width++;
|
||||
|
||||
if (width > 0) {
|
||||
sig.replace(cursor, module->Anyseq(NEW_ID, width));
|
||||
if (worker.next_bit_mode == MODE_ANYSEQ)
|
||||
sig.replace(cursor, module->Anyseq(NEW_ID, width));
|
||||
else
|
||||
sig.replace(cursor, module->Anyconst(NEW_ID, width));
|
||||
cursor += width;
|
||||
} else {
|
||||
cursor++;
|
||||
|
|
|
@ -142,7 +142,7 @@ struct statdata_t
|
|||
}
|
||||
}
|
||||
|
||||
void log_data()
|
||||
void log_data(RTLIL::IdString mod_name, bool top_mod)
|
||||
{
|
||||
log(" Number of wires: %6d\n", num_wires);
|
||||
log(" Number of wire bits: %6d\n", num_wire_bits);
|
||||
|
@ -163,7 +163,7 @@ struct statdata_t
|
|||
|
||||
if (area != 0) {
|
||||
log("\n");
|
||||
log(" Chip area for this module: %f\n", area);
|
||||
log(" Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -275,7 +275,7 @@ struct StatPass : public Pass {
|
|||
log("\n");
|
||||
log("=== %s%s ===\n", RTLIL::id2cstr(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)");
|
||||
log("\n");
|
||||
data.log_data();
|
||||
data.log_data(mod->name, false);
|
||||
}
|
||||
|
||||
if (top_mod != NULL && GetSize(mod_stat) > 1)
|
||||
|
@ -288,7 +288,7 @@ struct StatPass : public Pass {
|
|||
statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0);
|
||||
|
||||
log("\n");
|
||||
data.log_data();
|
||||
data.log_data(top_mod->name, true);
|
||||
}
|
||||
|
||||
log("\n");
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
#include "frontends/verific/verific.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <set>
|
||||
|
@ -258,7 +259,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
|||
if (mod->wires_.count(portname) == 0)
|
||||
log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first));
|
||||
int port_size = mod->wires_.at(portname)->width;
|
||||
if (conn_size == port_size)
|
||||
if (conn_size == port_size || conn_size == 0)
|
||||
continue;
|
||||
if (conn_size != port_size*num)
|
||||
log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first));
|
||||
|
@ -421,6 +422,7 @@ struct HierarchyPass : public Pass {
|
|||
bool flag_simcheck = false;
|
||||
bool purge_lib = false;
|
||||
RTLIL::Module *top_mod = NULL;
|
||||
std::string load_top_mod;
|
||||
std::vector<std::string> libdirs;
|
||||
|
||||
bool auto_top_mode = false;
|
||||
|
@ -511,7 +513,7 @@ struct HierarchyPass : public Pass {
|
|||
top_mod = design->modules_.count(RTLIL::escape_id(args[argidx])) ? design->modules_.at(RTLIL::escape_id(args[argidx])) : NULL;
|
||||
}
|
||||
if (top_mod == NULL)
|
||||
log_cmd_error("Module `%s' not found!\n", args[argidx].c_str());
|
||||
load_top_mod = args[argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-auto-top") {
|
||||
|
@ -522,6 +524,22 @@ struct HierarchyPass : public Pass {
|
|||
}
|
||||
extra_args(args, argidx, design, false);
|
||||
|
||||
if (!load_top_mod.empty()) {
|
||||
#ifdef YOSYS_ENABLE_VERIFIC
|
||||
if (verific_import_pending) {
|
||||
verific_import(design, load_top_mod);
|
||||
top_mod = design->module(RTLIL::escape_id(load_top_mod));
|
||||
}
|
||||
#endif
|
||||
if (top_mod == NULL)
|
||||
log_cmd_error("Module `%s' not found!\n", load_top_mod.c_str());
|
||||
} else {
|
||||
#ifdef YOSYS_ENABLE_VERIFIC
|
||||
if (verific_import_pending)
|
||||
verific_import(design);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (generate_mode) {
|
||||
generate(design, generate_cells, generate_ports);
|
||||
return;
|
||||
|
|
|
@ -33,8 +33,20 @@ struct MemoryDffWorker
|
|||
dict<SigBit, int> sigbit_users_count;
|
||||
dict<SigSpec, Cell*> mux_cells_a, mux_cells_b;
|
||||
pool<Cell*> forward_merged_dffs, candidate_dffs;
|
||||
pool<SigBit> init_bits;
|
||||
|
||||
MemoryDffWorker(Module *module) : module(module), sigmap(module) { }
|
||||
MemoryDffWorker(Module *module) : module(module), sigmap(module)
|
||||
{
|
||||
for (auto wire : module->wires()) {
|
||||
if (wire->attributes.count("\\init") == 0)
|
||||
continue;
|
||||
SigSpec sig = sigmap(wire);
|
||||
Const initval = wire->attributes.count("\\init");
|
||||
for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++)
|
||||
if (initval[i] == State::S0 || initval[i] == State::S1)
|
||||
init_bits.insert(sig[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool find_sig_before_dff(RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity, bool after = false)
|
||||
{
|
||||
|
@ -45,6 +57,9 @@ struct MemoryDffWorker
|
|||
if (bit.wire == NULL)
|
||||
continue;
|
||||
|
||||
if (!after && init_bits.count(sigmap(bit)))
|
||||
return false;
|
||||
|
||||
for (auto cell : dff_cells)
|
||||
{
|
||||
if (after && forward_merged_dffs.count(cell))
|
||||
|
@ -72,6 +87,9 @@ struct MemoryDffWorker
|
|||
if (d.size() != 1)
|
||||
continue;
|
||||
|
||||
if (after && init_bits.count(d))
|
||||
return false;
|
||||
|
||||
bit = d;
|
||||
clk = this_clk;
|
||||
clk_polarity = this_clk_polarity;
|
||||
|
|
|
@ -61,49 +61,59 @@ struct MemoryNordffPass : public Pass {
|
|||
|
||||
SigSpec rd_addr = cell->getPort("\\RD_ADDR");
|
||||
SigSpec rd_data = cell->getPort("\\RD_DATA");
|
||||
SigSpec rd_clk = cell->getPort("\\RD_CLK");
|
||||
SigSpec rd_en = cell->getPort("\\RD_EN");
|
||||
Const rd_clk_enable = cell->getParam("\\RD_CLK_ENABLE");
|
||||
Const rd_clk_polarity = cell->getParam("\\RD_CLK_POLARITY");
|
||||
|
||||
for (int i = 0; i < rd_ports; i++)
|
||||
{
|
||||
bool clk_enable = rd_clk_enable[i] == State::S1;
|
||||
|
||||
if (!clk_enable)
|
||||
continue;
|
||||
|
||||
bool clk_polarity = cell->getParam("\\RD_CLK_POLARITY")[i] == State::S1;
|
||||
bool transparent = cell->getParam("\\RD_TRANSPARENT")[i] == State::S1;
|
||||
|
||||
SigSpec clk = cell->getPort("\\RD_CLK")[i] ;
|
||||
SigSpec en = cell->getPort("\\RD_EN")[i];
|
||||
Cell *c;
|
||||
|
||||
if (transparent)
|
||||
if (clk_enable)
|
||||
{
|
||||
SigSpec sig_q = module->addWire(NEW_ID, abits);
|
||||
SigSpec sig_d = rd_addr.extract(abits * i, abits);
|
||||
rd_addr.replace(abits * i, sig_q);
|
||||
if (en != State::S1)
|
||||
sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
|
||||
c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
|
||||
}
|
||||
else
|
||||
{
|
||||
SigSpec sig_d = module->addWire(NEW_ID, width);
|
||||
SigSpec sig_q = rd_data.extract(width * i, width);
|
||||
rd_data.replace(width *i, sig_d);
|
||||
if (en != State::S1)
|
||||
sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
|
||||
c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
|
||||
bool clk_polarity = cell->getParam("\\RD_CLK_POLARITY")[i] == State::S1;
|
||||
bool transparent = cell->getParam("\\RD_TRANSPARENT")[i] == State::S1;
|
||||
|
||||
SigSpec clk = cell->getPort("\\RD_CLK")[i] ;
|
||||
SigSpec en = cell->getPort("\\RD_EN")[i];
|
||||
Cell *c;
|
||||
|
||||
if (transparent)
|
||||
{
|
||||
SigSpec sig_q = module->addWire(NEW_ID, abits);
|
||||
SigSpec sig_d = rd_addr.extract(abits * i, abits);
|
||||
rd_addr.replace(abits * i, sig_q);
|
||||
if (en != State::S1)
|
||||
sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
|
||||
c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
|
||||
}
|
||||
else
|
||||
{
|
||||
SigSpec sig_d = module->addWire(NEW_ID, width);
|
||||
SigSpec sig_q = rd_data.extract(width * i, width);
|
||||
rd_data.replace(width *i, sig_d);
|
||||
if (en != State::S1)
|
||||
sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
|
||||
c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
|
||||
}
|
||||
|
||||
log("Extracted %s FF from read port %d of %s.%s: %s\n", transparent ? "addr" : "data",
|
||||
i, log_id(module), log_id(cell), log_id(c));
|
||||
}
|
||||
|
||||
log("Extracted %s FF from read port %d of %s.%s: %s\n", transparent ? "addr" : "data",
|
||||
i, log_id(module), log_id(cell), log_id(c));
|
||||
rd_en[i] = State::S1;
|
||||
rd_clk[i] = State::S0;
|
||||
rd_clk_enable[i] = State::S0;
|
||||
rd_clk_polarity[i] = State::S1;
|
||||
}
|
||||
|
||||
cell->setPort("\\RD_ADDR", rd_addr);
|
||||
cell->setPort("\\RD_DATA", rd_data);
|
||||
cell->setPort("\\RD_CLK", rd_clk);
|
||||
cell->setPort("\\RD_EN", rd_en);
|
||||
cell->setParam("\\RD_CLK_ENABLE", rd_clk_enable);
|
||||
cell->setParam("\\RD_CLK_POLARITY", rd_clk_polarity);
|
||||
}
|
||||
}
|
||||
} MemoryNordffPass;
|
||||
|
|
|
@ -60,6 +60,10 @@
|
|||
|
||||
#include "frontends/blif/blifparse.h"
|
||||
|
||||
#ifdef YOSYS_LINK_ABC
|
||||
extern "C" int Abc_RealMain(int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -546,11 +550,13 @@ std::string replace_tempdir(std::string text, std::string tempdir_name, bool sho
|
|||
}
|
||||
|
||||
std::string selfdir_name = proc_self_dirname();
|
||||
while (1) {
|
||||
size_t pos = text.find(selfdir_name);
|
||||
if (pos == std::string::npos)
|
||||
break;
|
||||
text = text.substr(0, pos) + "<yosys-exe-dir>/" + text.substr(pos + GetSize(selfdir_name));
|
||||
if (selfdir_name != "/") {
|
||||
while (1) {
|
||||
size_t pos = text.find(selfdir_name);
|
||||
if (pos == std::string::npos)
|
||||
break;
|
||||
text = text.substr(0, pos) + "<yosys-exe-dir>/" + text.substr(pos + GetSize(selfdir_name));
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
|
@ -943,8 +949,24 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
|||
buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str());
|
||||
log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str());
|
||||
|
||||
#ifndef YOSYS_LINK_ABC
|
||||
abc_output_filter filt(tempdir_name, show_tempdir);
|
||||
int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1));
|
||||
#else
|
||||
// These needs to be mutable, supposedly due to getopt
|
||||
char *abc_argv[5];
|
||||
string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str());
|
||||
abc_argv[0] = strdup(exe_file.c_str());
|
||||
abc_argv[1] = strdup("-s");
|
||||
abc_argv[2] = strdup("-f");
|
||||
abc_argv[3] = strdup(tmp_script_name.c_str());
|
||||
abc_argv[4] = 0;
|
||||
int ret = Abc_RealMain(4, abc_argv);
|
||||
free(abc_argv[0]);
|
||||
free(abc_argv[1]);
|
||||
free(abc_argv[2]);
|
||||
free(abc_argv[3]);
|
||||
#endif
|
||||
if (ret != 0)
|
||||
log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ struct DeminoutPass : public Pass {
|
|||
for (auto module : design->selected_modules())
|
||||
{
|
||||
SigMap sigmap(module);
|
||||
pool<SigBit> bits_written, bits_used, bits_inout;
|
||||
pool<SigBit> bits_written, bits_used, bits_inout, bits_tribuf;
|
||||
dict<SigBit, int> bits_numports;
|
||||
|
||||
for (auto wire : module->wires())
|
||||
|
@ -82,6 +82,25 @@ struct DeminoutPass : public Pass {
|
|||
if (cellport_in)
|
||||
for (auto bit : sigmap(conn.second))
|
||||
bits_used.insert(bit);
|
||||
|
||||
if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_"))
|
||||
{
|
||||
bool tribuf = (cell->type == "$_TBUF_");
|
||||
|
||||
if (!tribuf) {
|
||||
for (auto &c : cell->connections()) {
|
||||
if (!c.first.in("\\A", "\\B"))
|
||||
continue;
|
||||
for (auto b : sigmap(c.second))
|
||||
if (b == State::Sz)
|
||||
tribuf = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tribuf)
|
||||
for (auto bit : sigmap(conn.second))
|
||||
bits_tribuf.insert(bit);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto wire : module->selected_wires())
|
||||
|
@ -95,10 +114,15 @@ struct DeminoutPass : public Pass {
|
|||
if (bits_numports[bit] > 1 || bits_inout.count(bit))
|
||||
new_input = true, new_output = true;
|
||||
|
||||
if (bits_written.count(bit))
|
||||
if (bits_written.count(bit)) {
|
||||
new_output = true;
|
||||
else if (bits_used.count(bit))
|
||||
new_input = true;
|
||||
if (bits_tribuf.count(bit))
|
||||
goto tribuf_bit;
|
||||
} else {
|
||||
tribuf_bit:
|
||||
if (bits_used.count(bit))
|
||||
new_input = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_input != new_output) {
|
||||
|
|
|
@ -146,11 +146,37 @@ struct IopadmapPass : public Pass {
|
|||
for (auto module : design->selected_modules())
|
||||
{
|
||||
dict<IdString, pool<int>> skip_wires;
|
||||
pool<SigBit> skip_wire_bits;
|
||||
SigMap sigmap(module);
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type == RTLIL::escape_id(inpad_celltype) && cell->hasPort(RTLIL::escape_id(inpad_portname2)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inpad_portname2))))
|
||||
skip_wire_bits.insert(bit);
|
||||
|
||||
if (cell->type == RTLIL::escape_id(outpad_celltype) && cell->hasPort(RTLIL::escape_id(outpad_portname2)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(outpad_portname2))))
|
||||
skip_wire_bits.insert(bit);
|
||||
|
||||
if (cell->type == RTLIL::escape_id(inoutpad_celltype) && cell->hasPort(RTLIL::escape_id(inoutpad_portname2)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inoutpad_portname2))))
|
||||
skip_wire_bits.insert(bit);
|
||||
|
||||
if (cell->type == RTLIL::escape_id(toutpad_celltype) && cell->hasPort(RTLIL::escape_id(toutpad_portname3)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(toutpad_portname3))))
|
||||
skip_wire_bits.insert(bit);
|
||||
|
||||
if (cell->type == RTLIL::escape_id(tinoutpad_celltype) && cell->hasPort(RTLIL::escape_id(tinoutpad_portname4)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(tinoutpad_portname4))))
|
||||
skip_wire_bits.insert(bit);
|
||||
}
|
||||
|
||||
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
|
||||
{
|
||||
SigMap sigmap(module);
|
||||
dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits;
|
||||
pool<pair<IdString, IdString>> norewrites;
|
||||
SigMap rewrites;
|
||||
|
||||
for (auto cell : module->cells())
|
||||
if (cell->type == "$_TBUF_") {
|
||||
|
@ -177,6 +203,9 @@ struct IopadmapPass : public Pass {
|
|||
if (tbuf_bits.count(mapped_wire_bit) == 0)
|
||||
continue;
|
||||
|
||||
if (skip_wire_bits.count(mapped_wire_bit))
|
||||
continue;
|
||||
|
||||
auto &tbuf_cache = tbuf_bits.at(mapped_wire_bit);
|
||||
Cell *tbuf_cell = module->cell(tbuf_cache.first);
|
||||
|
||||
|
@ -219,6 +248,9 @@ struct IopadmapPass : public Pass {
|
|||
|
||||
module->remove(tbuf_cell);
|
||||
skip_wires[wire->name].insert(i);
|
||||
|
||||
norewrites.insert(make_pair(cell->name, RTLIL::escape_id(tinoutpad_portname4)));
|
||||
rewrites.add(sigmap(wire_bit), owire);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -256,6 +288,22 @@ struct IopadmapPass : public Pass {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetSize(norewrites))
|
||||
{
|
||||
for (auto cell : module->cells())
|
||||
for (auto port : cell->connections())
|
||||
{
|
||||
if (norewrites.count(make_pair(cell->name, port.first)))
|
||||
continue;
|
||||
|
||||
SigSpec orig_sig = sigmap(port.second);
|
||||
SigSpec new_sig = rewrites(orig_sig);
|
||||
|
||||
if (orig_sig != new_sig)
|
||||
cell->setPort(port.first, new_sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto wire : module->selected_wires())
|
||||
|
@ -272,6 +320,13 @@ struct IopadmapPass : public Pass {
|
|||
skip_bit_indices = skip_wires.at(wire->name);
|
||||
}
|
||||
|
||||
for (int i = 0; i < GetSize(wire); i++)
|
||||
if (skip_wire_bits.count(sigmap(SigBit(wire, i))))
|
||||
skip_bit_indices.insert(i);
|
||||
|
||||
if (GetSize(wire) == GetSize(skip_bit_indices))
|
||||
continue;
|
||||
|
||||
if (wire->port_input && !wire->port_output) {
|
||||
if (inpad_celltype.empty()) {
|
||||
log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
|
||||
|
|
|
@ -55,13 +55,14 @@ struct PrepPass : public ScriptPass
|
|||
log("\n");
|
||||
log(" -memx\n");
|
||||
log(" simulate verilog simulation behavior for out-of-bounds memory accesses\n");
|
||||
log(" using the 'memory_memx' pass. This option implies -nordff.\n");
|
||||
log(" using the 'memory_memx' pass.\n");
|
||||
log("\n");
|
||||
log(" -nomem\n");
|
||||
log(" do not run any of the memory_* passes\n");
|
||||
log("\n");
|
||||
log(" -nordff\n");
|
||||
log(" passed to 'memory_dff'. prohibits merging of FFs into memory read ports\n");
|
||||
log(" -rdff\n");
|
||||
log(" do not pass -nordff to 'memory_dff'. This enables merging of FFs into\n");
|
||||
log(" memory read ports.\n");
|
||||
log("\n");
|
||||
log(" -nokeepdc\n");
|
||||
log(" do not call opt_* with -keepdc\n");
|
||||
|
@ -77,13 +78,12 @@ struct PrepPass : public ScriptPass
|
|||
log("\n");
|
||||
}
|
||||
|
||||
string top_module, fsm_opts, memory_opts;
|
||||
bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc;
|
||||
string top_module, fsm_opts;
|
||||
bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, nordff;
|
||||
|
||||
virtual void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
top_module.clear();
|
||||
memory_opts.clear();
|
||||
|
||||
autotop = false;
|
||||
flatten = false;
|
||||
|
@ -91,6 +91,7 @@ struct PrepPass : public ScriptPass
|
|||
memxmode = false;
|
||||
nomemmode = false;
|
||||
nokeepdc = false;
|
||||
nordff = true;
|
||||
}
|
||||
|
||||
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
@ -129,7 +130,6 @@ struct PrepPass : public ScriptPass
|
|||
}
|
||||
if (args[argidx] == "-memx") {
|
||||
memxmode = true;
|
||||
memory_opts += " -nordff";
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nomem") {
|
||||
|
@ -137,7 +137,11 @@ struct PrepPass : public ScriptPass
|
|||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nordff") {
|
||||
memory_opts += " -nordff";
|
||||
nordff = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-rdff") {
|
||||
nordff = false;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nokeepdc") {
|
||||
|
@ -196,7 +200,7 @@ struct PrepPass : public ScriptPass
|
|||
run(memxmode ? "wreduce -memx" : "wreduce");
|
||||
}
|
||||
if (!nomemmode) {
|
||||
run("memory_dff" + (help_mode ? " [-nordff]" : memory_opts));
|
||||
run(string("memory_dff") + (help_mode ? " [-nordff]" : nordff ? " -nordff" : ""));
|
||||
if (help_mode || memxmode)
|
||||
run("memory_memx", "(if -memx)");
|
||||
run("opt_clean");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
`define SB_DFF_REG reg Q = 0;
|
||||
// `define SB_DFF_REG reg Q;
|
||||
`define SB_DFF_REG reg Q = 0
|
||||
// `define SB_DFF_REG reg Q
|
||||
|
||||
// SiliconBlue IO Cells
|
||||
|
||||
|
@ -132,21 +132,18 @@ endmodule
|
|||
|
||||
// Positive Edge SiliconBlue FF Cells
|
||||
|
||||
module SB_DFF (output Q, input C, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFF (output `SB_DFF_REG, input C, D);
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFE (output Q, input C, E, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFE (output `SB_DFF_REG, input C, E, D);
|
||||
always @(posedge C)
|
||||
if (E)
|
||||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFSR (output Q, input C, R, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
|
||||
always @(posedge C)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -154,8 +151,7 @@ module SB_DFFSR (output Q, input C, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFR (output Q, input C, R, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFR (output `SB_DFF_REG, input C, R, D);
|
||||
always @(posedge C, posedge R)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -163,8 +159,7 @@ module SB_DFFR (output Q, input C, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFSS (output Q, input C, S, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
|
||||
always @(posedge C)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -172,8 +167,7 @@ module SB_DFFSS (output Q, input C, S, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFS (output Q, input C, S, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFS (output `SB_DFF_REG, input C, S, D);
|
||||
always @(posedge C, posedge S)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -181,8 +175,7 @@ module SB_DFFS (output Q, input C, S, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFESR (output Q, input C, E, R, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
|
||||
always @(posedge C)
|
||||
if (E) begin
|
||||
if (R)
|
||||
|
@ -192,8 +185,7 @@ module SB_DFFESR (output Q, input C, E, R, D);
|
|||
end
|
||||
endmodule
|
||||
|
||||
module SB_DFFER (output Q, input C, E, R, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
|
||||
always @(posedge C, posedge R)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -201,8 +193,7 @@ module SB_DFFER (output Q, input C, E, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFESS (output Q, input C, E, S, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
|
||||
always @(posedge C)
|
||||
if (E) begin
|
||||
if (S)
|
||||
|
@ -212,8 +203,7 @@ module SB_DFFESS (output Q, input C, E, S, D);
|
|||
end
|
||||
endmodule
|
||||
|
||||
module SB_DFFES (output Q, input C, E, S, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFES (output `SB_DFF_REG, input C, E, S, D);
|
||||
always @(posedge C, posedge S)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -223,21 +213,18 @@ endmodule
|
|||
|
||||
// Negative Edge SiliconBlue FF Cells
|
||||
|
||||
module SB_DFFN (output Q, input C, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFN (output `SB_DFF_REG, input C, D);
|
||||
always @(negedge C)
|
||||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNE (output Q, input C, E, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFNE (output `SB_DFF_REG, input C, E, D);
|
||||
always @(negedge C)
|
||||
if (E)
|
||||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNSR (output Q, input C, R, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
|
||||
always @(negedge C)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -245,8 +232,7 @@ module SB_DFFNSR (output Q, input C, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNR (output Q, input C, R, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
|
||||
always @(negedge C, posedge R)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -254,8 +240,7 @@ module SB_DFFNR (output Q, input C, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNSS (output Q, input C, S, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
|
||||
always @(negedge C)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -263,8 +248,7 @@ module SB_DFFNSS (output Q, input C, S, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNS (output Q, input C, S, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
|
||||
always @(negedge C, posedge S)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -272,8 +256,7 @@ module SB_DFFNS (output Q, input C, S, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNESR (output Q, input C, E, R, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
|
||||
always @(negedge C)
|
||||
if (E) begin
|
||||
if (R)
|
||||
|
@ -283,8 +266,7 @@ module SB_DFFNESR (output Q, input C, E, R, D);
|
|||
end
|
||||
endmodule
|
||||
|
||||
module SB_DFFNER (output Q, input C, E, R, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
|
||||
always @(negedge C, posedge R)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -292,8 +274,7 @@ module SB_DFFNER (output Q, input C, E, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNESS (output Q, input C, E, S, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
|
||||
always @(negedge C)
|
||||
if (E) begin
|
||||
if (S)
|
||||
|
@ -303,8 +284,7 @@ module SB_DFFNESS (output Q, input C, E, S, D);
|
|||
end
|
||||
endmodule
|
||||
|
||||
module SB_DFFNES (output Q, input C, E, S, D);
|
||||
`SB_DFF_REG
|
||||
module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D);
|
||||
always @(negedge C, posedge S)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -677,7 +657,7 @@ module ICESTORM_LC (
|
|||
parameter [0:0] SET_NORESET = 0;
|
||||
parameter [0:0] ASYNC_SR = 0;
|
||||
|
||||
wire COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && CIN) : 1'bx;
|
||||
assign COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && CIN) : 1'bx;
|
||||
|
||||
wire [7:0] lut_s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
|
||||
wire [3:0] lut_s2 = I2 ? lut_s3[ 7:4] : lut_s3[3:0];
|
||||
|
|
|
@ -26,6 +26,13 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
static SigBit get_bit_or_zero(const SigSpec &sig)
|
||||
{
|
||||
if (GetSize(sig) == 0)
|
||||
return State::S0;
|
||||
return sig[0];
|
||||
}
|
||||
|
||||
static void run_ice40_opts(Module *module, bool unlut_mode)
|
||||
{
|
||||
pool<SigBit> optimized_co;
|
||||
|
@ -45,7 +52,11 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
|
|||
SigSpec non_const_inputs, replacement_output;
|
||||
int count_zeros = 0, count_ones = 0;
|
||||
|
||||
SigBit inbit[3] = {cell->getPort("\\I0"), cell->getPort("\\I1"), cell->getPort("\\CI")};
|
||||
SigBit inbit[3] = {
|
||||
get_bit_or_zero(cell->getPort("\\I0")),
|
||||
get_bit_or_zero(cell->getPort("\\I1")),
|
||||
get_bit_or_zero(cell->getPort("\\CI"))
|
||||
};
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (inbit[i].wire == nullptr) {
|
||||
if (inbit[i] == State::S1)
|
||||
|
@ -63,8 +74,8 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
|
|||
replacement_output = non_const_inputs;
|
||||
|
||||
if (GetSize(replacement_output)) {
|
||||
optimized_co.insert(sigmap(cell->getPort("\\CO")));
|
||||
module->connect(cell->getPort("\\CO"), replacement_output);
|
||||
optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
|
||||
module->connect(cell->getPort("\\CO")[0], replacement_output);
|
||||
module->design->scratchpad_set_bool("opt.did_something", true);
|
||||
log("Optimized away SB_CARRY cell %s.%s: CO=%s\n",
|
||||
log_id(module), log_id(cell), log_signal(replacement_output));
|
||||
|
@ -78,10 +89,10 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
|
|||
{
|
||||
SigSpec inbits;
|
||||
|
||||
inbits.append(cell->getPort("\\I0"));
|
||||
inbits.append(cell->getPort("\\I1"));
|
||||
inbits.append(cell->getPort("\\I2"));
|
||||
inbits.append(cell->getPort("\\I3"));
|
||||
inbits.append(get_bit_or_zero(cell->getPort("\\I0")));
|
||||
inbits.append(get_bit_or_zero(cell->getPort("\\I1")));
|
||||
inbits.append(get_bit_or_zero(cell->getPort("\\I2")));
|
||||
inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
|
||||
sigmap.apply(inbits);
|
||||
|
||||
if (unlut_mode)
|
||||
|
@ -104,8 +115,13 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
|
|||
cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
|
||||
cell->unsetParam("\\LUT_INIT");
|
||||
|
||||
cell->setPort("\\A", SigSpec({cell->getPort("\\I3"), cell->getPort("\\I2"), cell->getPort("\\I1"), cell->getPort("\\I0")}));
|
||||
cell->setPort("\\Y", cell->getPort("\\O"));
|
||||
cell->setPort("\\A", SigSpec({
|
||||
get_bit_or_zero(cell->getPort("\\I3")),
|
||||
get_bit_or_zero(cell->getPort("\\I2")),
|
||||
get_bit_or_zero(cell->getPort("\\I1")),
|
||||
get_bit_or_zero(cell->getPort("\\I0"))
|
||||
}));
|
||||
cell->setPort("\\Y", cell->getPort("\\O")[0]);
|
||||
cell->unsetPort("\\I0");
|
||||
cell->unsetPort("\\I1");
|
||||
cell->unsetPort("\\I2");
|
||||
|
|
|
@ -45,7 +45,11 @@ struct SynthIce40Pass : public ScriptPass
|
|||
log(" is omitted if this parameter is not specified.\n");
|
||||
log("\n");
|
||||
log(" -edif <file>\n");
|
||||
log(" write the design to the specified edif file. writing of an output file\n");
|
||||
log(" write the design to the specified EDIF file. writing of an output file\n");
|
||||
log(" is omitted if this parameter is not specified.\n");
|
||||
log("\n");
|
||||
log(" -json <file>\n");
|
||||
log(" write the design to the specified JSON file. writing of an output file\n");
|
||||
log(" is omitted if this parameter is not specified.\n");
|
||||
log("\n");
|
||||
log(" -run <from_label>:<to_label>\n");
|
||||
|
@ -81,7 +85,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
log("\n");
|
||||
}
|
||||
|
||||
string top_opt, blif_file, edif_file;
|
||||
string top_opt, blif_file, edif_file, json_file;
|
||||
bool nocarry, nodffe, nobram, flatten, retime, abc2, vpr;
|
||||
|
||||
virtual void clear_flags() YS_OVERRIDE
|
||||
|
@ -89,6 +93,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
top_opt = "-auto-top";
|
||||
blif_file = "";
|
||||
edif_file = "";
|
||||
json_file = "";
|
||||
nocarry = false;
|
||||
nodffe = false;
|
||||
nobram = false;
|
||||
|
@ -118,6 +123,10 @@ struct SynthIce40Pass : public ScriptPass
|
|||
edif_file = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-json" && argidx+1 < args.size()) {
|
||||
json_file = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-run" && argidx+1 < args.size()) {
|
||||
size_t pos = args[argidx+1].find(':');
|
||||
if (pos == std::string::npos)
|
||||
|
@ -260,17 +269,15 @@ struct SynthIce40Pass : public ScriptPass
|
|||
if (!blif_file.empty() || help_mode) {
|
||||
if (vpr || help_mode) {
|
||||
run(stringf("opt_clean -purge"),
|
||||
" "
|
||||
" (vpr mode)");
|
||||
" (vpr mode)");
|
||||
run(stringf("write_blif -attr -cname -conn -param %s",
|
||||
help_mode ? "<file-name>" : blif_file.c_str()),
|
||||
" (vpr mode)");
|
||||
help_mode ? "<file-name>" : blif_file.c_str()),
|
||||
" (vpr mode)");
|
||||
}
|
||||
if (!vpr)
|
||||
run(stringf("write_blif -gates -attr -param %s",
|
||||
help_mode ? "<file-name>" : blif_file.c_str()),
|
||||
" "
|
||||
" (non-vpr mode)");
|
||||
help_mode ? "<file-name>" : blif_file.c_str()),
|
||||
" (non-vpr mode)");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,6 +286,12 @@ struct SynthIce40Pass : public ScriptPass
|
|||
if (!edif_file.empty() || help_mode)
|
||||
run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
|
||||
}
|
||||
|
||||
if (check_label("json"))
|
||||
{
|
||||
if (!json_file.empty() || help_mode)
|
||||
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
|
||||
}
|
||||
}
|
||||
} SynthIce40Pass;
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ do
|
|||
echo -n "Test: $bn "
|
||||
fi
|
||||
|
||||
rm -f ${bn}.{err,log,sikp}
|
||||
rm -f ${bn}.{err,log,skip}
|
||||
mkdir -p ${bn}.out
|
||||
rm -rf ${bn}.out/*
|
||||
|
||||
|
|
Loading…
Reference in New Issue