Merge remote-tracking branch 'origin/master' into eddie/synth_xilinx

This commit is contained in:
Eddie Hung 2019-08-20 11:57:52 -07:00
commit d9fe4cccbf
191 changed files with 6974 additions and 4473 deletions

View File

@ -36,37 +36,10 @@ matrix:
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
- zlib1g-dev
env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8"
# Latest gcc-6 on Travis Linux
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
- gperf
- build-essential
- bison
- flex
- libreadline-dev
- gawk
- tcl-dev
- libffi-dev
- git
- graphviz
- xdot
- pkg-config
- python
- python3
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-6 && CXX=g++-6"
# Latest gcc supported on Travis Linux
- os: linux
addons:
@ -74,7 +47,7 @@ matrix:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
- g++-9
- gperf
- build-essential
- bison
@ -92,8 +65,9 @@ matrix:
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
- zlib1g-dev
env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7"
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-9 && CXX=g++-9"
# Clang which ships on Trusty Linux
- os: linux
@ -121,6 +95,7 @@ matrix:
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
- zlib1g-dev
env:
- MATRIX_EVAL="CONFIG=clang && CC=clang-3.8 && CXX=clang++-3.8"
@ -129,9 +104,9 @@ matrix:
addons:
apt:
sources:
- llvm-toolchain-trusty-5.0
- llvm-toolchain-xenial-8
packages:
- clang-5.0
- clang-8
- gperf
- build-essential
- bison
@ -149,8 +124,9 @@ matrix:
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
- zlib1g-dev
env:
- MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"
- MATRIX_EVAL="CONFIG=clang && CC=clang-8 && CXX=clang++-8"
# # Latest clang on Mac OS X
# - os: osx

View File

@ -28,7 +28,7 @@ echo
echo 'Building...' && echo -en 'travis_fold:start:script.build\\r'
echo
make
make CC=$CC CXX=$CC LD=$CC
echo
echo -en 'travis_fold:end:script.build\\r'

View File

@ -51,7 +51,7 @@ fi
git clone git://github.com/steveicarus/iverilog.git
cd iverilog
autoconf
./configure --prefix=$HOME/.local-bin
CC=gcc CXX=g++ ./configure --prefix=$HOME/.local-bin
make
make install
echo

View File

@ -18,7 +18,14 @@ Yosys 0.9 .. Yosys 0.9-dev
- Renamed labels/options in synth_ecp5 (e.g. dram -> map_lutram; -nodram -> -nolutram)
- Renamed labels in synth_intel (e.g. bram -> map_bram)
- Renamed labels/options in synth_xilinx (e.g. dram -> map_lutram; -nodram -> -nolutram)
- Added automatic gzip decompression for frontends
- Added $_NMUX_ cell type
- Added automatic gzip compression (based on filename extension) for backends
- Improve attribute and parameter encoding in JSON to avoid ambiguities between
bit vectors and strings containing [01xz]*
- Added "opt_share" pass, run as part of "opt -full"
- Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping
- Removed "ice40_unlut"
Yosys 0.8 .. Yosys 0.8-dev
--------------------------

View File

@ -1,33 +1,57 @@
FROM ubuntu:18.04 as builder
LABEL author="Abdelrahman Hosny <abdelrahman.hosny@hotmail.com>"
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y build-essential \
ARG IMAGE="python:3-slim-buster"
#---
FROM $IMAGE AS base
RUN apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
ca-certificates \
clang \
curl \
libffi-dev \
libreadline-dev \
tcl-dev \
graphviz \
xdot \
&& apt-get autoclean && apt-get clean && apt-get -y autoremove \
&& update-ca-certificates \
&& rm -rf /var/lib/apt/lists
#---
FROM base AS build
RUN apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
bison \
flex \
libreadline-dev \
gawk \
tcl-dev \
libffi-dev \
gcc \
git \
iverilog \
pkg-config \
python3 && \
rm -rf /var/lib/apt/lists
COPY . /
RUN make && \
make install
&& apt-get autoclean && apt-get clean && apt-get -y autoremove \
&& rm -rf /var/lib/apt/lists
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y libreadline-dev tcl-dev
COPY . /yosys
COPY --from=builder /yosys /build/yosys
COPY --from=builder /yosys-abc /build/yosys-abc
COPY --from=builder /yosys-config /build/yosys-config
COPY --from=builder /yosys-filterlib /build/yosys-filterlib
COPY --from=builder /yosys-smtbmc /build/yosys-smtbmc
ENV PREFIX /opt/yosys
RUN cd /yosys \
&& make \
&& make install \
&& make test
#---
FROM base
COPY --from=build /opt/yosys /opt/yosys
ENV PATH /opt/yosys/bin:$PATH
ENV PATH /build:$PATH
RUN useradd -m yosys
USER yosys
ENTRYPOINT ["yosys"]
CMD ["yosys"]

View File

@ -19,6 +19,7 @@ ENABLE_VERIFIC := 0
ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0
ENABLE_PROTOBUF := 0
ENABLE_ZLIB := 1
# python wrappers
ENABLE_PYOSYS := 0
@ -260,7 +261,8 @@ CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
# TODO: Try to solve pthread linking issue in more appropriate way
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" LDFLAGS="-Wl,--allow-multiple-definition" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
EXE = .exe
else ifeq ($(CONFIG),msys2)
@ -384,6 +386,12 @@ ifeq ($(ENABLE_GLOB),1)
CXXFLAGS += -DYOSYS_ENABLE_GLOB
endif
ifeq ($(ENABLE_ZLIB),1)
CXXFLAGS += -DYOSYS_ENABLE_ZLIB
LDLIBS += -lz
endif
ifeq ($(ENABLE_TCL),1)
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
ifeq ($(OS), FreeBSD)
@ -394,7 +402,7 @@ endif
ifeq ($(CONFIG),mxe)
CXXFLAGS += -DYOSYS_ENABLE_TCL
LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz
LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz -luserenv
else
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
ifeq ($(OS), FreeBSD)
@ -674,10 +682,12 @@ endif
test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/simple && bash run-test.sh $(SEEDOPT)
+cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT)
+cd tests/hana && bash run-test.sh $(SEEDOPT)
+cd tests/asicworld && bash run-test.sh $(SEEDOPT)
# +cd tests/realmath && bash run-test.sh $(SEEDOPT)
+cd tests/share && bash run-test.sh $(SEEDOPT)
+cd tests/opt_share && bash run-test.sh $(SEEDOPT)
+cd tests/fsm && bash run-test.sh $(SEEDOPT)
+cd tests/techmap && bash run-test.sh
+cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT)
@ -688,7 +698,6 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/opt && bash run-test.sh
+cd tests/aiger && bash run-test.sh $(ABCOPT)
+cd tests/arch && bash run-test.sh
+cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT)
@echo ""
@echo " Passed \"make test\"."
@echo ""
@ -773,7 +782,7 @@ clean:
rm -rf kernel/*.pyh
if test -d manual; then cd manual && sh clean.sh; fi
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) $(PY_WRAP_INCLUDES) $(PY_WRAPPER_FILE).cc
rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
rm -f kernel/version_*.o kernel/version_*.cc
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
@ -862,9 +871,11 @@ config-mxe: clean
config-msys2: clean
echo 'CONFIG := msys2' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-msys2-64: clean
echo 'CONFIG := msys2-64' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-cygwin: clean
echo 'CONFIG := cygwin' > Makefile.conf

View File

@ -67,13 +67,13 @@ prerequisites for building yosys:
$ sudo apt-get install build-essential clang bison flex \
libreadline-dev gawk tcl-dev libffi-dev git \
graphviz xdot pkg-config python3 libboost-system-dev \
libboost-python-dev libboost-filesystem-dev
libboost-python-dev libboost-filesystem-dev zlib1g-dev
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 graphviz pkgconfig python36 boost
git graphviz pkgconfig python36 boost zlib
On FreeBSD use the following command to install all prerequisites:
@ -85,7 +85,7 @@ On FreeBSD system use gmake instead of make. To run tests use:
For Cygwin use the following command to install all prerequisites, or select these additional packages:
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well
as a source distribution for Visual Studio. Visit the Yosys download page for
@ -130,18 +130,15 @@ commands and ``help <command>`` to print details on the specified command:
yosys> help help
reading the design using the Verilog frontend:
reading and elaborating the design using the Verilog frontend:
yosys> read_verilog tests/simple/fiedler-cooley.v
yosys> read -sv tests/simple/fiedler-cooley.v
yosys> hierarchy -top up3down5
writing the design to the console in Yosys's internal format:
yosys> write_ilang
elaborate design hierarchy:
yosys> hierarchy
convert processes (``always`` blocks) to netlist elements and perform
some simple optimizations:
@ -163,51 +160,26 @@ write design netlist to a new Verilog file:
yosys> write_verilog synth.v
a similar synthesis can be performed using yosys command line options only:
$ ./yosys -o synth.v -p hierarchy -p proc -p opt \
-p techmap -p opt tests/simple/fiedler-cooley.v
or using a simple synthesis script:
$ cat synth.ys
read_verilog tests/simple/fiedler-cooley.v
hierarchy; proc; opt; techmap; opt
read -sv tests/simple/fiedler-cooley.v
hierarchy -top up3down5
proc; opt; techmap; opt
write_verilog synth.v
$ ./yosys synth.ys
It is also possible to only have the synthesis commands but not the read/write
commands in the synthesis script:
$ cat synth.ys
hierarchy; proc; opt; techmap; opt
$ ./yosys -o synth.v tests/simple/fiedler-cooley.v synth.ys
The following very basic synthesis script should work well with all designs:
# check design hierarchy
hierarchy
# translate processes (always blocks)
proc; opt
# detect and optimize FSM encodings
fsm; opt
# implement memories (arrays)
memory; opt
# convert to gate logic
techmap; opt
If ABC is enabled in the Yosys build configuration and a cell library is given
in the liberty file ``mycells.lib``, the following synthesis script will
synthesize for the given cell library:
# read design
read -sv tests/simple/fiedler-cooley.v
hierarchy -top up3down5
# the high-level stuff
hierarchy; proc; fsm; opt; memory; opt
proc; fsm; opt; memory; opt
# mapping to internal cell library
techmap; opt
@ -222,7 +194,8 @@ synthesize for the given cell library:
clean
If you do not have a liberty file but want to test this synthesis script,
you can use the file ``examples/cmos/cmos_cells.lib`` from the yosys sources.
you can use the file ``examples/cmos/cmos_cells.lib`` from the yosys sources
as simple example.
Liberty file downloads for and information about free and open ASIC standard
cell libraries can be found here:
@ -231,20 +204,18 @@ cell libraries can be found here:
- http://www.vlsitechnology.org/synopsys/vsclib013.lib
The command ``synth`` provides a good default synthesis script (see
``help synth``). If possible a synthesis script should borrow from ``synth``.
For example:
``help synth``):
# the high-level stuff
hierarchy
synth -run coarse
read -sv tests/simple/fiedler-cooley.v
synth -top up3down5
# mapping to internal cells
techmap; opt -fast
# mapping to target cells
dfflibmap -liberty mycells.lib
abc -liberty mycells.lib
clean
Yosys is under construction. A more detailed documentation will follow.
The command ``prep`` provides a good default word-level synthesis script, as
used in SMT-based formal verification.
Unsupported Verilog-2005 Features

View File

@ -53,7 +53,7 @@ PRIVATE_NAMESPACE_BEGIN
inline int32_t to_big_endian(int32_t i32) {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return __builtin_bswap32(i32);
return bswap32(i32);
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
return i32;
#else
@ -312,7 +312,7 @@ struct XAigerWriter
#if 0
toposort.analyze_loops = true;
#endif
bool no_loops = toposort.sort();
bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
#if 0
unsigned i = 0;
for (auto &it : toposort.loops) {
@ -388,11 +388,11 @@ struct XAigerWriter
RTLIL::SigSpec rhs;
if (it != cell->connections_.end()) {
if (GetSize(it->second) < GetSize(w))
it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second)));
it->second.append(RTLIL::SigSpec(State::S0, GetSize(w)-GetSize(it->second)));
rhs = it->second;
}
else {
rhs = RTLIL::SigSpec(RTLIL::S0, GetSize(w));
rhs = RTLIL::SigSpec(State::S0, GetSize(w));
cell->setPort(port_name, rhs);
}
@ -400,10 +400,10 @@ struct XAigerWriter
for (auto b : rhs.bits()) {
SigBit I = sigmap(b);
if (b == RTLIL::Sx)
b = RTLIL::S0;
b = State::S0;
else if (I != b) {
if (I == RTLIL::Sx)
alias_map[b] = RTLIL::S0;
alias_map[b] = State::S0;
else
alias_map[b] = I;
}
@ -610,19 +610,18 @@ struct XAigerWriter
std::stringstream h_buffer;
auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1);
write_h_buffer(1);
log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size());
log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits));
write_h_buffer(input_bits.size() + ci_bits.size());
log_debug("coNum = %zu\n", output_bits.size() + co_bits.size());
log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits));
write_h_buffer(output_bits.size() + co_bits.size());
log_debug("piNum = %zu\n", input_bits.size());
log_debug("piNum = %d\n", GetSize(input_bits));
write_h_buffer(input_bits.size());
log_debug("poNum = %zu\n", output_bits.size());
log_debug("poNum = %d\n", GetSize(output_bits));
write_h_buffer(output_bits.size());
log_debug("boxNum = %zu\n", box_list.size());
log_debug("boxNum = %d\n", GetSize(box_list));
write_h_buffer(box_list.size());
RTLIL::Module *holes_module = nullptr;
holes_module = module->design->addModule("$__holes__");
RTLIL::Module *holes_module = module->design->addModule("$__holes__");
log_assert(holes_module);
int port_id = 1;
@ -672,7 +671,7 @@ struct XAigerWriter
if (holes_cell)
port_wire.append(holes_wire);
else
holes_module->connect(holes_wire, RTLIL::S0);
holes_module->connect(holes_wire, State::S0);
}
if (!port_wire.empty())
holes_cell->setPort(w->name, port_wire);
@ -719,27 +718,33 @@ struct XAigerWriter
Pass::call(holes_module->design, "flatten -wb");
// TODO: Should techmap/aigmap/check all lib_whitebox-es just once,
// instead of per write_xaiger call
// instead of per write_xaiger call
Pass::call(holes_module->design, "techmap");
Pass::call(holes_module->design, "aigmap");
for (auto cell : holes_module->cells())
if (!cell->type.in("$_NOT_", "$_AND_"))
log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n");
Pass::call(holes_module->design, "clean -purge");
holes_module->design->selection_stack.pop_back();
// Move into a new (temporary) design so that "clean" will only
// operate (and run checks on) this one module
RTLIL::Design *holes_design = new RTLIL::Design;
holes_module->design->modules_.erase(holes_module->name);
holes_design->add(holes_module);
Pass::call(holes_design, "clean -purge");
std::stringstream a_buffer;
XAigerWriter writer(holes_module, true /* holes_mode */);
writer.write_aiger(a_buffer, false /*ascii_mode*/);
holes_module->design->selection_stack.pop_back();
delete holes_design;
f << "a";
std::string buffer_str = a_buffer.str();
int32_t buffer_size_be = to_big_endian(buffer_str.size());
f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
f.write(buffer_str.data(), buffer_str.size());
holes_module->design->remove(holes_module);
log_pop();
}
@ -772,7 +777,7 @@ struct XAigerWriter
if (output_bits.count(b)) {
int o = ordered_outputs.at(b);
output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire));
output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), i, log_id(wire));
continue;
}

View File

@ -327,6 +327,13 @@ struct BlifDumper
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_NMUX_") {
f << stringf(".names %s %s %s %s\n0-0 1\n-01 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_FF_") {
f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr_init(cell->getPort("\\Q")));
@ -370,7 +377,7 @@ struct BlifDumper
f << stringf("\n");
RTLIL::SigSpec mask = cell->parameters.at("\\LUT");
for (int i = 0; i < (1 << width); i++)
if (mask[i] == RTLIL::S1) {
if (mask[i] == State::S1) {
for (int j = width-1; j >= 0; j--) {
f << ((i>>j)&1 ? '1' : '0');
}

View File

@ -496,7 +496,7 @@ struct BtorWorker
goto okay;
}
if (cell->type.in("$mux", "$_MUX_"))
if (cell->type.in("$mux", "$_MUX_", "$_NMUX_"))
{
SigSpec sig_a = sigmap(cell->getPort("\\A"));
SigSpec sig_b = sigmap(cell->getPort("\\B"));
@ -511,6 +511,12 @@ struct BtorWorker
int nid = next_nid++;
btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a);
if (cell->type == "$_NMUX_") {
int tmp = nid;
nid = next_nid++;
btorf("%d not %d %d\n", nid, sid, tmp);
}
add_nid_sig(nid, sig_y);
goto okay;
}
@ -610,8 +616,8 @@ struct BtorWorker
if (initstate_nid < 0)
{
int sid = get_bv_sid(1);
int one_nid = get_sig_nid(Const(1, 1));
int zero_nid = get_sig_nid(Const(0, 1));
int one_nid = get_sig_nid(State::S1);
int zero_nid = get_sig_nid(State::S0);
initstate_nid = next_nid++;
btorf("%d state %d\n", initstate_nid, sid);
btorf("%d init %d %d %d\n", next_nid++, sid, initstate_nid, one_nid);

View File

@ -122,9 +122,9 @@ struct FirrtlWorker
// Current (3/13/2019) conventions:
// generate a constant 0 for clock and a constant 1 for enable if they are undefined.
if (!clk.is_fully_def())
this->clk = SigSpec(RTLIL::Const(0, 1));
this->clk = SigSpec(State::S0);
if (!ena.is_fully_def())
this->ena = SigSpec(RTLIL::Const(1, 1));
this->ena = SigSpec(State::S1);
}
string gen_read(const char * indent) {
string addr_expr = make_expr(addr);
@ -297,7 +297,7 @@ struct FirrtlWorker
std::string cell_type = fid(cell->type);
std::string instanceOf;
// If this is a parameterized module, its parent module is encoded in the cell type
if (cell->type.substr(0, 8) == "$paramod")
if (cell->type.begins_with("$paramod"))
{
std::string::iterator it;
for (it = cell_type.begin(); it < cell_type.end(); it++)
@ -363,7 +363,7 @@ struct FirrtlWorker
}
// Check for subfield assignment.
std::string bitsString = "bits(";
if (sinkExpr.substr(0, bitsString.length()) == bitsString ) {
if (sinkExpr.compare(0, bitsString.length(), bitsString) == 0) {
if (sinkSig == nullptr)
log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str());
// Don't generate the assignment here.
@ -381,10 +381,10 @@ struct FirrtlWorker
// Given an expression for a shift amount, and a maximum width,
// generate the FIRRTL expression for equivalent dynamic shift taking into account FIRRTL shift semantics.
std::string gen_dshl(const string b_expr, const int b_padded_width)
std::string gen_dshl(const string b_expr, const int b_width)
{
string result = b_expr;
if (b_padded_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) {
if (b_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) {
int max_shift_width_bits = FIRRTL_MAX_DSH_WIDTH_ERROR - 1;
string max_shift_string = stringf("UInt<%d>(%d)", max_shift_width_bits, (1<<max_shift_width_bits) - 1);
// Deal with the difference in semantics between FIRRTL and verilog
@ -422,22 +422,33 @@ struct FirrtlWorker
for (auto cell : module->cells())
{
bool extract_y_bits = false; // Assume no extraction of final bits will be required.
static Const ndef(0, 0);
// Is this cell is a module instance?
if (cell->type[0] != '$')
{
process_instance(cell, wire_exprs);
continue;
}
// Not a module instance. Set up cell properties
bool extract_y_bits = false; // Assume no extraction of final bits will be required.
int a_width = cell->parameters.at("\\A_WIDTH", ndef).as_int(); // The width of "A"
int b_width = cell->parameters.at("\\B_WIDTH", ndef).as_int(); // The width of "A"
const int y_width = cell->parameters.at("\\Y_WIDTH", ndef).as_int(); // The width of the result
const bool a_signed = cell->parameters.at("\\A_SIGNED", ndef).as_bool();
const bool b_signed = cell->parameters.at("\\B_SIGNED", ndef).as_bool();
bool firrtl_is_signed = a_signed; // The result is signed (subsequent code may change this).
int firrtl_width = 0;
string primop;
bool always_uint = false;
string y_id = make_id(cell->name);
if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor"))
{
string y_id = make_id(cell->name);
bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A"));
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
if (cell->parameters.at("\\A_SIGNED").as_bool()) {
if (a_signed) {
a_expr = "asSInt(" + a_expr + ")";
}
@ -446,12 +457,13 @@ struct FirrtlWorker
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
}
string primop;
bool always_uint = false;
// Assume the FIRRTL width is a single bit.
firrtl_width = 1;
if (cell->type == "$not") primop = "not";
else if (cell->type == "$neg") {
primop = "neg";
is_signed = true; // Result of "neg" is signed (an SInt).
firrtl_is_signed = true; // Result of "neg" is signed (an SInt).
firrtl_width = a_width;
} else if (cell->type == "$logic_not") {
primop = "eq";
a_expr = stringf("%s, UInt(0)", a_expr.c_str());
@ -466,14 +478,12 @@ struct FirrtlWorker
else if (cell->type == "$reduce_bool") {
primop = "neq";
// Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand.
bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool();
int a_width = cell->parameters.at("\\A_WIDTH").as_int();
a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width);
}
string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str());
if ((is_signed && !always_uint))
if ((firrtl_is_signed && !always_uint))
expr = stringf("asUInt(%s)", expr.c_str());
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
@ -481,81 +491,121 @@ struct FirrtlWorker
continue;
}
if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx",
if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or", "$eq", "$eqx",
"$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl",
"$logic_and", "$logic_or"))
"$logic_and", "$logic_or", "$pow"))
{
string y_id = make_id(cell->name);
bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A"));
string b_expr = make_expr(cell->getPort("\\B"));
int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int();
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
if (cell->parameters.at("\\A_SIGNED").as_bool()) {
if (a_signed) {
a_expr = "asSInt(" + a_expr + ")";
}
// Shift amount is always unsigned, and needn't be padded to result width.
if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) {
if (cell->parameters.at("\\B_SIGNED").as_bool()) {
b_expr = "asSInt(" + b_expr + ")";
// Expand the "A" operand to the result width
if (a_width < y_width) {
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
a_width = y_width;
}
if (b_padded_width < y_width) {
auto b_sig = cell->getPort("\\B");
b_padded_width = y_width;
}
// Shift amount is always unsigned, and needn't be padded to result width,
// otherwise, we need to cast the b_expr appropriately
if (b_signed && !cell->type.in("$shr", "$sshr", "$shl", "$sshl", "$pow")) {
b_expr = "asSInt(" + b_expr + ")";
// Expand the "B" operand to the result width
if (b_width < y_width) {
b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
b_width = y_width;
}
}
// For the arithmetic ops, expand operand widths to result widths befor performing the operation.
// This corresponds (according to iverilog) to what verilog compilers implement.
if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or"))
{
if (a_width < y_width) {
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
a_width = y_width;
}
if (b_width < y_width) {
b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
b_width = y_width;
}
}
// Assume the FIRRTL width is the width of "A"
firrtl_width = a_width;
auto a_sig = cell->getPort("\\A");
if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) {
a_expr = "asUInt(" + a_expr + ")";
if (cell->type == "$add") {
primop = "add";
firrtl_is_signed = a_signed | b_signed;
firrtl_width = max(a_width, b_width);
} else if (cell->type == "$sub") {
primop = "sub";
firrtl_is_signed = true;
int a_widthInc = (!a_signed && b_signed) ? 2 : (a_signed && !b_signed) ? 1 : 0;
int b_widthInc = (a_signed && !b_signed) ? 2 : (!a_signed && b_signed) ? 1 : 0;
firrtl_width = max(a_width + a_widthInc, b_width + b_widthInc);
} else if (cell->type == "$mul") {
primop = "mul";
firrtl_is_signed = a_signed | b_signed;
firrtl_width = a_width + b_width;
} else if (cell->type == "$div") {
primop = "div";
firrtl_is_signed = a_signed | b_signed;
firrtl_width = a_width;
} else if (cell->type == "$mod") {
primop = "rem";
firrtl_width = min(a_width, b_width);
} else if (cell->type == "$and") {
primop = "and";
always_uint = true;
firrtl_width = max(a_width, b_width);
}
string primop;
bool always_uint = false;
if (cell->type == "$add") primop = "add";
else if (cell->type == "$sub") primop = "sub";
else if (cell->type == "$mul") primop = "mul";
else if (cell->type == "$div") primop = "div";
else if (cell->type == "$mod") primop = "rem";
else if (cell->type == "$and") {
primop = "and";
always_uint = true;
}
else if (cell->type == "$or" ) {
primop = "or";
always_uint = true;
}
primop = "or";
always_uint = true;
firrtl_width = max(a_width, b_width);
}
else if (cell->type == "$xor") {
primop = "xor";
always_uint = true;
}
primop = "xor";
always_uint = true;
firrtl_width = max(a_width, b_width);
}
else if (cell->type == "$xnor") {
primop = "xnor";
always_uint = true;
firrtl_width = max(a_width, b_width);
}
else if ((cell->type == "$eq") | (cell->type == "$eqx")) {
primop = "eq";
always_uint = true;
}
primop = "eq";
always_uint = true;
firrtl_width = 1;
}
else if ((cell->type == "$ne") | (cell->type == "$nex")) {
primop = "neq";
always_uint = true;
}
primop = "neq";
always_uint = true;
firrtl_width = 1;
}
else if (cell->type == "$gt") {
primop = "gt";
always_uint = true;
}
primop = "gt";
always_uint = true;
firrtl_width = 1;
}
else if (cell->type == "$ge") {
primop = "geq";
always_uint = true;
}
primop = "geq";
always_uint = true;
firrtl_width = 1;
}
else if (cell->type == "$lt") {
primop = "lt";
always_uint = true;
}
primop = "lt";
always_uint = true;
firrtl_width = 1;
}
else if (cell->type == "$le") {
primop = "leq";
always_uint = true;
}
primop = "leq";
always_uint = true;
firrtl_width = 1;
}
else if ((cell->type == "$shl") | (cell->type == "$sshl")) {
// FIRRTL will widen the result (y) by the amount of the shift.
// We'll need to offset this by extracting the un-widened portion as Verilog would do.
@ -564,11 +614,14 @@ struct FirrtlWorker
auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) {
primop = "shl";
b_expr = std::to_string(b_sig.as_int());
int shift_amount = b_sig.as_int();
b_expr = std::to_string(shift_amount);
firrtl_width = a_width + shift_amount;
} else {
primop = "dshl";
// Convert from FIRRTL left shift semantics.
b_expr = gen_dshl(b_expr, b_padded_width);
b_expr = gen_dshl(b_expr, b_width);
firrtl_width = a_width + (1 << b_width) - 1;
}
}
else if ((cell->type == "$shr") | (cell->type == "$sshr")) {
@ -578,36 +631,86 @@ struct FirrtlWorker
auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) {
primop = "shr";
b_expr = std::to_string(b_sig.as_int());
int shift_amount = b_sig.as_int();
b_expr = std::to_string(shift_amount);
firrtl_width = max(1, a_width - shift_amount);
} else {
primop = "dshr";
firrtl_width = a_width;
}
// We'll need to do some special fixups if the source (and thus result) is signed.
if (firrtl_is_signed) {
// If this is a "logical" shift right, pretend the source is unsigned.
if (cell->type == "$shr") {
a_expr = "asUInt(" + a_expr + ")";
}
}
}
else if ((cell->type == "$logic_and")) {
primop = "and";
a_expr = "neq(" + a_expr + ", UInt(0))";
b_expr = "neq(" + b_expr + ", UInt(0))";
always_uint = true;
}
primop = "and";
a_expr = "neq(" + a_expr + ", UInt(0))";
b_expr = "neq(" + b_expr + ", UInt(0))";
always_uint = true;
firrtl_width = 1;
}
else if ((cell->type == "$logic_or")) {
primop = "or";
a_expr = "neq(" + a_expr + ", UInt(0))";
b_expr = "neq(" + b_expr + ", UInt(0))";
always_uint = true;
}
primop = "or";
a_expr = "neq(" + a_expr + ", UInt(0))";
b_expr = "neq(" + b_expr + ", UInt(0))";
always_uint = true;
firrtl_width = 1;
}
else if ((cell->type == "$pow")) {
if (a_sig.is_fully_const() && a_sig.as_int() == 2) {
// We'll convert this to a shift. To simplify things, change the a_expr to "1"
// so we can use b_expr directly as a shift amount.
// Only support 2 ** N (i.e., shift left)
// FIRRTL will widen the result (y) by the amount of the shift.
// We'll need to offset this by extracting the un-widened portion as Verilog would do.
a_expr = firrtl_is_signed ? "SInt(1)" : "UInt(1)";
extract_y_bits = true;
// Is the shift amount constant?
auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) {
primop = "shl";
int shiftAmount = b_sig.as_int();
if (shiftAmount < 0) {
log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, log_id(module), log_id(cell));
}
b_expr = std::to_string(shiftAmount);
firrtl_width = a_width + shiftAmount;
} else {
primop = "dshl";
// Convert from FIRRTL left shift semantics.
b_expr = gen_dshl(b_expr, b_width);
firrtl_width = a_width + (1 << b_width) - 1;
}
} else {
log_error("Non power 2: %s.%s\n", log_id(module), log_id(cell));
}
}
if (!cell->parameters.at("\\B_SIGNED").as_bool()) {
b_expr = "asUInt(" + b_expr + ")";
}
string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str());
// Deal with FIRRTL's "shift widens" semantics
if (extract_y_bits) {
expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1);
string expr;
// Deal with $xnor == ~^ (not xor)
if (primop == "xnor") {
expr = stringf("not(xor(%s, %s))", a_expr.c_str(), b_expr.c_str());
} else {
expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str());
}
if ((is_signed && !always_uint) || cell->type.in("$sub"))
// Deal with FIRRTL's "shift widens" semantics, or the need to widen the FIRRTL result.
// If the operation is signed, the FIRRTL width will be 1 one bit larger.
if (extract_y_bits) {
expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1);
} else if (firrtl_is_signed && (firrtl_width + 1) < y_width) {
expr = stringf("pad(%s, %d)", expr.c_str(), y_width);
}
if ((firrtl_is_signed && !always_uint))
expr = stringf("asUInt(%s)", expr.c_str());
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
@ -618,7 +721,6 @@ struct FirrtlWorker
if (cell->type.in("$mux"))
{
string y_id = make_id(cell->name);
int width = cell->parameters.at("\\WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A"));
string b_expr = make_expr(cell->getPort("\\B"));
@ -762,21 +864,20 @@ struct FirrtlWorker
if (clkpol == false)
log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell));
string q_id = make_id(cell->name);
int width = cell->parameters.at("\\WIDTH").as_int();
string expr = make_expr(cell->getPort("\\D"));
string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")";
wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", q_id.c_str(), width, clk_expr.c_str()));
wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", y_id.c_str(), width, clk_expr.c_str()));
cell_exprs.push_back(stringf(" %s <= %s\n", q_id.c_str(), expr.c_str()));
register_reverse_wire_map(q_id, cell->getPort("\\Q"));
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
register_reverse_wire_map(y_id, cell->getPort("\\Q"));
continue;
}
// This may be a parameterized module - paramod.
if (cell->type.substr(0, 8) == "$paramod")
if (cell->type.begins_with("$paramod"))
{
process_instance(cell, wire_exprs);
continue;
@ -785,8 +886,6 @@ struct FirrtlWorker
// assign y = a[b +: y_width];
// We'll extract the correct bits as part of the primop.
string y_id = make_id(cell->name);
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A"));
// Get the initial bit selector
string b_expr = make_expr(cell->getPort("\\B"));
@ -808,18 +907,15 @@ struct FirrtlWorker
// assign y = a >> b;
// where b may be negative
string y_id = make_id(cell->name);
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A"));
string b_expr = make_expr(cell->getPort("\\B"));
auto b_string = b_expr.c_str();
int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int();
string expr;
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
if (cell->getParam("\\B_SIGNED").as_bool()) {
// We generate a left or right shift based on the sign of b.
std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_padded_width).c_str(), y_width);
std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_width).c_str(), y_width);
std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string);
expr = stringf("mux(%s < 0, %s, %s)",
b_string,
@ -833,7 +929,21 @@ struct FirrtlWorker
register_reverse_wire_map(y_id, cell->getPort("\\Y"));
continue;
}
log_warning("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
if (cell->type == "$pos") {
// assign y = a;
// printCell(cell);
string a_expr = make_expr(cell->getPort("\\A"));
// Verilog appears to treat the result as signed, so if the result is wider than "A",
// we need to pad.
if (a_width < y_width) {
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
}
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), a_expr.c_str()));
register_reverse_wire_map(y_id, cell->getPort("\\Y"));
continue;
}
log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
}
for (auto conn : module->connections())

View File

@ -40,8 +40,8 @@ void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
for (int i = 0; i < width; i++) {
log_assert(offset+i < (int)data.bits.size());
switch (data.bits[offset+i]) {
case RTLIL::S0: break;
case RTLIL::S1: val |= 1 << i; break;
case State::S0: break;
case State::S1: val |= 1 << i; break;
default: val = -1; break;
}
}
@ -54,8 +54,8 @@ void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
for (int i = offset+width-1; i >= offset; i--) {
log_assert(i < (int)data.bits.size());
switch (data.bits[i]) {
case RTLIL::S0: f << stringf("0"); break;
case RTLIL::S1: f << stringf("1"); break;
case State::S0: f << stringf("0"); break;
case State::S1: f << stringf("1"); break;
case RTLIL::Sx: f << stringf("x"); break;
case RTLIL::Sz: f << stringf("z"); break;
case RTLIL::Sa: f << stringf("-"); break;

View File

@ -108,7 +108,7 @@ struct IntersynthBackend : public Backend {
if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design;
Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "ilang" : "verilog"));
libs.push_back(lib);
}
@ -183,7 +183,7 @@ struct IntersynthBackend : public Backend {
if (param.second.bits.size() != 32) {
node_code += stringf(" %s '", RTLIL::id2cstr(param.first));
for (int i = param.second.bits.size()-1; i >= 0; i--)
node_code += param.second.bits[i] == RTLIL::S1 ? "1" : "0";
node_code += param.second.bits[i] == State::S1 ? "1" : "0";
} else
node_code += stringf(" %s 0x%x", RTLIL::id2cstr(param.first), param.second.as_int());
}

View File

@ -83,20 +83,43 @@ struct JsonWriter
return str + " ]";
}
void write_parameter_value(const Const &value)
{
if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) {
string str = value.decode_string();
int state = 0;
for (char c : str) {
if (state == 0) {
if (c == '0' || c == '1' || c == 'x' || c == 'z')
state = 0;
else if (c == ' ')
state = 1;
else
state = 2;
} else if (state == 1 && c != ' ')
state = 2;
}
if (state < 2)
str += " ";
f << get_string(str);
} else
if (GetSize(value) == 32 && value.is_fully_def()) {
if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", value.as_int());
else
f << stringf("%u", value.as_int());
} else {
f << get_string(value.as_string());
}
}
void write_parameters(const dict<IdString, Const> &parameters, bool for_module=false)
{
bool first = true;
for (auto &param : parameters) {
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str());
if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0)
f << get_string(param.second.decode_string());
else if (GetSize(param.second.bits) > 32)
f << get_string(param.second.as_string());
else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", param.second.as_int());
else
f << stringf("%u", param.second.as_int());
write_parameter_value(param.second);
first = false;
}
}
@ -342,12 +365,13 @@ struct JsonBackend : public Backend {
log("Module and cell ports and nets can be single bit wide or vectors of multiple\n");
log("bits. Each individual signal bit is assigned a unique integer. The <bit_vector>\n");
log("values referenced above are vectors of this integers. Signal bits that are\n");
log("connected to a constant driver are denoted as string \"0\" or \"1\" instead of\n");
log("a number.\n");
log("connected to a constant driver are denoted as string \"0\", \"1\", \"x\", or\n");
log("\"z\" instead of a number.\n");
log("\n");
log("Numeric parameter and attribute values up to 32 bits are written as decimal\n");
log("values. Numbers larger than that are written as string holding the binary\n");
log("representation of the value.\n");
log("Numeric 32-bit parameter and attribute values are written as decimal values.\n");
log("Bit verctors of different sizes, or ones containing 'x' or 'z' bits, are written\n");
log("as string holding the binary representation of the value. Strings are written\n");
log("as strings, with an appended blank in cases of strings of the form /[01xz]* */.\n");
log("\n");
log("For example the following Verilog code:\n");
log("\n");

View File

@ -472,7 +472,7 @@ struct SimplecWorker
return;
}
if (cell->type == "$_MUX_")
if (cell->type.in("$_MUX_", "$_NMUX_"))
{
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
@ -484,7 +484,9 @@ struct SimplecWorker
string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0";
// casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933)
string expr = stringf("%s ? (bool)%s : (bool)%s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str());
string expr = stringf("%s ? %s(bool)%s : %s(bool)%s", s_expr.c_str(),
cell->type == "$_NMUX_" ? "!" : "", b_expr.c_str(),
cell->type == "$_NMUX_" ? "!" : "", a_expr.c_str());
log_assert(y.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +

View File

@ -510,6 +510,7 @@ struct Smt2Worker
if (cell->type == "$_ANDNOT_") return export_gate(cell, "(and A (not B))");
if (cell->type == "$_ORNOT_") return export_gate(cell, "(or A (not B))");
if (cell->type == "$_MUX_") return export_gate(cell, "(ite S B A)");
if (cell->type == "$_NMUX_") return export_gate(cell, "(not (ite S B A))");
if (cell->type == "$_AOI3_") return export_gate(cell, "(not (or (and A B) C))");
if (cell->type == "$_OAI3_") return export_gate(cell, "(not (and (or A B) C))");
if (cell->type == "$_AOI4_") return export_gate(cell, "(not (or (and A B) (and C D)))");
@ -600,7 +601,7 @@ struct Smt2Worker
if (cell->type == "$logic_and") return export_reduce(cell, "(and (or A) (or B))", false);
if (cell->type == "$logic_or") return export_reduce(cell, "(or A B)", false);
if (cell->type == "$mux" || cell->type == "$pmux")
if (cell->type.in("$mux", "$pmux"))
{
int width = GetSize(cell->getPort("\\Y"));
std::string processed_expr = get_bv(cell->getPort("\\A"));
@ -1475,7 +1476,7 @@ struct Smt2Backend : public Backend {
int indent = 0;
while (indent < GetSize(line) && (line[indent] == ' ' || line[indent] == '\t'))
indent++;
if (line.substr(indent, 2) == "%%")
if (line.compare(indent, 2, "%%") == 0)
break;
*f << line << std::endl;
}

View File

@ -61,7 +61,7 @@ struct SmvWorker
{
string name = stringf("_%s", id.c_str());
if (name.substr(0, 2) == "_\\")
if (name.compare(0, 2, "_\\") == 0)
name = "_" + name.substr(2);
for (auto &c : name) {
@ -537,6 +537,13 @@ struct SmvWorker
continue;
}
if (cell->type == "$_NMUX_")
{
definitions.push_back(stringf("%s := !(bool(%s) ? %s : %s);", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\S")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\A"))));
continue;
}
if (cell->type == "$_AOI3_")
{
definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")),

View File

@ -200,9 +200,9 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
int32_t val = 0;
for (int i = offset+width-1; i >= offset; i--) {
log_assert(i < (int)data.bits.size());
if (data.bits[i] != RTLIL::S0 && data.bits[i] != RTLIL::S1)
if (data.bits[i] != State::S0 && data.bits[i] != State::S1)
goto dump_hex;
if (data.bits[i] == RTLIL::S1)
if (data.bits[i] == State::S1)
val |= 1 << (i - offset);
}
if (decimal)
@ -219,8 +219,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
for (int i = offset; i < offset+width; i++) {
log_assert(i < (int)data.bits.size());
switch (data.bits[i]) {
case RTLIL::S0: bin_digits.push_back('0'); break;
case RTLIL::S1: bin_digits.push_back('1'); break;
case State::S0: bin_digits.push_back('0'); break;
case State::S1: bin_digits.push_back('1'); break;
case RTLIL::Sx: bin_digits.push_back('x'); break;
case RTLIL::Sz: bin_digits.push_back('z'); break;
case RTLIL::Sa: bin_digits.push_back('?'); break;
@ -273,8 +273,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
for (int i = offset+width-1; i >= offset; i--) {
log_assert(i < (int)data.bits.size());
switch (data.bits[i]) {
case RTLIL::S0: f << stringf("0"); break;
case RTLIL::S1: f << stringf("1"); break;
case State::S0: f << stringf("0"); break;
case State::S1: f << stringf("1"); break;
case RTLIL::Sx: f << stringf("x"); break;
case RTLIL::Sz: f << stringf("z"); break;
case RTLIL::Sa: f << stringf("?"); break;
@ -380,9 +380,9 @@ void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString,
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str());
f << stringf(" = ");
if (modattr && (it->second == Const(0, 1) || it->second == Const(0)))
if (modattr && (it->second == State::S0 || it->second == Const(0)))
f << stringf(" 0 ");
else if (modattr && (it->second == Const(1, 1) || it->second == Const(1)))
else if (modattr && (it->second == State::S1 || it->second == Const(1)))
f << stringf(" 1 ");
else
dump_const(f, it->second, -1, 0, false, as_comment);
@ -558,6 +558,20 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
if (cell->type == "$_NMUX_") {
f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, cell->getPort("\\Y"));
f << stringf(" = !(");
dump_cell_expr_port(f, cell, "S", false);
f << stringf(" ? ");
dump_attributes(f, "", cell->attributes, ' ');
dump_cell_expr_port(f, cell, "B", false);
f << stringf(" : ");
dump_cell_expr_port(f, cell, "A", false);
f << stringf(");\n");
return true;
}
if (cell->type.in("$_AOI3_", "$_OAI3_")) {
f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, cell->getPort("\\Y"));
@ -590,7 +604,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
if (cell->type.substr(0, 6) == "$_DFF_")
if (cell->type.begins_with("$_DFF_"))
{
std::string reg_name = cellname(cell);
bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name);
@ -631,7 +645,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
if (cell->type.substr(0, 8) == "$_DFFSR_")
if (cell->type.begins_with("$_DFFSR_"))
{
char pol_c = cell->type[8], pol_s = cell->type[9], pol_r = cell->type[10];
@ -935,7 +949,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
if (cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffe")
if (cell->type.in("$dff", "$adff", "$dffe"))
{
RTLIL::SigSpec sig_clk, sig_arst, sig_en, val_arst;
bool pol_clk, pol_arst = false, pol_en = false;

8
examples/mimas2/README Normal file
View File

@ -0,0 +1,8 @@
A simple example design, based on the Numato Labs Mimas V2 board
================================================================
This example uses Yosys for synthesis and Xilinx ISE
for place&route and bit-stream creation.
To synthesize:
bash run.sh

View File

@ -0,0 +1,13 @@
CONFIG VCCAUX = "3.3" ;
NET "CLK" LOC = D9 | IOSTANDARD = LVCMOS33 | PERIOD = 12MHz ;
NET "LED[7]" LOC = P15 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LED[6]" LOC = P16 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LED[5]" LOC = N15 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LED[4]" LOC = N16 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LED[3]" LOC = U17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LED[2]" LOC = U18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LED[1]" LOC = T17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LED[0]" LOC = T18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

14
examples/mimas2/example.v Normal file
View File

@ -0,0 +1,14 @@
module example(
input wire CLK,
output wire [7:0] LED
);
reg [27:0] ctr;
initial ctr = 0;
always @(posedge CLK)
ctr <= ctr + 1;
assign LED = ctr[27:20];
endmodule

8
examples/mimas2/run.sh Normal file
View File

@ -0,0 +1,8 @@
#!/bin/sh
set -e
yosys run_yosys.ys
edif2ngd example.edif
ngdbuild example -uc example.ucf -p xc6slx9csg324-3
map -w example
par -w example.ncd example_par.ncd
bitgen -w example_par.ncd -g StartupClk:JTAGClk

View File

@ -0,0 +1,4 @@
read_verilog example.v
synth_xilinx -top example -family xc6s
iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I
write_edif -pvector bra example.edif

View File

@ -30,6 +30,7 @@
#include <libkern/OSByteOrder.h>
#define __builtin_bswap32 OSSwapInt32
#endif
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include "kernel/yosys.h"
@ -66,7 +67,7 @@ struct ConstEvalAig
continue;
for (auto &it2 : it.second->connections())
if (yosys_celltypes.cell_output(it.second->type, it2.first)) {
auto r = sig2driver.insert(std::make_pair(it2.second, it.second));
auto r YS_ATTRIBUTE(unused) = sig2driver.insert(std::make_pair(it2.second, it.second));
log_assert(r.second);
}
}
@ -151,12 +152,12 @@ struct ConstEvalAig
RTLIL::State eval_ret = RTLIL::Sx;
if (cell->type == "$_NOT_") {
if (sig_a == RTLIL::S0) eval_ret = RTLIL::S1;
else if (sig_a == RTLIL::S1) eval_ret = RTLIL::S0;
if (sig_a == State::S0) eval_ret = State::S1;
else if (sig_a == State::S1) eval_ret = State::S0;
}
else if (cell->type == "$_AND_") {
if (sig_a == RTLIL::S0) {
eval_ret = RTLIL::S0;
if (sig_a == State::S0) {
eval_ret = State::S0;
goto eval_end;
}
@ -164,15 +165,15 @@ struct ConstEvalAig
RTLIL::SigBit sig_b = cell->getPort("\\B");
if (!eval(sig_b))
return false;
if (sig_b == RTLIL::S0) {
eval_ret = RTLIL::S0;
if (sig_b == State::S0) {
eval_ret = State::S0;
goto eval_end;
}
if (sig_a != RTLIL::S1 || sig_b != RTLIL::S1)
if (sig_a != State::S1 || sig_b != State::S1)
goto eval_end;
eval_ret = RTLIL::S1;
eval_ret = State::S1;
}
}
else log_abort();
@ -256,7 +257,7 @@ end_of_header:
RTLIL::Wire* n0 = module->wire("\\__0__");
if (n0)
module->connect(n0, RTLIL::S0);
module->connect(n0, State::S0);
// Parse footer (symbol table, comments, etc.)
unsigned l1;
@ -301,7 +302,11 @@ static uint32_t parse_xaiger_literal(std::istream &f)
uint32_t l;
f.read(reinterpret_cast<char*>(&l), sizeof(l));
if (f.gcount() != sizeof(l))
#if defined(_WIN32) && defined(__MINGW32__)
log_error("Offset %I64d: unable to read literal!\n", static_cast<int64_t>(f.tellg()));
#else
log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast<int64_t>(f.tellg()));
#endif
return from_big_endian(l);
}
@ -333,7 +338,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera
return wire;
}
void AigerReader::parse_xaiger()
void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
{
std::string header;
f >> header;
@ -367,22 +372,7 @@ void AigerReader::parse_xaiger()
RTLIL::Wire* n0 = module->wire("\\__0__");
if (n0)
module->connect(n0, RTLIL::S0);
dict<int,IdString> box_lookup;
for (auto m : design->modules()) {
auto it = m->attributes.find("\\abc_box_id");
if (it == m->attributes.end())
continue;
if (m->name.begins_with("$paramod"))
continue;
auto id = it->second.as_int();
auto r = box_lookup.insert(std::make_pair(id, m->name));
if (!r.second)
log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n",
log_id(m), id, log_id(r.first->second));
log_assert(r.second);
}
module->connect(n0, State::S0);
// Parse footer (symbol table, comments, etc.)
std::string s;
@ -399,9 +389,9 @@ void AigerReader::parse_xaiger()
f.ignore(1);
// XAIGER extensions
if (c == 'm') {
uint32_t dataSize = parse_xaiger_literal(f);
uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
uint32_t lutNum = parse_xaiger_literal(f);
uint32_t lutSize = parse_xaiger_literal(f);
uint32_t lutSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize);
ConstEvalAig ce(module);
for (unsigned i = 0; i < lutNum; ++i) {
@ -426,7 +416,7 @@ void AigerReader::parse_xaiger()
int gray = j ^ (j >> 1);
ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast<int>(cutLeavesM)});
RTLIL::SigBit o(output_sig);
bool success = ce.eval(o);
bool success YS_ATTRIBUTE(unused) = ce.eval(o);
log_assert(success);
log_assert(o.wire == nullptr);
lut_mask[gray] = o.data;
@ -438,7 +428,7 @@ void AigerReader::parse_xaiger()
}
}
else if (c == 'r') {
uint32_t dataSize = parse_xaiger_literal(f);
uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
flopNum = parse_xaiger_literal(f);
log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
f.ignore(flopNum * sizeof(uint32_t));
@ -450,18 +440,18 @@ void AigerReader::parse_xaiger()
}
else if (c == 'h') {
f.ignore(sizeof(uint32_t));
uint32_t version = parse_xaiger_literal(f);
uint32_t version YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
log_assert(version == 1);
uint32_t ciNum = parse_xaiger_literal(f);
uint32_t ciNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
log_debug("ciNum = %u\n", ciNum);
uint32_t coNum = parse_xaiger_literal(f);
uint32_t coNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
log_debug("coNum = %u\n", coNum);
piNum = parse_xaiger_literal(f);
log_debug("piNum = %u\n", piNum);
uint32_t poNum = parse_xaiger_literal(f);
uint32_t poNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
log_debug("poNum = %u\n", poNum);
uint32_t boxNum = parse_xaiger_literal(f);
log_debug("boxNum = %u\n", poNum);
log_debug("boxNum = %u\n", boxNum);
for (unsigned i = 0; i < boxNum; i++) {
f.ignore(2*sizeof(uint32_t));
uint32_t boxUniqueId = parse_xaiger_literal(f);
@ -531,9 +521,9 @@ void AigerReader::parse_aiger_ascii()
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0)
q_wire->attributes["\\init"] = RTLIL::S0;
q_wire->attributes["\\init"] = State::S0;
else if (l3 == 1)
q_wire->attributes["\\init"] = RTLIL::S1;
q_wire->attributes["\\init"] = State::S1;
else if (l3 == l1) {
//q_wire->attributes["\\init"] = RTLIL::Sx;
}
@ -542,7 +532,7 @@ void AigerReader::parse_aiger_ascii()
}
else {
// AIGER latches are assumed to be initialized to zero
q_wire->attributes["\\init"] = RTLIL::S0;
q_wire->attributes["\\init"] = State::S0;
}
latches.push_back(q_wire);
}
@ -656,9 +646,9 @@ void AigerReader::parse_aiger_binary()
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0)
q_wire->attributes["\\init"] = RTLIL::S0;
q_wire->attributes["\\init"] = State::S0;
else if (l3 == 1)
q_wire->attributes["\\init"] = RTLIL::S1;
q_wire->attributes["\\init"] = State::S1;
else if (l3 == l1) {
//q_wire->attributes["\\init"] = RTLIL::Sx;
}
@ -667,7 +657,7 @@ void AigerReader::parse_aiger_binary()
}
else {
// AIGER latches are assumed to be initialized to zero
q_wire->attributes["\\init"] = RTLIL::S0;
q_wire->attributes["\\init"] = State::S0;
}
latches.push_back(q_wire);
}
@ -911,9 +901,6 @@ void AigerReader::post_process()
RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable));
if (cell) { // ABC could have optimised this box away
module->rename(cell, escaped_s);
RTLIL::Module* box_module = design->module(cell->type);
log_assert(box_module);
for (const auto &i : cell->connections()) {
RTLIL::IdString port_name = i.first;
RTLIL::SigSpec rhs = i.second;
@ -982,16 +969,17 @@ void AigerReader::post_process()
}
module->fixup_ports();
// Insert into a new (temporary) design so that "clean" will only
// operate (and run checks on) this one module
RTLIL::Design *mapped_design = new RTLIL::Design;
mapped_design->add(module);
Pass::call(mapped_design, "clean");
mapped_design->modules_.erase(module->name);
delete mapped_design;
design->add(module);
design->selection_stack.emplace_back(false);
RTLIL::Selection& sel = design->selection_stack.back();
sel.select(module);
Pass::call(design, "clean");
design->selection_stack.pop_back();
for (auto cell : module->cells().to_vector()) {
if (cell->type != "$lut") continue;
auto y_port = cell->getPort("\\Y").as_bit();

View File

@ -47,7 +47,7 @@ struct AigerReader
AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports);
void parse_aiger();
void parse_xaiger();
void parse_xaiger(const dict<int,IdString> &box_lookup);
void parse_aiger_ascii();
void parse_aiger_binary();
void post_process();

View File

@ -283,8 +283,8 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
if (!bits.empty()) {
fprintf(f, " bits='");
for (size_t i = bits.size(); i > 0; i--)
fprintf(f, "%c", bits[i-1] == RTLIL::S0 ? '0' :
bits[i-1] == RTLIL::S1 ? '1' :
fprintf(f, "%c", bits[i-1] == State::S0 ? '0' :
bits[i-1] == State::S1 ? '1' :
bits[i-1] == RTLIL::Sx ? 'x' :
bits[i-1] == RTLIL::Sz ? 'z' : '?');
fprintf(f, "'(%d)", GetSize(bits));
@ -716,7 +716,7 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
node->integer = v;
node->is_signed = is_signed;
for (int i = 0; i < width; i++) {
node->bits.push_back((v & 1) ? RTLIL::S1 : RTLIL::S0);
node->bits.push_back((v & 1) ? State::S1 : State::S0);
v = v >> 1;
}
node->range_valid = true;
@ -733,9 +733,9 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
node->bits = v;
for (size_t i = 0; i < 32; i++) {
if (i < node->bits.size())
node->integer |= (node->bits[i] == RTLIL::S1) << i;
node->integer |= (node->bits[i] == State::S1) << i;
else if (is_signed && !node->bits.empty())
node->integer |= (node->bits.back() == RTLIL::S1) << i;
node->integer |= (node->bits.back() == State::S1) << i;
}
node->range_valid = true;
node->range_left = node->bits.size()-1;
@ -767,7 +767,7 @@ AstNode *AstNode::mkconst_str(const std::string &str)
for (size_t i = 0; i < str.size(); i++) {
unsigned char ch = str[str.size() - i - 1];
for (int j = 0; j < 8; j++) {
data.push_back((ch & 1) ? RTLIL::S1 : RTLIL::S0);
data.push_back((ch & 1) ? State::S1 : State::S0);
ch = ch >> 1;
}
}
@ -780,7 +780,7 @@ AstNode *AstNode::mkconst_str(const std::string &str)
bool AstNode::bits_only_01() const
{
for (auto bit : bits)
if (bit != RTLIL::S0 && bit != RTLIL::S1)
if (bit != State::S0 && bit != State::S1)
return false;
return true;
}
@ -1164,7 +1164,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
}
}
if (flag_icells && (*it)->str.substr(0, 2) == "\\$")
if (flag_icells && (*it)->str.compare(0, 2, "\\$") == 0)
(*it)->str = (*it)->str.substr(1);
if (defer)
@ -1172,7 +1172,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
if (design->has((*it)->str)) {
RTLIL::Module *existing_mod = design->module((*it)->str);
if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str());
} else if (nooverwrite) {
log("Ignoring re-definition of module `%s' at %s:%d.\n",
@ -1463,7 +1463,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
{
std::string stripped_name = name.str();
if (stripped_name.substr(0, 9) == "$abstract")
if (stripped_name.compare(0, 9, "$abstract") == 0)
stripped_name = stripped_name.substr(9);
log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
@ -1551,7 +1551,9 @@ RTLIL::Module *AstModule::clone() const
new_mod->nomeminit = nomeminit;
new_mod->nomem2reg = nomem2reg;
new_mod->mem2reg = mem2reg;
new_mod->noblackbox = noblackbox;
new_mod->lib = lib;
new_mod->nowb = nowb;
new_mod->noopt = noopt;
new_mod->icells = icells;
new_mod->pwires = pwires;

View File

@ -1516,7 +1516,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
AstNode *child = *it;
if (child->type == AST_CELLTYPE) {
cell->type = child->str;
if (flag_icells && cell->type.substr(0, 2) == "\\$")
if (flag_icells && cell->type.begins_with("\\$"))
cell->type = cell->type.substr(1);
continue;
}

View File

@ -2319,7 +2319,7 @@ skip_dynamic_range_lvalue_expansion:;
if (attr.first.str().rfind("\\via_celltype_defparam_", 0) == 0)
{
AstNode *cell_arg = new AstNode(AST_PARASET, attr.second->clone());
cell_arg->str = RTLIL::escape_id(attr.first.str().substr(strlen("\\via_celltype_defparam_")));
cell_arg->str = RTLIL::escape_id(attr.first.substr(strlen("\\via_celltype_defparam_")));
cell->children.push_back(cell_arg);
}
@ -2793,13 +2793,13 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
std::getline(f, line);
for (int i = 0; i < GetSize(line); i++) {
if (in_comment && line.substr(i, 2) == "*/") {
if (in_comment && line.compare(i, 2, "*/") == 0) {
line[i] = ' ';
line[i+1] = ' ';
in_comment = false;
continue;
}
if (!in_comment && line.substr(i, 2) == "/*")
if (!in_comment && line.compare(i, 2, "/*") == 0)
in_comment = true;
if (in_comment)
line[i] = ' ';
@ -2808,7 +2808,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
while (1)
{
token = next_token(line, " \t\r\n");
if (token.empty() || token.substr(0, 2) == "//")
if (token.empty() || token.compare(0, 2, "//") == 0)
break;
if (token[0] == '@') {
@ -3439,19 +3439,11 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
{
std::map<std::string, AstNode*> backup_scope;
std::map<std::string, AstNode::varinfo_t> variables;
bool delete_temp_block = false;
AstNode *block = NULL;
AstNode *block = new AstNode(AST_BLOCK);
size_t argidx = 0;
for (auto child : children)
{
if (child->type == AST_BLOCK)
{
log_assert(block == NULL);
block = child;
continue;
}
if (child->type == AST_WIRE)
{
while (child->simplify(true, false, false, 1, -1, false, true)) { }
@ -3468,13 +3460,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue;
}
log_assert(block == NULL);
delete_temp_block = true;
block = new AstNode(AST_BLOCK);
block->children.push_back(child->clone());
}
log_assert(block != NULL);
log_assert(variables.count(str) != 0);
while (!block->children.empty())
@ -3642,8 +3630,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
log_abort();
}
if (delete_temp_block)
delete block;
delete block;
for (auto &it : backup_scope)
if (it.second == NULL)

View File

@ -78,7 +78,7 @@ failed:
return std::pair<RTLIL::IdString, int>("\\" + name, 0);
}
void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean, bool sop_mode, bool wideports)
void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool run_clean, bool sop_mode, bool wideports)
{
RTLIL::Module *module = nullptr;
RTLIL::Const *lutptr = NULL;

View File

@ -24,7 +24,7 @@
YOSYS_NAMESPACE_BEGIN
extern void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name,
extern void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name,
bool run_clean = false, bool sop_mode = false, bool wideports = false);
YOSYS_NAMESPACE_END

View File

@ -25,7 +25,7 @@ struct JsonNode
{
char type; // S=String, N=Number, A=Array, D=Dict
string data_string;
int data_number;
int64_t data_number;
vector<JsonNode*> data_array;
dict<string, JsonNode*> data_dict;
vector<string> data_dict_keys;
@ -206,6 +206,38 @@ struct JsonNode
}
};
Const json_parse_attr_param_value(JsonNode *node)
{
Const value;
if (node->type == 'S') {
string &s = node->data_string;
size_t cursor = s.find_first_not_of("01xz");
if (cursor == string::npos) {
value = Const::from_string(s);
} else if (s.find_first_not_of(' ', cursor) == string::npos) {
value = Const(s.substr(0, GetSize(s)-1));
} else {
value = Const(s);
}
} else
if (node->type == 'N') {
value = Const(node->data_number, 32);
if (node->data_number < 0)
value.flags |= RTLIL::CONST_FLAG_SIGNED;
} else
if (node->type == 'A') {
log_error("JSON attribute or parameter value is an array.\n");
} else
if (node->type == 'D') {
log_error("JSON attribute or parameter value is a dict.\n");
} else {
log_abort();
}
return value;
}
void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
{
if (node->type != 'D')
@ -214,28 +246,7 @@ void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
for (auto it : node->data_dict)
{
IdString key = RTLIL::escape_id(it.first.c_str());
JsonNode *value_node = it.second;
Const value;
if (value_node->type == 'S') {
string &s = value_node->data_string;
if (s.find_first_not_of("01xz") == string::npos)
value = Const::from_string(s);
else
value = Const(s);
} else
if (value_node->type == 'N') {
value = Const(value_node->data_number, 32);
} else
if (value_node->type == 'A') {
log_error("JSON attribute or parameter value is an array.\n");
} else
if (value_node->type == 'D') {
log_error("JSON attribute or parameter value is a dict.\n");
} else {
log_abort();
}
Const value = json_parse_attr_param_value(it.second);
results[key] = value;
}
}

View File

@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <stdlib.h>
#include <stdio.h>
@ -111,9 +112,10 @@ string get_full_netlist_name(Netlist *nl)
// ==================================================================
VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover) :
VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit) :
mode_gates(mode_gates), mode_keep(mode_keep), mode_nosva(mode_nosva),
mode_names(mode_names), mode_verific(mode_verific), mode_autocover(mode_autocover)
mode_names(mode_names), mode_verific(mode_verific), mode_autocover(mode_autocover),
mode_fullinit(mode_fullinit)
{
}
@ -1454,6 +1456,50 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
merge_past_ffs(past_ffs);
}
if (!mode_fullinit)
{
pool<SigBit> non_ff_bits;
CellTypes ff_types;
ff_types.setup_internals_ff();
ff_types.setup_stdcells_mem();
for (auto cell : module->cells())
{
if (ff_types.cell_known(cell->type))
continue;
for (auto conn : cell->connections())
{
if (!cell->output(conn.first))
continue;
for (auto bit : conn.second)
if (bit.wire != nullptr)
non_ff_bits.insert(bit);
}
}
for (auto wire : module->wires())
{
if (!wire->attributes.count("\\init"))
continue;
Const &initval = wire->attributes.at("\\init");
for (int i = 0; i < GetSize(initval); i++)
{
if (initval[i] != State::S0 && initval[i] != State::S1)
continue;
if (non_ff_bits.count(SigBit(wire, i)))
initval[i] = State::Sx;
}
if (initval.is_fully_undef())
wire->attributes.erase("\\init");
}
}
}
// ==================================================================
@ -1743,7 +1789,7 @@ struct VerificExtNets
new_net = new Net(name.c_str());
nl->Add(new_net);
Net *n = route_up(new_net, port->IsOutput(), ca_nl, ca_net);
Net *n YS_ATTRIBUTE(unused) = route_up(new_net, port->IsOutput(), ca_nl, ca_net);
log_assert(n == ca_net);
}
@ -1829,7 +1875,7 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par
while (!nl_todo.empty()) {
Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0) {
VerificImporter importer(false, false, false, false, false, false);
VerificImporter importer(false, false, false, false, false, false, false);
importer.import_netlist(design, nl, nl_todo);
}
nl_todo.erase(nl);
@ -1952,6 +1998,9 @@ struct VerificPass : public Pass {
log(" -autocover\n");
log(" Generate automatic cover statements for all asserts\n");
log("\n");
log(" -fullinit\n");
log(" Keep all register initializations, even those for non-FF registers.\n");
log("\n");
log(" -chparam name value \n");
log(" Elaborate the specified top modules (all modules when -all given) using\n");
log(" this parameter value. Modules on which this parameter does not exist will\n");
@ -2140,7 +2189,7 @@ struct VerificPass : public Pass {
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++) {
for (argidx++; argidx < GetSize(args) && GetSize(args[argidx]) >= 2 && args[argidx].compare(0, 2, "-D") == 0; argidx++) {
std::string name = args[argidx].substr(2);
if (args[argidx] == "-D") {
if (++argidx >= GetSize(args))
@ -2213,7 +2262,7 @@ struct VerificPass : public Pass {
std::set<Netlist*> nl_todo, nl_done;
bool mode_all = false, mode_gates = false, mode_keep = false;
bool mode_nosva = false, mode_names = false, mode_verific = false;
bool mode_autocover = false;
bool mode_autocover = false, mode_fullinit = false;
bool flatten = false, extnets = false;
string dumpfile;
Map parameters(STRING_HASH);
@ -2255,6 +2304,10 @@ struct VerificPass : public Pass {
mode_autocover = true;
continue;
}
if (args[argidx] == "-fullinit") {
mode_fullinit = true;
continue;
}
if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) {
const std::string &key = args[++argidx];
const std::string &value = args[++argidx];
@ -2283,7 +2336,7 @@ struct VerificPass : public Pass {
break;
}
if (argidx > GetSize(args) && args[argidx].substr(0, 1) == "-")
if (argidx > GetSize(args) && args[argidx].compare(0, 1, "-") == 0)
cmd_error(args, argidx, "unknown option");
if (mode_all)
@ -2378,7 +2431,7 @@ struct VerificPass : public Pass {
Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0) {
VerificImporter importer(mode_gates, mode_keep, mode_nosva,
mode_names, mode_verific, mode_autocover);
mode_names, mode_verific, mode_autocover, mode_fullinit);
importer.import_netlist(design, nl, nl_todo);
}
nl_todo.erase(nl);
@ -2484,7 +2537,7 @@ struct ReadPass : public Pass {
args[0] = "verific";
} else {
args[0] = "read_verilog";
args.erase(args.begin()+1, args.begin()+2);
args[1] = "-defer";
}
Pass::call(design, args);
return;
@ -2498,6 +2551,7 @@ struct ReadPass : public Pass {
if (args[1] == "-formal")
args.insert(args.begin()+1, std::string());
args[1] = "-sv";
args.insert(args.begin()+1, "-defer");
}
Pass::call(design, args);
return;

View File

@ -72,9 +72,9 @@ struct VerificImporter
pool<Verific::Net*, hash_ptr_ops> any_all_nets;
bool mode_gates, mode_keep, mode_nosva, mode_names, mode_verific;
bool mode_autocover;
bool mode_autocover, mode_fullinit;
VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover);
VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit);
RTLIL::SigBit net_map_at(Verific::Net *net);

View File

@ -357,7 +357,7 @@ struct SvaFsm
for (int i = 0; i < GetSize(nodes); i++)
{
if (next_state_sig[i] != State::S0) {
clocking.addDff(NEW_ID, next_state_sig[i], state_wire[i], Const(0, 1));
clocking.addDff(NEW_ID, next_state_sig[i], state_wire[i], State::S0);
} else {
module->connect(state_wire[i], State::S0);
}

View File

@ -99,7 +99,7 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
if (base == 10) {
while (!digits.empty())
data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0);
data.push_back(my_decimal_div_by_two(digits) ? State::S1 : State::S0);
} else {
int bits_per_digit = my_ilog2(base-1);
for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) {
@ -115,17 +115,17 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
else if (*it == 0xf2)
data.push_back(RTLIL::Sa);
else
data.push_back((*it & bitmask) ? RTLIL::S1 : RTLIL::S0);
data.push_back((*it & bitmask) ? State::S1 : State::S0);
}
}
}
int len = GetSize(data);
RTLIL::State msb = data.empty() ? RTLIL::S0 : data.back();
RTLIL::State msb = data.empty() ? State::S0 : data.back();
if (len_in_bits < 0) {
if (len < 32)
data.resize(32, msb == RTLIL::S0 || msb == RTLIL::S1 ? RTLIL::S0 : msb);
data.resize(32, msb == State::S0 || msb == State::S1 ? RTLIL::S0 : msb);
return;
}
@ -133,11 +133,11 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
log_file_error(current_filename, get_line_num(), "Unsized constant must have width of 1 bit, but have %d bits!\n", len);
for (len = len - 1; len >= 0; len--)
if (data[len] == RTLIL::S1)
if (data[len] == State::S1)
break;
if (msb == RTLIL::S0 || msb == RTLIL::S1) {
if (msb == State::S0 || msb == State::S1) {
len += 1;
data.resize(len_in_bits, RTLIL::S0);
data.resize(len_in_bits, State::S0);
} else {
len += 2;
data.resize(len_in_bits, msb);
@ -169,7 +169,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
for (int i = 0; i < len; i++) {
unsigned char ch = str[len - i];
for (int j = 0; j < 8; j++) {
data.push_back((ch & 1) ? RTLIL::S1 : RTLIL::S0);
data.push_back((ch & 1) ? State::S1 : State::S0);
ch = ch >> 1;
}
}
@ -190,8 +190,8 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
if (*endptr == 0) {
std::vector<RTLIL::State> data;
my_strtobin(data, str, -1, 10, case_type, false);
if (data.back() == RTLIL::S1)
data.push_back(RTLIL::S0);
if (data.back() == State::S1)
data.push_back(State::S0);
return AstNode::mkconst_bits(data, true);
}
@ -237,8 +237,8 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
}
}
if (len_in_bits < 0) {
if (is_signed && data.back() == RTLIL::S1)
data.push_back(RTLIL::S0);
if (is_signed && data.back() == State::S1)
data.push_back(State::S0);
}
return AstNode::mkconst_bits(data, is_signed, is_unsized);
}

View File

@ -70,6 +70,9 @@ YOSYS_NAMESPACE_END
#define YY_INPUT(buf,result,max_size) \
result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
#undef YY_BUF_SIZE
#define YY_BUF_SIZE 65536
%}
%option yylineno

View File

@ -274,7 +274,7 @@ hierarchical_id:
$$ = $1;
} |
hierarchical_id TOK_PACKAGESEP TOK_ID {
if ($3->substr(0, 1) == "\\")
if ($3->compare(0, 1, "\\") == 0)
*$1 += "::" + $3->substr(1);
else
*$1 += "::" + *$3;
@ -282,7 +282,7 @@ hierarchical_id:
$$ = $1;
} |
hierarchical_id '.' TOK_ID {
if ($3->substr(0, 1) == "\\")
if ($3->compare(0, 1, "\\") == 0)
*$1 += "." + $3->substr(1);
else
*$1 += "." + *$3;
@ -2184,7 +2184,7 @@ basic_expr:
$$ = $1;
} |
'(' expr ')' TOK_CONSTVAL {
if ($4->substr(0, 1) != "'")
if ($4->compare(0, 1, "'") != 0)
frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());
AstNode *bits = $2;
AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
@ -2194,7 +2194,7 @@ basic_expr:
delete $4;
} |
hierarchical_id TOK_CONSTVAL {
if ($2->substr(0, 1) != "'")
if ($2->compare(0, 1, "'") != 0)
frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());
AstNode *bits = new AstNode(AST_IDENTIFIER);
bits->str = *$1;

View File

@ -268,9 +268,9 @@ Aig::Aig(Cell *cell)
cell->parameters.sort();
for (auto p : cell->parameters)
{
if (p.first == "\\A_WIDTH" && mkname_a_signed) {
if (p.first == ID(A_WIDTH) && mkname_a_signed) {
name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U');
} else if (p.first == "\\B_WIDTH" && mkname_b_signed) {
} else if (p.first == ID(B_WIDTH) && mkname_b_signed) {
name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U');
} else {
mkname_last = name;
@ -280,181 +280,183 @@ Aig::Aig(Cell *cell)
mkname_a_signed = false;
mkname_b_signed = false;
mkname_is_signed = false;
if (p.first == "\\A_SIGNED") {
if (p.first == ID(A_SIGNED)) {
mkname_a_signed = true;
mkname_is_signed = p.second.as_bool();
}
if (p.first == "\\B_SIGNED") {
if (p.first == ID(B_SIGNED)) {
mkname_b_signed = true;
mkname_is_signed = p.second.as_bool();
}
}
if (cell->type.in("$not", "$_NOT_", "$pos", "$_BUF_"))
if (cell->type.in(ID($not), ID($_NOT_), ID($pos), ID($_BUF_)))
{
for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
int A = mk.inport("\\A", i);
int Y = cell->type.in("$not", "$_NOT_") ? mk.not_gate(A) : A;
mk.outport(Y, "\\Y", i);
for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
int A = mk.inport(ID::A, i);
int Y = cell->type.in(ID($not), ID($_NOT_)) ? mk.not_gate(A) : A;
mk.outport(Y, ID::Y, i);
}
goto optimize;
}
if (cell->type.in("$and", "$_AND_", "$_NAND_", "$or", "$_OR_", "$_NOR_", "$xor", "$xnor", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_"))
if (cell->type.in(ID($and), ID($_AND_), ID($_NAND_), ID($or), ID($_OR_), ID($_NOR_), ID($xor), ID($xnor), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)))
{
for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
int A = mk.inport("\\A", i);
int B = mk.inport("\\B", i);
int Y = cell->type.in("$and", "$_AND_") ? mk.and_gate(A, B) :
cell->type.in("$_NAND_") ? mk.nand_gate(A, B) :
cell->type.in("$or", "$_OR_") ? mk.or_gate(A, B) :
cell->type.in("$_NOR_") ? mk.nor_gate(A, B) :
cell->type.in("$xor", "$_XOR_") ? mk.xor_gate(A, B) :
cell->type.in("$xnor", "$_XNOR_") ? mk.xnor_gate(A, B) :
cell->type.in("$_ANDNOT_") ? mk.andnot_gate(A, B) :
cell->type.in("$_ORNOT_") ? mk.ornot_gate(A, B) : -1;
mk.outport(Y, "\\Y", i);
for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
int A = mk.inport(ID::A, i);
int B = mk.inport(ID::B, i);
int Y = cell->type.in(ID($and), ID($_AND_)) ? mk.and_gate(A, B) :
cell->type.in(ID($_NAND_)) ? mk.nand_gate(A, B) :
cell->type.in(ID($or), ID($_OR_)) ? mk.or_gate(A, B) :
cell->type.in(ID($_NOR_)) ? mk.nor_gate(A, B) :
cell->type.in(ID($xor), ID($_XOR_)) ? mk.xor_gate(A, B) :
cell->type.in(ID($xnor), ID($_XNOR_)) ? mk.xnor_gate(A, B) :
cell->type.in(ID($_ANDNOT_)) ? mk.andnot_gate(A, B) :
cell->type.in(ID($_ORNOT_)) ? mk.ornot_gate(A, B) : -1;
mk.outport(Y, ID::Y, i);
}
goto optimize;
}
if (cell->type.in("$mux", "$_MUX_"))
if (cell->type.in(ID($mux), ID($_MUX_)))
{
int S = mk.inport("\\S");
for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
int A = mk.inport("\\A", i);
int B = mk.inport("\\B", i);
int S = mk.inport(ID(S));
for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
int A = mk.inport(ID::A, i);
int B = mk.inport(ID::B, i);
int Y = mk.mux_gate(A, B, S);
mk.outport(Y, "\\Y", i);
if (cell->type == ID($_NMUX_))
Y = mk.not_gate(Y);
mk.outport(Y, ID::Y, i);
}
goto optimize;
}
if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool"))
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool)))
{
int Y = mk.inport("\\A", 0);
for (int i = 1; i < GetSize(cell->getPort("\\A")); i++) {
int A = mk.inport("\\A", i);
if (cell->type == "$reduce_and") Y = mk.and_gate(A, Y);
if (cell->type == "$reduce_or") Y = mk.or_gate(A, Y);
if (cell->type == "$reduce_bool") Y = mk.or_gate(A, Y);
if (cell->type == "$reduce_xor") Y = mk.xor_gate(A, Y);
if (cell->type == "$reduce_xnor") Y = mk.xor_gate(A, Y);
int Y = mk.inport(ID::A, 0);
for (int i = 1; i < GetSize(cell->getPort(ID::A)); i++) {
int A = mk.inport(ID::A, i);
if (cell->type == ID($reduce_and)) Y = mk.and_gate(A, Y);
if (cell->type == ID($reduce_or)) Y = mk.or_gate(A, Y);
if (cell->type == ID($reduce_bool)) Y = mk.or_gate(A, Y);
if (cell->type == ID($reduce_xor)) Y = mk.xor_gate(A, Y);
if (cell->type == ID($reduce_xnor)) Y = mk.xor_gate(A, Y);
}
if (cell->type == "$reduce_xnor")
if (cell->type == ID($reduce_xnor))
Y = mk.not_gate(Y);
mk.outport(Y, "\\Y", 0);
for (int i = 1; i < GetSize(cell->getPort("\\Y")); i++)
mk.outport(mk.bool_node(false), "\\Y", i);
mk.outport(Y, ID::Y, 0);
for (int i = 1; i < GetSize(cell->getPort(ID::Y)); i++)
mk.outport(mk.bool_node(false), ID::Y, i);
goto optimize;
}
if (cell->type.in("$logic_not", "$logic_and", "$logic_or"))
if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or)))
{
int A = mk.inport("\\A", 0), Y = -1;
for (int i = 1; i < GetSize(cell->getPort("\\A")); i++)
A = mk.or_gate(mk.inport("\\A", i), A);
if (cell->type.in("$logic_and", "$logic_or")) {
int B = mk.inport("\\B", 0);
for (int i = 1; i < GetSize(cell->getPort("\\B")); i++)
B = mk.or_gate(mk.inport("\\B", i), B);
if (cell->type == "$logic_and") Y = mk.and_gate(A, B);
if (cell->type == "$logic_or") Y = mk.or_gate(A, B);
int A = mk.inport(ID::A, 0), Y = -1;
for (int i = 1; i < GetSize(cell->getPort(ID::A)); i++)
A = mk.or_gate(mk.inport(ID::A, i), A);
if (cell->type.in(ID($logic_and), ID($logic_or))) {
int B = mk.inport(ID::B, 0);
for (int i = 1; i < GetSize(cell->getPort(ID::B)); i++)
B = mk.or_gate(mk.inport(ID::B, i), B);
if (cell->type == ID($logic_and)) Y = mk.and_gate(A, B);
if (cell->type == ID($logic_or)) Y = mk.or_gate(A, B);
} else {
if (cell->type == "$logic_not") Y = mk.not_gate(A);
if (cell->type == ID($logic_not)) Y = mk.not_gate(A);
}
mk.outport_bool(Y, "\\Y");
mk.outport_bool(Y, ID::Y);
goto optimize;
}
if (cell->type.in("$add", "$sub"))
if (cell->type.in(ID($add), ID($sub)))
{
int width = GetSize(cell->getPort("\\Y"));
vector<int> A = mk.inport_vec("\\A", width);
vector<int> B = mk.inport_vec("\\B", width);
int width = GetSize(cell->getPort(ID::Y));
vector<int> A = mk.inport_vec(ID::A, width);
vector<int> B = mk.inport_vec(ID::B, width);
int carry = mk.bool_node(false);
if (cell->type == "$sub") {
if (cell->type == ID($sub)) {
for (auto &n : B)
n = mk.not_gate(n);
carry = mk.not_gate(carry);
}
vector<int> Y = mk.adder(A, B, carry);
mk.outport_vec(Y, "\\Y");
mk.outport_vec(Y, ID::Y);
goto optimize;
}
if (cell->type == "$alu")
if (cell->type == ID($alu))
{
int width = GetSize(cell->getPort("\\Y"));
vector<int> A = mk.inport_vec("\\A", width);
vector<int> B = mk.inport_vec("\\B", width);
int carry = mk.inport("\\CI");
int binv = mk.inport("\\BI");
int width = GetSize(cell->getPort(ID::Y));
vector<int> A = mk.inport_vec(ID::A, width);
vector<int> B = mk.inport_vec(ID::B, width);
int carry = mk.inport(ID(CI));
int binv = mk.inport(ID(BI));
for (auto &n : B)
n = mk.xor_gate(n, binv);
vector<int> X(width), CO(width);
vector<int> Y = mk.adder(A, B, carry, &X, &CO);
for (int i = 0; i < width; i++)
X[i] = mk.xor_gate(A[i], B[i]);
mk.outport_vec(Y, "\\Y");
mk.outport_vec(X, "\\X");
mk.outport_vec(CO, "\\CO");
mk.outport_vec(Y, ID::Y);
mk.outport_vec(X, ID(X));
mk.outport_vec(CO, ID(CO));
goto optimize;
}
if (cell->type.in("$eq", "$ne"))
if (cell->type.in(ID($eq), ID($ne)))
{
int width = max(GetSize(cell->getPort("\\A")), GetSize(cell->getPort("\\B")));
vector<int> A = mk.inport_vec("\\A", width);
vector<int> B = mk.inport_vec("\\B", width);
int width = max(GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::B)));
vector<int> A = mk.inport_vec(ID::A, width);
vector<int> B = mk.inport_vec(ID::B, width);
int Y = mk.bool_node(false);
for (int i = 0; i < width; i++)
Y = mk.or_gate(Y, mk.xor_gate(A[i], B[i]));
if (cell->type == "$eq")
if (cell->type == ID($eq))
Y = mk.not_gate(Y);
mk.outport_bool(Y, "\\Y");
mk.outport_bool(Y, ID::Y);
goto optimize;
}
if (cell->type == "$_AOI3_")
if (cell->type == ID($_AOI3_))
{
int A = mk.inport("\\A");
int B = mk.inport("\\B");
int C = mk.inport("\\C");
int A = mk.inport(ID::A);
int B = mk.inport(ID::B);
int C = mk.inport(ID(C));
int Y = mk.nor_gate(mk.and_gate(A, B), C);
mk.outport(Y, "\\Y");
mk.outport(Y, ID::Y);
goto optimize;
}
if (cell->type == "$_OAI3_")
if (cell->type == ID($_OAI3_))
{
int A = mk.inport("\\A");
int B = mk.inport("\\B");
int C = mk.inport("\\C");
int A = mk.inport(ID::A);
int B = mk.inport(ID::B);
int C = mk.inport(ID(C));
int Y = mk.nand_gate(mk.or_gate(A, B), C);
mk.outport(Y, "\\Y");
mk.outport(Y, ID::Y);
goto optimize;
}
if (cell->type == "$_AOI4_")
if (cell->type == ID($_AOI4_))
{
int A = mk.inport("\\A");
int B = mk.inport("\\B");
int C = mk.inport("\\C");
int D = mk.inport("\\D");
int A = mk.inport(ID::A);
int B = mk.inport(ID::B);
int C = mk.inport(ID(C));
int D = mk.inport(ID(D));
int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D));
mk.outport(Y, "\\Y");
mk.outport(Y, ID::Y);
goto optimize;
}
if (cell->type == "$_OAI4_")
if (cell->type == ID($_OAI4_))
{
int A = mk.inport("\\A");
int B = mk.inport("\\B");
int C = mk.inport("\\C");
int D = mk.inport("\\D");
int A = mk.inport(ID::A);
int B = mk.inport(ID::B);
int C = mk.inport(ID(C));
int D = mk.inport(ID(D));
int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D));
mk.outport(Y, "\\Y");
mk.outport(Y, ID::Y);
goto optimize;
}

View File

@ -24,9 +24,9 @@ PRIVATE_NAMESPACE_BEGIN
void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
IdString A = "\\A", Y = "\\Y";
IdString A = ID::A, Y = ID::Y;
bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
int a_width = GetSize(cell->getPort(A));
int y_width = GetSize(cell->getPort(Y));
@ -41,14 +41,14 @@ void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
IdString A = "\\A", B = "\\B", Y = "\\Y";
IdString A = ID::A, B = ID::B, Y = ID::Y;
bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
int a_width = GetSize(cell->getPort(A));
int b_width = GetSize(cell->getPort(B));
int y_width = GetSize(cell->getPort(Y));
if (cell->type == "$and" && !is_signed) {
if (cell->type == ID($and) && !is_signed) {
if (a_width > b_width)
a_width = b_width;
else
@ -71,9 +71,9 @@ void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
void arith_neg_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
IdString A = "\\A", Y = "\\Y";
IdString A = ID::A, Y = ID::Y;
bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
int a_width = GetSize(cell->getPort(A));
int y_width = GetSize(cell->getPort(Y));
@ -87,14 +87,14 @@ void arith_neg_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
void arith_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
IdString A = "\\A", B = "\\B", Y = "\\Y";
IdString A = ID::A, B = ID::B, Y = ID::Y;
bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
int a_width = GetSize(cell->getPort(A));
int b_width = GetSize(cell->getPort(B));
int y_width = GetSize(cell->getPort(Y));
if (!is_signed && cell->type != "$sub") {
if (!is_signed && cell->type != ID($sub)) {
int ab_width = std::max(a_width, b_width);
y_width = std::min(y_width, ab_width+1);
}
@ -114,7 +114,7 @@ void arith_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
void reduce_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
IdString A = "\\A", Y = "\\Y";
IdString A = ID::A, Y = ID::Y;
int a_width = GetSize(cell->getPort(A));
@ -124,7 +124,7 @@ void reduce_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
void compare_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
IdString A = "\\A", B = "\\B", Y = "\\Y";
IdString A = ID::A, B = ID::B, Y = ID::Y;
int a_width = GetSize(cell->getPort(A));
int b_width = GetSize(cell->getPort(B));
@ -138,7 +138,7 @@ void compare_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
void mux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
IdString A = "\\A", B = "\\B", S = "\\S", Y = "\\Y";
IdString A = ID::A, B = ID::B, S = ID(S), Y = ID::Y;
int a_width = GetSize(cell->getPort(A));
int b_width = GetSize(cell->getPort(B));
@ -160,43 +160,43 @@ PRIVATE_NAMESPACE_END
bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell)
{
if (cell->type.in("$not", "$pos")) {
if (cell->type.in(ID($not), ID($pos))) {
bitwise_unary_op(this, cell);
return true;
}
if (cell->type.in("$and", "$or", "$xor", "$xnor")) {
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor))) {
bitwise_binary_op(this, cell);
return true;
}
if (cell->type == "$neg") {
if (cell->type == ID($neg)) {
arith_neg_op(this, cell);
return true;
}
if (cell->type.in("$add", "$sub")) {
if (cell->type.in(ID($add), ID($sub))) {
arith_binary_op(this, cell);
return true;
}
if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", "$logic_not")) {
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($logic_not))) {
reduce_op(this, cell);
return true;
}
// FIXME:
// if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) {
// if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
// shift_op(this, cell);
// return true;
// }
if (cell->type.in("$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt")) {
if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt))) {
compare_op(this, cell);
return true;
}
if (cell->type.in("$mux", "$pmux")) {
if (cell->type.in(ID($mux), ID($pmux))) {
mux_op(this, cell);
return true;
}

View File

@ -84,46 +84,46 @@ struct CellTypes
{
setup_internals_eval();
IdString A = "\\A", B = "\\B", EN = "\\EN", Y = "\\Y";
IdString SRC = "\\SRC", DST = "\\DST", DAT = "\\DAT";
IdString EN_SRC = "\\EN_SRC", EN_DST = "\\EN_DST";
IdString A = ID::A, B = ID::B, EN = ID(EN), Y = ID::Y;
IdString SRC = ID(SRC), DST = ID(DST), DAT = ID(DAT);
IdString EN_SRC = ID(EN_SRC), EN_DST = ID(EN_DST);
setup_type("$tribuf", {A, EN}, {Y}, true);
setup_type(ID($tribuf), {A, EN}, {Y}, true);
setup_type("$assert", {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$assume", {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$live", {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$fair", {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$cover", {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$initstate", pool<RTLIL::IdString>(), {Y}, true);
setup_type("$anyconst", pool<RTLIL::IdString>(), {Y}, true);
setup_type("$anyseq", pool<RTLIL::IdString>(), {Y}, true);
setup_type("$allconst", pool<RTLIL::IdString>(), {Y}, true);
setup_type("$allseq", pool<RTLIL::IdString>(), {Y}, true);
setup_type("$equiv", {A, B}, {Y}, true);
setup_type("$specify2", {EN, SRC, DST}, pool<RTLIL::IdString>(), true);
setup_type("$specify3", {EN, SRC, DST, DAT}, pool<RTLIL::IdString>(), true);
setup_type("$specrule", {EN_SRC, EN_DST, SRC, DST}, pool<RTLIL::IdString>(), true);
setup_type(ID($assert), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type(ID($assume), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type(ID($live), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type(ID($fair), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type(ID($cover), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type(ID($initstate), pool<RTLIL::IdString>(), {Y}, true);
setup_type(ID($anyconst), pool<RTLIL::IdString>(), {Y}, true);
setup_type(ID($anyseq), pool<RTLIL::IdString>(), {Y}, true);
setup_type(ID($allconst), pool<RTLIL::IdString>(), {Y}, true);
setup_type(ID($allseq), pool<RTLIL::IdString>(), {Y}, true);
setup_type(ID($equiv), {A, B}, {Y}, true);
setup_type(ID($specify2), {EN, SRC, DST}, pool<RTLIL::IdString>(), true);
setup_type(ID($specify3), {EN, SRC, DST, DAT}, pool<RTLIL::IdString>(), true);
setup_type(ID($specrule), {EN_SRC, EN_DST, SRC, DST}, pool<RTLIL::IdString>(), true);
}
void setup_internals_eval()
{
std::vector<RTLIL::IdString> unary_ops = {
"$not", "$pos", "$neg",
"$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
"$logic_not", "$slice", "$lut", "$sop"
ID($not), ID($pos), ID($neg),
ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
ID($logic_not), ID($slice), ID($lut), ID($sop)
};
std::vector<RTLIL::IdString> binary_ops = {
"$and", "$or", "$xor", "$xnor",
"$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
"$add", "$sub", "$mul", "$div", "$mod", "$pow",
"$logic_and", "$logic_or", "$concat", "$macc"
ID($and), ID($or), ID($xor), ID($xnor),
ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow),
ID($logic_and), ID($logic_or), ID($concat), ID($macc)
};
IdString A = "\\A", B = "\\B", S = "\\S", Y = "\\Y";
IdString P = "\\P", G = "\\G", C = "\\C", X = "\\X";
IdString BI = "\\BI", CI = "\\CI", CO = "\\CO", EN = "\\EN";
IdString A = ID::A, B = ID::B, S = ID(S), Y = ID::Y;
IdString P = ID(P), G = ID(G), C = ID(C), X = ID(X);
IdString BI = ID(BI), CI = ID(CI), CO = ID(CO), EN = ID(EN);
for (auto type : unary_ops)
setup_type(type, {A}, {Y}, true);
@ -131,81 +131,91 @@ struct CellTypes
for (auto type : binary_ops)
setup_type(type, {A, B}, {Y}, true);
for (auto type : std::vector<RTLIL::IdString>({"$mux", "$pmux"}))
for (auto type : std::vector<RTLIL::IdString>({ID($mux), ID($pmux)}))
setup_type(type, {A, B, S}, {Y}, true);
setup_type("$lcu", {P, G, CI}, {CO}, true);
setup_type("$alu", {A, B, CI, BI}, {X, Y, CO}, true);
setup_type("$fa", {A, B, C}, {X, Y}, true);
setup_type(ID($lcu), {P, G, CI}, {CO}, true);
setup_type(ID($alu), {A, B, CI, BI}, {X, Y, CO}, true);
setup_type(ID($fa), {A, B, C}, {X, Y}, true);
}
void setup_internals_ff()
{
IdString SET = ID(SET), CLR = ID(CLR), CLK = ID(CLK), ARST = ID(ARST), EN = ID(EN);
IdString Q = ID(Q), D = ID(D);
setup_type(ID($sr), {SET, CLR}, {Q});
setup_type(ID($ff), {D}, {Q});
setup_type(ID($dff), {CLK, D}, {Q});
setup_type(ID($dffe), {CLK, EN, D}, {Q});
setup_type(ID($dffsr), {CLK, SET, CLR, D}, {Q});
setup_type(ID($adff), {CLK, ARST, D}, {Q});
setup_type(ID($dlatch), {EN, D}, {Q});
setup_type(ID($dlatchsr), {EN, SET, CLR, D}, {Q});
}
void setup_internals_mem()
{
IdString SET = "\\SET", CLR = "\\CLR", CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN";
IdString Q = "\\Q", D = "\\D", ADDR = "\\ADDR", DATA = "\\DATA", RD_EN = "\\RD_EN";
IdString RD_CLK = "\\RD_CLK", RD_ADDR = "\\RD_ADDR", WR_CLK = "\\WR_CLK", WR_EN = "\\WR_EN";
IdString WR_ADDR = "\\WR_ADDR", WR_DATA = "\\WR_DATA", RD_DATA = "\\RD_DATA";
IdString CTRL_IN = "\\CTRL_IN", CTRL_OUT = "\\CTRL_OUT";
setup_internals_ff();
setup_type("$sr", {SET, CLR}, {Q});
setup_type("$ff", {D}, {Q});
setup_type("$dff", {CLK, D}, {Q});
setup_type("$dffe", {CLK, EN, D}, {Q});
setup_type("$dffsr", {CLK, SET, CLR, D}, {Q});
setup_type("$adff", {CLK, ARST, D}, {Q});
setup_type("$dlatch", {EN, D}, {Q});
setup_type("$dlatchsr", {EN, SET, CLR, D}, {Q});
IdString CLK = ID(CLK), ARST = ID(ARST), EN = ID(EN);
IdString ADDR = ID(ADDR), DATA = ID(DATA), RD_EN = ID(RD_EN);
IdString RD_CLK = ID(RD_CLK), RD_ADDR = ID(RD_ADDR), WR_CLK = ID(WR_CLK), WR_EN = ID(WR_EN);
IdString WR_ADDR = ID(WR_ADDR), WR_DATA = ID(WR_DATA), RD_DATA = ID(RD_DATA);
IdString CTRL_IN = ID(CTRL_IN), CTRL_OUT = ID(CTRL_OUT);
setup_type("$memrd", {CLK, EN, ADDR}, {DATA});
setup_type("$memwr", {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>());
setup_type("$meminit", {ADDR, DATA}, pool<RTLIL::IdString>());
setup_type("$mem", {RD_CLK, RD_EN, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
setup_type(ID($memrd), {CLK, EN, ADDR}, {DATA});
setup_type(ID($memwr), {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>());
setup_type(ID($meminit), {ADDR, DATA}, pool<RTLIL::IdString>());
setup_type(ID($mem), {RD_CLK, RD_EN, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
setup_type("$fsm", {CLK, ARST, CTRL_IN}, {CTRL_OUT});
setup_type(ID($fsm), {CLK, ARST, CTRL_IN}, {CTRL_OUT});
}
void setup_stdcells()
{
setup_stdcells_eval();
IdString A = "\\A", E = "\\E", Y = "\\Y";
IdString A = ID::A, E = ID(E), Y = ID::Y;
setup_type("$_TBUF_", {A, E}, {Y}, true);
setup_type(ID($_TBUF_), {A, E}, {Y}, true);
}
void setup_stdcells_eval()
{
IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D";
IdString E = "\\E", F = "\\F", G = "\\G", H = "\\H";
IdString I = "\\I", J = "\\J", K = "\\K", L = "\\L";
IdString M = "\\M", N = "\\N", O = "\\O", P = "\\P";
IdString S = "\\S", T = "\\T", U = "\\U", V = "\\V";
IdString Y = "\\Y";
IdString A = ID::A, B = ID::B, C = ID(C), D = ID(D);
IdString E = ID(E), F = ID(F), G = ID(G), H = ID(H);
IdString I = ID(I), J = ID(J), K = ID(K), L = ID(L);
IdString M = ID(M), N = ID(N), O = ID(O), P = ID(P);
IdString S = ID(S), T = ID(T), U = ID(U), V = ID(V);
IdString Y = ID::Y;
setup_type("$_BUF_", {A}, {Y}, true);
setup_type("$_NOT_", {A}, {Y}, true);
setup_type("$_AND_", {A, B}, {Y}, true);
setup_type("$_NAND_", {A, B}, {Y}, true);
setup_type("$_OR_", {A, B}, {Y}, true);
setup_type("$_NOR_", {A, B}, {Y}, true);
setup_type("$_XOR_", {A, B}, {Y}, true);
setup_type("$_XNOR_", {A, B}, {Y}, true);
setup_type("$_ANDNOT_", {A, B}, {Y}, true);
setup_type("$_ORNOT_", {A, B}, {Y}, true);
setup_type("$_MUX_", {A, B, S}, {Y}, true);
setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true);
setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);
setup_type("$_AOI3_", {A, B, C}, {Y}, true);
setup_type("$_OAI3_", {A, B, C}, {Y}, true);
setup_type("$_AOI4_", {A, B, C, D}, {Y}, true);
setup_type("$_OAI4_", {A, B, C, D}, {Y}, true);
setup_type(ID($_BUF_), {A}, {Y}, true);
setup_type(ID($_NOT_), {A}, {Y}, true);
setup_type(ID($_AND_), {A, B}, {Y}, true);
setup_type(ID($_NAND_), {A, B}, {Y}, true);
setup_type(ID($_OR_), {A, B}, {Y}, true);
setup_type(ID($_NOR_), {A, B}, {Y}, true);
setup_type(ID($_XOR_), {A, B}, {Y}, true);
setup_type(ID($_XNOR_), {A, B}, {Y}, true);
setup_type(ID($_ANDNOT_), {A, B}, {Y}, true);
setup_type(ID($_ORNOT_), {A, B}, {Y}, true);
setup_type(ID($_MUX_), {A, B, S}, {Y}, true);
setup_type(ID($_NMUX_), {A, B, S}, {Y}, true);
setup_type(ID($_MUX4_), {A, B, C, D, S, T}, {Y}, true);
setup_type(ID($_MUX8_), {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
setup_type(ID($_MUX16_), {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);
setup_type(ID($_AOI3_), {A, B, C}, {Y}, true);
setup_type(ID($_OAI3_), {A, B, C}, {Y}, true);
setup_type(ID($_AOI4_), {A, B, C, D}, {Y}, true);
setup_type(ID($_OAI4_), {A, B, C, D}, {Y}, true);
}
void setup_stdcells_mem()
{
IdString S = "\\S", R = "\\R", C = "\\C";
IdString D = "\\D", Q = "\\Q", E = "\\E";
IdString S = ID(S), R = ID(R), C = ID(C);
IdString D = ID(D), Q = ID(Q), E = ID(E);
std::vector<char> list_np = {'N', 'P'}, list_01 = {'0', '1'};
@ -213,7 +223,7 @@ struct CellTypes
for (auto c2 : list_np)
setup_type(stringf("$_SR_%c%c_", c1, c2), {S, R}, {Q});
setup_type("$_FF_", {D}, {Q});
setup_type(ID($_FF_), {D}, {Q});
for (auto c1 : list_np)
setup_type(stringf("$_DFF_%c_", c1), {C, D}, {Q});
@ -272,20 +282,20 @@ struct CellTypes
static RTLIL::Const eval_not(RTLIL::Const v)
{
for (auto &bit : v.bits)
if (bit == RTLIL::S0) bit = RTLIL::S1;
else if (bit == RTLIL::S1) bit = RTLIL::S0;
if (bit == State::S0) bit = State::S1;
else if (bit == State::S1) bit = State::S0;
return v;
}
static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len, bool *errp = nullptr)
{
if (type == "$sshr" && !signed1)
type = "$shr";
if (type == "$sshl" && !signed1)
type = "$shl";
if (type == ID($sshr) && !signed1)
type = ID($shr);
if (type == ID($sshl) && !signed1)
type = ID($shl);
if (type != "$sshr" && type != "$sshl" && type != "$shr" && type != "$shl" && type != "$shift" && type != "$shiftx" &&
type != "$pos" && type != "$neg" && type != "$not") {
if (type != ID($sshr) && type != ID($sshl) && type != ID($shr) && type != ID($shl) && type != ID($shift) && type != ID($shiftx) &&
type != ID($pos) && type != ID($neg) && type != ID($not)) {
if (!signed1 || !signed2)
signed1 = false, signed2 = false;
}
@ -328,25 +338,25 @@ struct CellTypes
HANDLE_CELL_TYPE(neg)
#undef HANDLE_CELL_TYPE
if (type == "$_BUF_")
if (type == ID($_BUF_))
return arg1;
if (type == "$_NOT_")
if (type == ID($_NOT_))
return eval_not(arg1);
if (type == "$_AND_")
if (type == ID($_AND_))
return const_and(arg1, arg2, false, false, 1);
if (type == "$_NAND_")
if (type == ID($_NAND_))
return eval_not(const_and(arg1, arg2, false, false, 1));
if (type == "$_OR_")
if (type == ID($_OR_))
return const_or(arg1, arg2, false, false, 1);
if (type == "$_NOR_")
if (type == ID($_NOR_))
return eval_not(const_or(arg1, arg2, false, false, 1));
if (type == "$_XOR_")
if (type == ID($_XOR_))
return const_xor(arg1, arg2, false, false, 1);
if (type == "$_XNOR_")
if (type == ID($_XNOR_))
return const_xnor(arg1, arg2, false, false, 1);
if (type == "$_ANDNOT_")
if (type == ID($_ANDNOT_))
return const_and(arg1, eval_not(arg2), false, false, 1);
if (type == "$_ORNOT_")
if (type == ID($_ORNOT_))
return const_or(arg1, eval_not(arg2), false, false, 1);
if (errp != nullptr) {
@ -359,35 +369,35 @@ struct CellTypes
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr)
{
if (cell->type == "$slice") {
if (cell->type == ID($slice)) {
RTLIL::Const ret;
int width = cell->parameters.at("\\Y_WIDTH").as_int();
int offset = cell->parameters.at("\\OFFSET").as_int();
int width = cell->parameters.at(ID(Y_WIDTH)).as_int();
int offset = cell->parameters.at(ID(OFFSET)).as_int();
ret.bits.insert(ret.bits.end(), arg1.bits.begin()+offset, arg1.bits.begin()+offset+width);
return ret;
}
if (cell->type == "$concat") {
if (cell->type == ID($concat)) {
RTLIL::Const ret = arg1;
ret.bits.insert(ret.bits.end(), arg2.bits.begin(), arg2.bits.end());
return ret;
}
if (cell->type == "$lut")
if (cell->type == ID($lut))
{
int width = cell->parameters.at("\\WIDTH").as_int();
int width = cell->parameters.at(ID(WIDTH)).as_int();
std::vector<RTLIL::State> t = cell->parameters.at("\\LUT").bits;
std::vector<RTLIL::State> t = cell->parameters.at(ID(LUT)).bits;
while (GetSize(t) < (1 << width))
t.push_back(RTLIL::S0);
t.push_back(State::S0);
t.resize(1 << width);
for (int i = width-1; i >= 0; i--) {
RTLIL::State sel = arg1.bits.at(i);
std::vector<RTLIL::State> new_t;
if (sel == RTLIL::S0)
if (sel == State::S0)
new_t = std::vector<RTLIL::State>(t.begin(), t.begin() + GetSize(t)/2);
else if (sel == RTLIL::S1)
else if (sel == State::S1)
new_t = std::vector<RTLIL::State>(t.begin() + GetSize(t)/2, t.end());
else
for (int j = 0; j < GetSize(t)/2; j++)
@ -399,14 +409,14 @@ struct CellTypes
return t;
}
if (cell->type == "$sop")
if (cell->type == ID($sop))
{
int width = cell->parameters.at("\\WIDTH").as_int();
int depth = cell->parameters.at("\\DEPTH").as_int();
std::vector<RTLIL::State> t = cell->parameters.at("\\TABLE").bits;
int width = cell->parameters.at(ID(WIDTH)).as_int();
int depth = cell->parameters.at(ID(DEPTH)).as_int();
std::vector<RTLIL::State> t = cell->parameters.at(ID(TABLE)).bits;
while (GetSize(t) < width*depth*2)
t.push_back(RTLIL::S0);
t.push_back(State::S0);
RTLIL::State default_ret = State::S0;
@ -437,15 +447,15 @@ struct CellTypes
return default_ret;
}
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
bool signed_a = cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool();
bool signed_b = cell->parameters.count(ID(B_SIGNED)) > 0 && cell->parameters[ID(B_SIGNED)].as_bool();
int result_len = cell->parameters.count(ID(Y_WIDTH)) > 0 ? cell->parameters[ID(Y_WIDTH)].as_int() : -1;
return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len, errp);
}
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr)
{
if (cell->type.in("$mux", "$pmux", "$_MUX_")) {
if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
RTLIL::Const ret = arg1;
for (size_t i = 0; i < arg3.bits.size(); i++)
if (arg3.bits[i] == RTLIL::State::S1) {
@ -455,9 +465,9 @@ struct CellTypes
return ret;
}
if (cell->type == "$_AOI3_")
if (cell->type == ID($_AOI3_))
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
if (cell->type == "$_OAI3_")
if (cell->type == ID($_OAI3_))
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
log_assert(arg3.bits.size() == 0);
@ -466,9 +476,9 @@ struct CellTypes
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4, bool *errp = nullptr)
{
if (cell->type == "$_AOI4_")
if (cell->type == ID($_AOI4_))
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
if (cell->type == "$_OAI4_")
if (cell->type == ID($_OAI4_))
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_or(arg3, arg4, false, false, 1), false, false, 1));
log_assert(arg4.bits.size() == 0);

View File

@ -89,12 +89,12 @@ struct ConstEval
bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef)
{
if (cell->type == "$lcu")
if (cell->type == ID($lcu))
{
RTLIL::SigSpec sig_p = cell->getPort("\\P");
RTLIL::SigSpec sig_g = cell->getPort("\\G");
RTLIL::SigSpec sig_ci = cell->getPort("\\CI");
RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort("\\CO")));
RTLIL::SigSpec sig_p = cell->getPort(ID(P));
RTLIL::SigSpec sig_g = cell->getPort(ID(G));
RTLIL::SigSpec sig_ci = cell->getPort(ID(CI));
RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort(ID(CO))));
if (sig_co.is_fully_const())
return true;
@ -114,8 +114,8 @@ struct ConstEval
bool carry = sig_ci.as_bool();
for (int i = 0; i < GetSize(coval); i++) {
carry = (sig_g[i] == RTLIL::S1) || (sig_p[i] == RTLIL::S1 && carry);
coval.bits[i] = carry ? RTLIL::S1 : RTLIL::S0;
carry = (sig_g[i] == State::S1) || (sig_p[i] == RTLIL::S1 && carry);
coval.bits[i] = carry ? State::S1 : State::S0;
}
set(sig_co, coval);
@ -128,24 +128,24 @@ struct ConstEval
RTLIL::SigSpec sig_a, sig_b, sig_s, sig_y;
log_assert(cell->hasPort("\\Y"));
sig_y = values_map(assign_map(cell->getPort("\\Y")));
log_assert(cell->hasPort(ID::Y));
sig_y = values_map(assign_map(cell->getPort(ID::Y)));
if (sig_y.is_fully_const())
return true;
if (cell->hasPort("\\S")) {
sig_s = cell->getPort("\\S");
if (cell->hasPort(ID(S))) {
sig_s = cell->getPort(ID(S));
if (!eval(sig_s, undef, cell))
return false;
}
if (cell->hasPort("\\A"))
sig_a = cell->getPort("\\A");
if (cell->hasPort(ID::A))
sig_a = cell->getPort(ID::A);
if (cell->hasPort("\\B"))
sig_b = cell->getPort("\\B");
if (cell->hasPort(ID::B))
sig_b = cell->getPort(ID::B);
if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_")
if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_NMUX_)))
{
std::vector<RTLIL::SigSpec> y_candidates;
int count_maybe_set_s_bits = 0;
@ -175,7 +175,10 @@ struct ConstEval
for (auto &yc : y_candidates) {
if (!eval(yc, undef, cell))
return false;
y_values.push_back(yc.as_const());
if (cell->type == ID($_NMUX_))
y_values.push_back(RTLIL::const_not(yc.as_const(), Const(), false, false, GetSize(yc)));
else
y_values.push_back(yc.as_const());
}
if (y_values.size() > 1)
@ -195,10 +198,10 @@ struct ConstEval
else
set(sig_y, y_values.front());
}
else if (cell->type == "$fa")
else if (cell->type == ID($fa))
{
RTLIL::SigSpec sig_c = cell->getPort("\\C");
RTLIL::SigSpec sig_x = cell->getPort("\\X");
RTLIL::SigSpec sig_c = cell->getPort(ID(C));
RTLIL::SigSpec sig_x = cell->getPort(ID(X));
int width = GetSize(sig_c);
if (!eval(sig_a, undef, cell))
@ -224,13 +227,13 @@ struct ConstEval
set(sig_y, val_y);
set(sig_x, val_x);
}
else if (cell->type == "$alu")
else if (cell->type == ID($alu))
{
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
bool signed_a = cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool();
bool signed_b = cell->parameters.count(ID(B_SIGNED)) > 0 && cell->parameters[ID(B_SIGNED)].as_bool();
RTLIL::SigSpec sig_ci = cell->getPort("\\CI");
RTLIL::SigSpec sig_bi = cell->getPort("\\BI");
RTLIL::SigSpec sig_ci = cell->getPort(ID(CI));
RTLIL::SigSpec sig_bi = cell->getPort(ID(BI));
if (!eval(sig_a, undef, cell))
return false;
@ -244,15 +247,15 @@ struct ConstEval
if (!eval(sig_bi, undef, cell))
return false;
RTLIL::SigSpec sig_x = cell->getPort("\\X");
RTLIL::SigSpec sig_co = cell->getPort("\\CO");
RTLIL::SigSpec sig_x = cell->getPort(ID(X));
RTLIL::SigSpec sig_co = cell->getPort(ID(CO));
bool any_input_undef = !(sig_a.is_fully_def() && sig_b.is_fully_def() && sig_ci.is_fully_def() && sig_bi.is_fully_def());
sig_a.extend_u0(GetSize(sig_y), signed_a);
sig_b.extend_u0(GetSize(sig_y), signed_b);
bool carry = sig_ci[0] == RTLIL::S1;
bool b_inv = sig_bi[0] == RTLIL::S1;
bool carry = sig_ci[0] == State::S1;
bool b_inv = sig_bi[0] == State::S1;
for (int i = 0; i < GetSize(sig_y); i++)
{
@ -261,26 +264,26 @@ struct ConstEval
if (!x_inputs.is_fully_def()) {
set(sig_x[i], RTLIL::Sx);
} else {
bool bit_a = sig_a[i] == RTLIL::S1;
bool bit_b = (sig_b[i] == RTLIL::S1) != b_inv;
bool bit_a = sig_a[i] == State::S1;
bool bit_b = (sig_b[i] == State::S1) != b_inv;
bool bit_x = bit_a != bit_b;
set(sig_x[i], bit_x ? RTLIL::S1 : RTLIL::S0);
set(sig_x[i], bit_x ? State::S1 : State::S0);
}
if (any_input_undef) {
set(sig_y[i], RTLIL::Sx);
set(sig_co[i], RTLIL::Sx);
} else {
bool bit_a = sig_a[i] == RTLIL::S1;
bool bit_b = (sig_b[i] == RTLIL::S1) != b_inv;
bool bit_a = sig_a[i] == State::S1;
bool bit_b = (sig_b[i] == State::S1) != b_inv;
bool bit_y = (bit_a != bit_b) != carry;
carry = (bit_a && bit_b) || (bit_a && carry) || (bit_b && carry);
set(sig_y[i], bit_y ? RTLIL::S1 : RTLIL::S0);
set(sig_co[i], carry ? RTLIL::S1 : RTLIL::S0);
set(sig_y[i], bit_y ? State::S1 : State::S0);
set(sig_co[i], carry ? State::S1 : State::S0);
}
}
}
else if (cell->type == "$macc")
else if (cell->type == ID($macc))
{
Macc macc;
macc.from_cell(cell);
@ -295,21 +298,21 @@ struct ConstEval
return false;
}
RTLIL::Const result(0, GetSize(cell->getPort("\\Y")));
RTLIL::Const result(0, GetSize(cell->getPort(ID::Y)));
if (!macc.eval(result))
log_abort();
set(cell->getPort("\\Y"), result);
set(cell->getPort(ID::Y), result);
}
else
{
RTLIL::SigSpec sig_c, sig_d;
if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) {
if (cell->hasPort("\\C"))
sig_c = cell->getPort("\\C");
if (cell->hasPort("\\D"))
sig_d = cell->getPort("\\D");
if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_))) {
if (cell->hasPort(ID(C)))
sig_c = cell->getPort(ID(C));
if (cell->hasPort(ID(D)))
sig_d = cell->getPort(ID(D));
}
if (sig_a.size() > 0 && !eval(sig_a, undef, cell))

View File

@ -24,62 +24,92 @@
YOSYS_NAMESPACE_BEGIN
int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr);
inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const> &parameters = dict<RTLIL::IdString, RTLIL::Const>(),
RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr)
struct CellCosts
{
static dict<RTLIL::IdString, int> gate_cost = {
{ "$_BUF_", 1 },
{ "$_NOT_", 2 },
{ "$_AND_", 4 },
{ "$_NAND_", 4 },
{ "$_OR_", 4 },
{ "$_NOR_", 4 },
{ "$_ANDNOT_", 4 },
{ "$_ORNOT_", 4 },
{ "$_XOR_", 8 },
{ "$_XNOR_", 8 },
{ "$_AOI3_", 6 },
{ "$_OAI3_", 6 },
{ "$_AOI4_", 8 },
{ "$_OAI4_", 8 },
{ "$_MUX_", 4 }
};
if (gate_cost.count(type))
return gate_cost.at(type);
if (parameters.empty() && design && design->module(type))
{
RTLIL::Module *mod = design->module(type);
if (mod->attributes.count("\\cost"))
return mod->attributes.at("\\cost").as_int();
dict<RTLIL::IdString, int> local_mod_cost_cache;
if (mod_cost_cache == nullptr)
mod_cost_cache = &local_mod_cost_cache;
if (mod_cost_cache->count(mod->name))
return mod_cost_cache->at(mod->name);
int module_cost = 1;
for (auto c : mod->cells())
module_cost += get_cell_cost(c, mod_cost_cache);
(*mod_cost_cache)[mod->name] = module_cost;
return module_cost;
static const dict<RTLIL::IdString, int>& default_gate_cost() {
static const dict<RTLIL::IdString, int> db = {
{ ID($_BUF_), 1 },
{ ID($_NOT_), 2 },
{ ID($_AND_), 4 },
{ ID($_NAND_), 4 },
{ ID($_OR_), 4 },
{ ID($_NOR_), 4 },
{ ID($_ANDNOT_), 4 },
{ ID($_ORNOT_), 4 },
{ ID($_XOR_), 5 },
{ ID($_XNOR_), 5 },
{ ID($_AOI3_), 6 },
{ ID($_OAI3_), 6 },
{ ID($_AOI4_), 7 },
{ ID($_OAI4_), 7 },
{ ID($_MUX_), 4 },
{ ID($_NMUX_), 4 }
};
return db;
}
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters));
return 1;
}
static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
static const dict<RTLIL::IdString, int> db = {
{ ID($_BUF_), 1 },
{ ID($_NOT_), 2 },
{ ID($_AND_), 6 },
{ ID($_NAND_), 4 },
{ ID($_OR_), 6 },
{ ID($_NOR_), 4 },
{ ID($_ANDNOT_), 6 },
{ ID($_ORNOT_), 6 },
{ ID($_XOR_), 12 },
{ ID($_XNOR_), 12 },
{ ID($_AOI3_), 6 },
{ ID($_OAI3_), 6 },
{ ID($_AOI4_), 8 },
{ ID($_OAI4_), 8 },
{ ID($_MUX_), 12 },
{ ID($_NMUX_), 10 }
};
return db;
}
inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache)
{
return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache);
}
dict<RTLIL::IdString, int> mod_cost_cache;
const dict<RTLIL::IdString, int> *gate_cost = nullptr;
Design *design = nullptr;
int get(RTLIL::IdString type) const
{
if (gate_cost && gate_cost->count(type))
return gate_cost->at(type);
log_warning("Can't determine cost of %s cell.\n", log_id(type));
return 1;
}
int get(RTLIL::Cell *cell)
{
if (gate_cost && gate_cost->count(cell->type))
return gate_cost->at(cell->type);
if (design && design->module(cell->type) && cell->parameters.empty())
{
RTLIL::Module *mod = design->module(cell->type);
if (mod->attributes.count(ID(cost)))
return mod->attributes.at(ID(cost)).as_int();
if (mod_cost_cache.count(mod->name))
return mod_cost_cache.at(mod->name);
int module_cost = 1;
for (auto c : mod->cells())
module_cost += get(c);
mod_cost_cache[mod->name] = module_cost;
return module_cost;
}
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters));
return 1;
}
};
YOSYS_NAMESPACE_END

View File

@ -522,6 +522,12 @@ int main(int argc, char **argv)
if (!backend_command.empty())
run_backend(output_filename, backend_command);
yosys_design->check();
for (auto it : saved_designs)
it.second->check();
for (auto it : pushed_designs)
it->check();
if (!depsfile.empty())
{
FILE *f = fopen(depsfile.c_str(), "wt");

View File

@ -91,7 +91,7 @@ YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(prin
static inline bool ys_debug(int n = 0) { if (log_force_debug) return true; log_debug_suppressed += n; return false; }
# define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0)
#else
static inline bool ys_debug(int n = 0) { return false; }
static inline bool ys_debug(int = 0) { return false; }
# define log_debug(_fmt, ...) do { } while (0)
#endif

View File

@ -70,9 +70,9 @@ struct Macc
while (GetSize(port.in_b) > 1 && port.in_b[GetSize(port.in_b)-1] == port.in_b[GetSize(port.in_b)-2])
port.in_b.remove(GetSize(port.in_b)-1);
} else {
while (GetSize(port.in_a) > 1 && port.in_a[GetSize(port.in_a)-1] == RTLIL::S0)
while (GetSize(port.in_a) > 1 && port.in_a[GetSize(port.in_a)-1] == State::S0)
port.in_a.remove(GetSize(port.in_a)-1);
while (GetSize(port.in_b) > 1 && port.in_b[GetSize(port.in_b)-1] == RTLIL::S0)
while (GetSize(port.in_b) > 1 && port.in_b[GetSize(port.in_b)-1] == State::S0)
port.in_b.remove(GetSize(port.in_b)-1);
}
@ -80,9 +80,9 @@ struct Macc
}
for (auto &bit : bit_ports)
if (bit == RTLIL::S1)
if (bit == State::S1)
off = const_add(off, RTLIL::Const(1, width), false, false, width);
else if (bit != RTLIL::S0)
else if (bit != State::S0)
new_bit_ports.append(bit);
if (off.as_bool()) {
@ -99,24 +99,24 @@ struct Macc
void from_cell(RTLIL::Cell *cell)
{
RTLIL::SigSpec port_a = cell->getPort("\\A");
RTLIL::SigSpec port_a = cell->getPort(ID::A);
ports.clear();
bit_ports = cell->getPort("\\B");
bit_ports = cell->getPort(ID::B);
std::vector<RTLIL::State> config_bits = cell->getParam("\\CONFIG").bits;
std::vector<RTLIL::State> config_bits = cell->getParam(ID(CONFIG)).bits;
int config_cursor = 0;
#ifndef NDEBUG
int config_width = cell->getParam("\\CONFIG_WIDTH").as_int();
int config_width = cell->getParam(ID(CONFIG_WIDTH)).as_int();
log_assert(GetSize(config_bits) >= config_width);
#endif
int num_bits = 0;
if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 1;
if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 2;
if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 4;
if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 8;
if (config_bits[config_cursor++] == State::S1) num_bits |= 1;
if (config_bits[config_cursor++] == State::S1) num_bits |= 2;
if (config_bits[config_cursor++] == State::S1) num_bits |= 4;
if (config_bits[config_cursor++] == State::S1) num_bits |= 8;
int port_a_cursor = 0;
while (port_a_cursor < GetSize(port_a))
@ -124,12 +124,12 @@ struct Macc
log_assert(config_cursor + 2 + 2*num_bits <= config_width);
port_t this_port;
this_port.is_signed = config_bits[config_cursor++] == RTLIL::S1;
this_port.do_subtract = config_bits[config_cursor++] == RTLIL::S1;
this_port.is_signed = config_bits[config_cursor++] == State::S1;
this_port.do_subtract = config_bits[config_cursor++] == State::S1;
int size_a = 0;
for (int i = 0; i < num_bits; i++)
if (config_bits[config_cursor++] == RTLIL::S1)
if (config_bits[config_cursor++] == State::S1)
size_a |= 1 << i;
this_port.in_a = port_a.extract(port_a_cursor, size_a);
@ -137,7 +137,7 @@ struct Macc
int size_b = 0;
for (int i = 0; i < num_bits; i++)
if (config_bits[config_cursor++] == RTLIL::S1)
if (config_bits[config_cursor++] == State::S1)
size_b |= 1 << i;
this_port.in_b = port_a.extract(port_a_cursor, size_b);
@ -166,43 +166,43 @@ struct Macc
num_bits++, max_size /= 2;
log_assert(num_bits < 16);
config_bits.push_back(num_bits & 1 ? RTLIL::S1 : RTLIL::S0);
config_bits.push_back(num_bits & 2 ? RTLIL::S1 : RTLIL::S0);
config_bits.push_back(num_bits & 4 ? RTLIL::S1 : RTLIL::S0);
config_bits.push_back(num_bits & 8 ? RTLIL::S1 : RTLIL::S0);
config_bits.push_back(num_bits & 1 ? State::S1 : State::S0);
config_bits.push_back(num_bits & 2 ? State::S1 : State::S0);
config_bits.push_back(num_bits & 4 ? State::S1 : State::S0);
config_bits.push_back(num_bits & 8 ? State::S1 : State::S0);
for (auto &port : ports)
{
if (GetSize(port.in_a) == 0)
continue;
config_bits.push_back(port.is_signed ? RTLIL::S1 : RTLIL::S0);
config_bits.push_back(port.do_subtract ? RTLIL::S1 : RTLIL::S0);
config_bits.push_back(port.is_signed ? State::S1 : State::S0);
config_bits.push_back(port.do_subtract ? State::S1 : State::S0);
int size_a = GetSize(port.in_a);
for (int i = 0; i < num_bits; i++)
config_bits.push_back(size_a & (1 << i) ? RTLIL::S1 : RTLIL::S0);
config_bits.push_back(size_a & (1 << i) ? State::S1 : State::S0);
int size_b = GetSize(port.in_b);
for (int i = 0; i < num_bits; i++)
config_bits.push_back(size_b & (1 << i) ? RTLIL::S1 : RTLIL::S0);
config_bits.push_back(size_b & (1 << i) ? State::S1 : State::S0);
port_a.append(port.in_a);
port_a.append(port.in_b);
}
cell->setPort("\\A", port_a);
cell->setPort("\\B", bit_ports);
cell->setParam("\\CONFIG", config_bits);
cell->setParam("\\CONFIG_WIDTH", GetSize(config_bits));
cell->setParam("\\A_WIDTH", GetSize(port_a));
cell->setParam("\\B_WIDTH", GetSize(bit_ports));
cell->setPort(ID::A, port_a);
cell->setPort(ID::B, bit_ports);
cell->setParam(ID(CONFIG), config_bits);
cell->setParam(ID(CONFIG_WIDTH), GetSize(config_bits));
cell->setParam(ID(A_WIDTH), GetSize(port_a));
cell->setParam(ID(B_WIDTH), GetSize(bit_ports));
}
bool eval(RTLIL::Const &result) const
{
for (auto &bit : result.bits)
bit = RTLIL::S0;
bit = State::S0;
for (auto &port : ports)
{

View File

@ -25,6 +25,65 @@
#include <stdio.h>
#include <errno.h>
#ifdef YOSYS_ENABLE_ZLIB
#include <zlib.h>
PRIVATE_NAMESPACE_BEGIN
#define GZ_BUFFER_SIZE 8192
void decompress_gzip(const std::string &filename, std::stringstream &out)
{
char buffer[GZ_BUFFER_SIZE];
int bytes_read;
gzFile gzf = gzopen(filename.c_str(), "rb");
while(!gzeof(gzf)) {
bytes_read = gzread(gzf, reinterpret_cast<void *>(buffer), GZ_BUFFER_SIZE);
out.write(buffer, bytes_read);
}
gzclose(gzf);
}
/*
An output stream that uses a stringbuf to buffer data internally,
using zlib to write gzip-compressed data every time the stream is flushed.
*/
class gzip_ostream : public std::ostream {
public:
gzip_ostream()
{
rdbuf(&outbuf);
}
bool open(const std::string &filename)
{
return outbuf.open(filename);
}
private:
class gzip_streambuf : public std::stringbuf {
public:
gzip_streambuf() { };
bool open(const std::string &filename)
{
gzf = gzopen(filename.c_str(), "wb");
return gzf != nullptr;
}
virtual int sync() override
{
gzwrite(gzf, reinterpret_cast<const void *>(str().c_str()), unsigned(str().size()));
str("");
return 0;
}
~gzip_streambuf()
{
sync();
gzclose(gzf);
}
private:
gzFile gzf = nullptr;
} outbuf;
};
PRIVATE_NAMESPACE_END
#endif
YOSYS_NAMESPACE_BEGIN
#define MAX_REG_COUNT 1000
@ -141,7 +200,7 @@ void Pass::extra_args(std::vector<std::string> args, size_t argidx, RTLIL::Desig
{
std::string arg = args[argidx];
if (arg.substr(0, 1) == "-")
if (arg.compare(0, 1, "-") == 0)
cmd_error(args, argidx, "Unknown option or option in arguments.");
if (!select)
@ -236,8 +295,6 @@ void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
pass_register[args[0]]->post_execute(state);
while (design->selection_stack.size() > orig_sel_stack_pos)
design->selection_stack.pop_back();
design->check();
}
void Pass::call_on_selection(RTLIL::Design *design, const RTLIL::Selection &selection, std::string command)
@ -319,8 +376,10 @@ void ScriptPass::run(std::string command, std::string info)
log(" %s\n", command.c_str());
else
log(" %s %s\n", command.c_str(), info.c_str());
} else
} else {
Pass::call(active_design, command);
active_design->check();
}
}
void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to)
@ -390,7 +449,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
{
std::string arg = args[argidx];
if (arg.substr(0, 1) == "-")
if (arg.compare(0, 1, "-") == 0)
cmd_error(args, argidx, "Unknown option or option in arguments.");
if (f != NULL)
cmd_error(args, argidx, "Extra filename argument in direct file mode.");
@ -398,7 +457,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
filename = arg;
if (filename == "<<" && argidx+1 < args.size())
filename += args[++argidx];
if (filename.substr(0, 2) == "<<") {
if (filename.compare(0, 2, "<<") == 0) {
if (Frontend::current_script_file == NULL)
log_error("Unexpected here document '%s' outside of script!\n", filename.c_str());
if (filename.size() <= 2)
@ -416,7 +475,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
break;
}
size_t indent = buffer.find_first_not_of(" \t\r\n");
if (indent != std::string::npos && buffer.substr(indent, eot_marker.size()) == eot_marker)
if (indent != std::string::npos && buffer.compare(indent, eot_marker.size(), eot_marker) == 0)
break;
last_here_document += buffer;
}
@ -436,12 +495,34 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
delete ff;
else
f = ff;
if (f != NULL) {
// Check for gzip magic
unsigned char magic[3];
int n = readsome(*ff, reinterpret_cast<char*>(magic), 3);
if (n == 3 && magic[0] == 0x1f && magic[1] == 0x8b) {
#ifdef YOSYS_ENABLE_ZLIB
log("Found gzip magic in file `%s', decompressing using zlib.\n", filename.c_str());
if (magic[2] != 8)
log_cmd_error("gzip file `%s' uses unsupported compression type %02x\n",
filename.c_str(), unsigned(magic[2]));
delete ff;
std::stringstream *df = new std::stringstream();
decompress_gzip(filename, *df);
f = df;
#else
log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", filename.c_str());
#endif
} else {
ff->clear();
ff->seekg(0, std::ios::beg);
}
}
}
if (f == NULL)
log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
for (size_t i = argidx+1; i < args.size(); i++)
if (args[i].substr(0, 1) == "-")
if (args[i].compare(0, 1, "-") == 0)
cmd_error(args, i, "Found option, expected arguments.");
if (argidx+1 < args.size()) {
@ -492,8 +573,6 @@ void Frontend::frontend_call(RTLIL::Design *design, std::istream *f, std::string
args.push_back(filename);
frontend_register[args[0]]->execute(args, design);
}
design->check();
}
Backend::Backend(std::string name, std::string short_help) :
@ -533,7 +612,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
{
std::string arg = args[argidx];
if (arg.substr(0, 1) == "-" && arg != "-")
if (arg.compare(0, 1, "-") == 0 && arg != "-")
cmd_error(args, argidx, "Unknown option or option in arguments.");
if (f != NULL)
cmd_error(args, argidx, "Extra filename argument in direct file mode.");
@ -546,14 +625,28 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
filename = arg;
rewrite_filename(filename);
std::ofstream *ff = new std::ofstream;
ff->open(filename.c_str(), std::ofstream::trunc);
yosys_output_files.insert(filename);
if (ff->fail()) {
delete ff;
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".gz") == 0) {
#ifdef YOSYS_ENABLE_ZLIB
gzip_ostream *gf = new gzip_ostream;
if (!gf->open(filename)) {
delete gf;
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
}
yosys_output_files.insert(filename);
f = gf;
#else
log_cmd_error("Yosys is compiled without zlib support, unable to write gzip output.\n");
#endif
} else {
std::ofstream *ff = new std::ofstream;
ff->open(filename.c_str(), std::ofstream::trunc);
yosys_output_files.insert(filename);
if (ff->fail()) {
delete ff;
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
}
f = ff;
}
f = ff;
}
if (called_with_fp)
@ -603,8 +696,6 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f
while (design->selection_stack.size() > orig_sel_stack_pos)
design->selection_stack.pop_back();
design->check();
}
static struct CellHelpMessages {

File diff suppressed because it is too large Load Diff

View File

@ -78,6 +78,8 @@ namespace RTLIL
{
#undef YOSYS_XTRACE_GET_PUT
#undef YOSYS_SORT_ID_FREE_LIST
#undef YOSYS_USE_STICKY_IDS
#undef YOSYS_NO_IDS_REFCNT
// the global id string cache
@ -87,13 +89,17 @@ namespace RTLIL
~destruct_guard_t() { ok = false; }
} destruct_guard;
static std::vector<int> global_refcount_storage_;
static std::vector<char*> global_id_storage_;
static dict<char*, int, hash_cstr_ops> global_id_index_;
#ifndef YOSYS_NO_IDS_REFCNT
static std::vector<int> global_refcount_storage_;
static std::vector<int> global_free_idx_list_;
#endif
#ifdef YOSYS_USE_STICKY_IDS
static int last_created_idx_ptr_;
static int last_created_idx_[8];
#endif
static inline void xtrace_db_dump()
{
@ -110,12 +116,14 @@ namespace RTLIL
static inline void checkpoint()
{
#ifdef YOSYS_USE_STICKY_IDS
last_created_idx_ptr_ = 0;
for (int i = 0; i < 8; i++) {
if (last_created_idx_[i])
put_reference(last_created_idx_[i]);
last_created_idx_[i] = 0;
}
#endif
#ifdef YOSYS_SORT_ID_FREE_LIST
std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>());
#endif
@ -123,36 +131,47 @@ namespace RTLIL
static inline int get_reference(int idx)
{
global_refcount_storage_.at(idx)++;
#ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace) {
log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
}
if (idx) {
#ifndef YOSYS_NO_IDS_REFCNT
global_refcount_storage_[idx]++;
#endif
#ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace)
log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
#endif
}
return idx;
}
static inline int get_reference(const char *p)
static int get_reference(const char *p)
{
log_assert(destruct_guard.ok);
if (p[0]) {
log_assert(p[1] != 0);
log_assert(p[0] == '$' || p[0] == '\\');
}
if (!p[0])
return 0;
log_assert(p[0] == '$' || p[0] == '\\');
log_assert(p[1] != 0);
auto it = global_id_index_.find((char*)p);
if (it != global_id_index_.end()) {
#ifndef YOSYS_NO_IDS_REFCNT
global_refcount_storage_.at(it->second)++;
#endif
#ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace) {
if (yosys_xtrace)
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second));
}
#endif
return it->second;
}
#ifndef YOSYS_NO_IDS_REFCNT
if (global_free_idx_list_.empty()) {
if (global_id_storage_.empty()) {
global_refcount_storage_.push_back(0);
global_id_storage_.push_back((char*)"");
global_id_index_[global_id_storage_.back()] = 0;
}
log_assert(global_id_storage_.size() < 0x40000000);
global_free_idx_list_.push_back(global_id_storage_.size());
global_id_storage_.push_back(nullptr);
@ -164,13 +183,15 @@ namespace RTLIL
global_id_storage_.at(idx) = strdup(p);
global_id_index_[global_id_storage_.at(idx)] = idx;
global_refcount_storage_.at(idx)++;
// Avoid Create->Delete->Create pattern
if (last_created_idx_[last_created_idx_ptr_])
put_reference(last_created_idx_[last_created_idx_ptr_]);
last_created_idx_[last_created_idx_ptr_] = idx;
get_reference(last_created_idx_[last_created_idx_ptr_]);
last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7;
#else
if (global_id_storage_.empty()) {
global_id_storage_.push_back((char*)"");
global_id_index_[global_id_storage_.back()] = 0;
}
int idx = global_id_storage_.size();
global_id_storage_.push_back(strdup(p));
global_id_index_[global_id_storage_.back()] = idx;
#endif
if (yosys_xtrace) {
log("#X# New IdString '%s' with index %d.\n", p, idx);
@ -178,18 +199,28 @@ namespace RTLIL
}
#ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace) {
if (yosys_xtrace)
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
}
#endif
#ifdef YOSYS_USE_STICKY_IDS
// Avoid Create->Delete->Create pattern
if (last_created_idx_[last_created_idx_ptr_])
put_reference(last_created_idx_[last_created_idx_ptr_]);
last_created_idx_[last_created_idx_ptr_] = idx;
get_reference(last_created_idx_[last_created_idx_ptr_]);
last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7;
#endif
return idx;
}
#ifndef YOSYS_NO_IDS_REFCNT
static inline void put_reference(int idx)
{
// put_reference() may be called from destructors after the destructor of
// global_refcount_storage_ has been run. in this case we simply do nothing.
if (!destruct_guard.ok)
if (!destruct_guard.ok || !idx)
return;
#ifdef YOSYS_XTRACE_GET_PUT
@ -198,11 +229,13 @@ namespace RTLIL
}
#endif
log_assert(global_refcount_storage_.at(idx) > 0);
int &refcount = global_refcount_storage_[idx];
if (--global_refcount_storage_.at(idx) != 0)
if (--refcount > 0)
return;
log_assert(refcount == 0);
if (yosys_xtrace) {
log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx);
log_backtrace("-X- ", yosys_xtrace-1);
@ -213,46 +246,50 @@ namespace RTLIL
global_id_storage_.at(idx) = nullptr;
global_free_idx_list_.push_back(idx);
}
#else
static inline void put_reference(int) { }
#endif
// the actual IdString object is just is a single int
int index_;
IdString() : index_(get_reference("")) { }
IdString(const char *str) : index_(get_reference(str)) { }
IdString(const IdString &str) : index_(get_reference(str.index_)) { }
IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
~IdString() { put_reference(index_); }
inline IdString() : index_(0) { }
inline IdString(const char *str) : index_(get_reference(str)) { }
inline IdString(const IdString &str) : index_(get_reference(str.index_)) { }
inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
inline IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
inline ~IdString() { put_reference(index_); }
void operator=(const IdString &rhs) {
inline void operator=(const IdString &rhs) {
put_reference(index_);
index_ = get_reference(rhs.index_);
}
void operator=(const char *rhs) {
inline void operator=(const char *rhs) {
IdString id(rhs);
*this = id;
}
void operator=(const std::string &rhs) {
inline void operator=(const std::string &rhs) {
IdString id(rhs);
*this = id;
}
const char *c_str() const {
inline const char *c_str() const {
return global_id_storage_.at(index_);
}
std::string str() const {
inline std::string str() const {
return std::string(global_id_storage_.at(index_));
}
bool operator<(const IdString &rhs) const {
inline bool operator<(const IdString &rhs) const {
return index_ < rhs.index_;
}
bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
inline bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
inline bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
// The methods below are just convenience functions for better compatibility with std::string.
@ -276,20 +313,24 @@ namespace RTLIL
return std::string(c_str() + pos, len);
}
int compare(size_t pos, size_t len, const char* s) const {
return strncmp(c_str()+pos, s, len);
}
bool begins_with(const char* prefix) const {
size_t len = strlen(prefix);
if (size() < len) return false;
return substr(0, len) == prefix;
return compare(0, len, prefix) == 0;
}
bool ends_with(const char* suffix) const {
size_t len = strlen(suffix);
if (size() < len) return false;
return substr(size()-len) == suffix;
return compare(size()-len, len, suffix) == 0;
}
size_t size() const {
return str().size();
return strlen(c_str());
}
bool empty() const {
@ -328,6 +369,14 @@ namespace RTLIL
bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; }
};
namespace ID {
// defined in rtlil.cc, initialized in yosys.cc
extern IdString A, B, Y;
extern IdString keep;
extern IdString whitebox;
extern IdString blackbox;
};
static inline std::string escape_id(std::string str) {
if (str.size() > 0 && str[0] != '\\' && str[0] != '$')
return "\\" + str;
@ -420,8 +469,12 @@ namespace RTLIL
// It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
template<typename T>
struct ObjIterator
{
struct ObjIterator {
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = ptrdiff_t;
using pointer = T*;
using reference = T&;
typename dict<RTLIL::IdString, T>::iterator it;
dict<RTLIL::IdString, T> *list_p;
int *refcount_p;
@ -474,13 +527,25 @@ namespace RTLIL
return it != other.it;
}
inline void operator++() {
inline bool operator==(const RTLIL::ObjIterator<T> &other) const {
return !(*this != other);
}
inline ObjIterator<T>& operator++() {
log_assert(list_p != nullptr);
if (++it == list_p->end()) {
(*refcount_p)--;
list_p = nullptr;
refcount_p = nullptr;
}
return *this;
}
inline const ObjIterator<T> operator++(int) {
ObjIterator<T> result(*this);
++(*this);
return result;
}
};
@ -584,7 +649,7 @@ struct RTLIL::AttrObject
bool get_bool_attribute(RTLIL::IdString id) const;
bool get_blackbox_attribute(bool ignore_wb=false) const {
return get_bool_attribute("\\blackbox") || (!ignore_wb && get_bool_attribute("\\whitebox"));
return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox));
}
void set_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
@ -772,6 +837,7 @@ public:
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const;
RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
RTLIL::SigSpec extract(int offset, int length = 1) const;
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, width_ - offset); }
void append(const RTLIL::SigSpec &signal);
void append_bit(const RTLIL::SigBit &bit);
@ -818,6 +884,7 @@ public:
operator std::vector<RTLIL::SigChunk>() const { return chunks(); }
operator std::vector<RTLIL::SigBit>() const { return bits(); }
RTLIL::SigBit at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; }
unsigned int hash() const { if (!hash_) updhash(); return hash_; };
@ -1138,6 +1205,7 @@ public:
RTLIL::Cell* addAndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addOrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addMuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addNmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addOai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addAoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y, const std::string &src = "");
@ -1213,6 +1281,7 @@ public:
RTLIL::SigBit AndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = "");
RTLIL::SigBit OrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = "");
RTLIL::SigBit MuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = "");
RTLIL::SigBit NmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = "");
RTLIL::SigBit Aoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = "");
RTLIL::SigBit Oai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = "");
RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, const std::string &src = "");
@ -1315,8 +1384,8 @@ public:
void fixup_parameters(bool set_a_signed = false, bool set_b_signed = false);
bool has_keep_attr() const {
return get_bool_attribute("\\keep") || (module && module->design && module->design->module(type) &&
module->design->module(type)->get_bool_attribute("\\keep"));
return get_bool_attribute(ID::keep) || (module && module->design && module->design->module(type) &&
module->design->module(type)->get_bool_attribute(ID::keep));
}
template<typename T> void rewrite_sigspecs(T &functor);
@ -1384,7 +1453,7 @@ struct RTLIL::Process : public RTLIL::AttrObject
inline RTLIL::SigBit::SigBit() : wire(NULL), data(RTLIL::State::S0) { }
inline RTLIL::SigBit::SigBit(RTLIL::State bit) : wire(NULL), data(bit) { }
inline RTLIL::SigBit::SigBit(bool bit) : wire(NULL), data(bit ? RTLIL::S1 : RTLIL::S0) { }
inline RTLIL::SigBit::SigBit(bool bit) : wire(NULL), data(bit ? State::S1 : State::S0) { }
inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_assert(wire && wire->width == 1); }
inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire != nullptr); }
inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data[0]; }

File diff suppressed because it is too large Load Diff

View File

@ -510,10 +510,13 @@ void yosys_setup()
if(already_setup)
return;
already_setup = true;
// if there are already IdString objects then we have a global initialization order bug
IdString empty_id;
log_assert(empty_id.index_ == 0);
IdString::get_reference(empty_id.index_);
RTLIL::ID::A = "\\A";
RTLIL::ID::B = "\\B";
RTLIL::ID::Y = "\\Y";
RTLIL::ID::keep = "\\keep";
RTLIL::ID::whitebox = "\\whitebox";
RTLIL::ID::blackbox = "\\blackbox";
#ifdef WITH_PYTHON
PyImport_AppendInittab((char*)"libyosys", INIT_MODULE);
@ -575,9 +578,6 @@ void yosys_shutdown()
#ifdef WITH_PYTHON
Py_Finalize();
#endif
IdString empty_id;
IdString::put_reference(empty_id.index_);
}
RTLIL::IdString new_id(std::string file, int line, std::string func)
@ -647,12 +647,12 @@ std::vector<std::string> glob_filename(const std::string &filename_pattern)
void rewrite_filename(std::string &filename)
{
if (filename.substr(0, 1) == "\"" && filename.substr(GetSize(filename)-1) == "\"")
if (filename.compare(0, 1, "\"") == 0 && filename.compare(GetSize(filename)-1, std::string::npos, "\"") == 0)
filename = filename.substr(1, GetSize(filename)-2);
if (filename.substr(0, 2) == "+/")
if (filename.compare(0, 2, "+/") == 0)
filename = proc_share_dirname() + filename.substr(2);
#ifndef _WIN32
if (filename.substr(0, 2) == "~/")
if (filename.compare(0, 2, "~/") == 0)
filename = filename.replace(0, 1, getenv("HOME"));
#endif
}
@ -894,23 +894,26 @@ void run_frontend(std::string filename, std::string command, std::string *backen
design = yosys_design;
if (command == "auto") {
if (filename.size() > 2 && filename.substr(filename.size()-2) == ".v")
std::string filename_trim = filename;
if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".gz") == 0)
filename_trim.erase(filename_trim.size()-3);
if (filename_trim.size() > 2 && filename_trim.compare(filename_trim.size()-2, std::string::npos, ".v") == 0)
command = "verilog";
else if (filename.size() > 2 && filename.substr(filename.size()-3) == ".sv")
else if (filename_trim.size() > 2 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".sv") == 0)
command = "verilog -sv";
else if (filename.size() > 3 && filename.substr(filename.size()-4) == ".vhd")
else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".vhd") == 0)
command = "vhdl";
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".blif")
else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-5, std::string::npos, ".blif") == 0)
command = "blif";
else if (filename.size() > 5 && filename.substr(filename.size()-6) == ".eblif")
else if (filename_trim.size() > 5 && filename_trim.compare(filename_trim.size()-6, std::string::npos, ".eblif") == 0)
command = "blif";
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".json")
else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-5, std::string::npos, ".json") == 0)
command = "json";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".il") == 0)
command = "ilang";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".ys")
else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".ys") == 0)
command = "script";
else if (filename.size() > 3 && filename.substr(filename.size()-4) == ".tcl")
else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".tcl") == 0)
command = "tcl";
else if (filename == "-")
command = "script";
@ -961,14 +964,18 @@ void run_frontend(std::string filename, std::string command, std::string *backen
command += next_line;
}
handle_label(command, from_to_active, run_from, run_to);
if (from_to_active)
if (from_to_active) {
Pass::call(design, command);
design->check();
}
}
if (!command.empty()) {
handle_label(command, from_to_active, run_from, run_to);
if (from_to_active)
if (from_to_active) {
Pass::call(design, command);
design->check();
}
}
}
catch (...) {
@ -997,6 +1004,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen
Pass::call(design, vector<string>({command, filename}));
else
Frontend::frontend_call(design, NULL, filename, command);
design->check();
}
void run_frontend(std::string filename, std::string command, RTLIL::Design *design)
@ -1020,17 +1028,17 @@ void run_backend(std::string filename, std::string command, RTLIL::Design *desig
design = yosys_design;
if (command == "auto") {
if (filename.size() > 2 && filename.substr(filename.size()-2) == ".v")
if (filename.size() > 2 && filename.compare(filename.size()-2, std::string::npos, ".v") == 0)
command = "verilog";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
else if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0)
command = "ilang";
else if (filename.size() > 4 && filename.substr(filename.size()-4) == ".aig")
else if (filename.size() > 4 && filename.compare(filename.size()-4, std::string::npos, ".aig") == 0)
command = "aiger";
else if (filename.size() > 5 && filename.substr(filename.size()-5) == ".blif")
else if (filename.size() > 5 && filename.compare(filename.size()-5, std::string::npos, ".blif") == 0)
command = "blif";
else if (filename.size() > 5 && filename.substr(filename.size()-5) == ".edif")
else if (filename.size() > 5 && filename.compare(filename.size()-5, std::string::npos, ".edif") == 0)
command = "edif";
else if (filename.size() > 5 && filename.substr(filename.size()-5) == ".json")
else if (filename.size() > 5 && filename.compare(filename.size()-5, std::string::npos, ".json") == 0)
command = "json";
else if (filename == "-")
command = "ilang";
@ -1064,7 +1072,7 @@ static char *readline_cmd_generator(const char *text, int state)
}
for (; it != pass_register.end(); it++) {
if (it->first.substr(0, len) == text)
if (it->first.compare(0, len, text) == 0)
return strdup((it++)->first.c_str());
}
return NULL;
@ -1086,7 +1094,7 @@ static char *readline_obj_generator(const char *text, int state)
if (design->selected_active_module.empty())
{
for (auto &it : design->modules_)
if (RTLIL::unescape_id(it.first).substr(0, len) == text)
if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0)
obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
}
else
@ -1095,19 +1103,19 @@ static char *readline_obj_generator(const char *text, int state)
RTLIL::Module *module = design->modules_.at(design->selected_active_module);
for (auto &it : module->wires_)
if (RTLIL::unescape_id(it.first).substr(0, len) == text)
if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0)
obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
for (auto &it : module->memories)
if (RTLIL::unescape_id(it.first).substr(0, len) == text)
if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0)
obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
for (auto &it : module->cells_)
if (RTLIL::unescape_id(it.first).substr(0, len) == text)
if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0)
obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
for (auto &it : module->processes)
if (RTLIL::unescape_id(it.first).substr(0, len) == text)
if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0)
obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
}
@ -1180,6 +1188,7 @@ void shell(RTLIL::Design *design)
design->selection_stack.pop_back();
log_reset_stack();
}
design->check();
}
if (command == NULL)
printf("exit\n");

View File

@ -52,6 +52,7 @@
#include <stdexcept>
#include <memory>
#include <cmath>
#include <cstddef>
#include <sstream>
#include <fstream>
@ -87,6 +88,10 @@ extern int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName);
extern void Tcl_Finalize(void);
extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr);
extern const char *Tcl_GetStringResult(Tcl_Interp *interp);
extern Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length);
extern Tcl_Obj *Tcl_NewIntObj(int intValue);
extern Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[]);
extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags);
# endif
#endif
@ -300,8 +305,17 @@ RTLIL::IdString new_id(std::string file, int line, std::string func);
#define NEW_ID \
YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__)
#define ID(_str) \
([]() { static YOSYS_NAMESPACE_PREFIX RTLIL::IdString _id(_str); return _id; })()
// Create a statically allocated IdString object, using for example ID(A) or ID($add).
//
// Recipe for Converting old code that is using conversion of strings like "\\A" and
// "$add" for creating IdStrings: Run below SED command on the .cc file and then use for
// example "meld foo.cc foo.cc.orig" to manually compile errors, if necessary.
//
// sed -i.orig -r 's/"\\\\([a-zA-Z0-9_]+)"/ID(\1)/g; s/"(\$[a-zA-Z0-9_]+)"/ID(\1)/g;' <filename>
//
#define ID(_id) ([]() { const char *p = "\\" #_id, *q = p[1] == '$' ? p+1 : p; \
static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id(q); return id; })()
namespace ID = RTLIL::ID;
RTLIL::Design *yosys_get_design();
std::string proc_self_dirname();

View File

@ -494,6 +494,6 @@ Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLA
\end{fixme}
\begin{fixme}
Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells.
Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, {\tt \$\_OAI4\_}, and {\tt \$\_NMUX\_} cells.
\end{fixme}

View File

@ -61,6 +61,7 @@ SOFTWARE. */
#include <windows.h>
#include <tchar.h>
#include <fcntl.h>
#include <unistd.h>
int child_pid=0;
@ -338,7 +339,7 @@ int run(int argc, char **argv, int is_gui) {
if (is_gui) {
/* Use exec, we don't need to wait for the GUI to finish */
execv(ptr, (const char * const *)(newargs));
execv(ptr, (char * const *)(newargs));
return fail("Could not exec %s", ptr); /* shouldn't get here! */
}

View File

@ -121,7 +121,7 @@ struct CoverPass : public Pass {
}
break;
}
while (argidx < args.size() && args[argidx].substr(0, 1) != "-")
while (argidx < args.size() && args[argidx].compare(0, 1, "-") != 0)
patterns.push_back(args[argidx++]);
extra_args(args, argidx, design);

View File

@ -107,7 +107,7 @@ struct DeletePass : public Pass {
for (auto &it : module->cells_) {
if (design->selected(module, it.second))
delete_cells.insert(it.second);
if ((it.second->type == "$memrd" || it.second->type == "$memwr") &&
if (it.second->type.in("$memrd", "$memwr") &&
delete_mems.count(it.second->parameters.at("\\MEMID").decode_string()) != 0)
delete_cells.insert(it.second);
}

View File

@ -34,7 +34,7 @@ static bool match_ids(RTLIL::IdString id, std::string pattern)
{
if (id == pattern)
return true;
if (id.size() > 0 && id[0] == '\\' && id.substr(1) == pattern)
if (id.size() > 0 && id[0] == '\\' && id.compare(1, std::string::npos, pattern.c_str()) == 0)
return true;
if (patmatch(pattern.c_str(), id.c_str()))
return true;
@ -124,11 +124,11 @@ static bool match_attr(const dict<RTLIL::IdString, RTLIL::Const> &attributes, st
size_t pos = match_expr.find_first_of("<!=>");
if (pos != std::string::npos) {
if (match_expr.substr(pos, 2) == "!=")
if (match_expr.compare(pos, 2, "!=") == 0)
return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), '!');
if (match_expr.substr(pos, 2) == "<=")
if (match_expr.compare(pos, 2, "<=") == 0)
return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), '[');
if (match_expr.substr(pos, 2) == ">=")
if (match_expr.compare(pos, 2, ">=") == 0)
return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), ']');
return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+1), match_expr[pos]);
}
@ -711,32 +711,32 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
log_cmd_error("Must have at least one element on the stack for operator %%a.\n");
select_op_alias(design, work_stack[work_stack.size()-1]);
} else
if (arg == "%x" || (arg.size() > 2 && arg.substr(0, 2) == "%x" && (arg[2] == ':' || arg[2] == '*' || arg[2] == '.' || ('0' <= arg[2] && arg[2] <= '9')))) {
if (arg == "%x" || (arg.size() > 2 && arg.compare(0, 2, "%x") == 0 && (arg[2] == ':' || arg[2] == '*' || arg[2] == '.' || ('0' <= arg[2] && arg[2] <= '9')))) {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%x.\n");
select_op_expand(design, arg, 'x', false);
} else
if (arg == "%ci" || (arg.size() > 3 && arg.substr(0, 3) == "%ci" && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
if (arg == "%ci" || (arg.size() > 3 && arg.compare(0, 3, "%ci") == 0 && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%ci.\n");
select_op_expand(design, arg, 'i', false);
} else
if (arg == "%co" || (arg.size() > 3 && arg.substr(0, 3) == "%co" && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
if (arg == "%co" || (arg.size() > 3 && arg.compare(0, 3, "%co") == 0 && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%co.\n");
select_op_expand(design, arg, 'o', false);
} else
if (arg == "%xe" || (arg.size() > 3 && arg.substr(0, 3) == "%xe" && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
if (arg == "%xe" || (arg.size() > 3 && arg.compare(0, 3, "%xe") == 0 && (arg[3] == ':' || arg[3] == '*' || arg[3] == '.' || ('0' <= arg[3] && arg[3] <= '9')))) {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%xe.\n");
select_op_expand(design, arg, 'x', true);
} else
if (arg == "%cie" || (arg.size() > 4 && arg.substr(0, 4) == "%cie" && (arg[4] == ':' || arg[4] == '*' || arg[4] == '.' || ('0' <= arg[4] && arg[4] <= '9')))) {
if (arg == "%cie" || (arg.size() > 4 && arg.compare(0, 4, "%cie") == 0 && (arg[4] == ':' || arg[4] == '*' || arg[4] == '.' || ('0' <= arg[4] && arg[4] <= '9')))) {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%cie.\n");
select_op_expand(design, arg, 'i', true);
} else
if (arg == "%coe" || (arg.size() > 4 && arg.substr(0, 4) == "%coe" && (arg[4] == ':' || arg[4] == '*' || arg[4] == '.' || ('0' <= arg[4] && arg[4] <= '9')))) {
if (arg == "%coe" || (arg.size() > 4 && arg.compare(0, 4, "%coe") == 0 && (arg[4] == ':' || arg[4] == '*' || arg[4] == '.' || ('0' <= arg[4] && arg[4] <= '9')))) {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on the stack for operator %%coe.\n");
select_op_expand(design, arg, 'o', true);
@ -766,7 +766,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
} else {
size_t pos = arg.find('/');
if (pos == std::string::npos) {
if (arg.find(':') == std::string::npos || arg.substr(0, 1) == "A")
if (arg.find(':') == std::string::npos || arg.compare(0, 1, "A") == 0)
arg_mod = arg;
else
arg_mod = "*", arg_memb = arg;
@ -787,7 +787,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
sel.full_selection = false;
for (auto &mod_it : design->modules_)
{
if (arg_mod.substr(0, 2) == "A:") {
if (arg_mod.compare(0, 2, "A:") == 0) {
if (!match_attr(mod_it.second->attributes, arg_mod.substr(2)))
continue;
} else
@ -800,27 +800,27 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
}
RTLIL::Module *mod = mod_it.second;
if (arg_memb.substr(0, 2) == "w:") {
if (arg_memb.compare(0, 2, "w:") == 0) {
for (auto &it : mod->wires_)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "i:") {
if (arg_memb.compare(0, 2, "i:") == 0) {
for (auto &it : mod->wires_)
if (it.second->port_input && match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "o:") {
if (arg_memb.compare(0, 2, "o:") == 0) {
for (auto &it : mod->wires_)
if (it.second->port_output && match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "x:") {
if (arg_memb.compare(0, 2, "x:") == 0) {
for (auto &it : mod->wires_)
if ((it.second->port_input || it.second->port_output) && match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "s:") {
if (arg_memb.compare(0, 2, "s:") == 0) {
size_t delim = arg_memb.substr(2).find(':');
if (delim == std::string::npos) {
int width = atoi(arg_memb.substr(2).c_str());
@ -837,27 +837,27 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
sel.selected_members[mod->name].insert(it.first);
}
} else
if (arg_memb.substr(0, 2) == "m:") {
if (arg_memb.compare(0, 2, "m:") == 0) {
for (auto &it : mod->memories)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "c:") {
if (arg_memb.compare(0, 2, "c:") ==0) {
for (auto &it : mod->cells_)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "t:") {
if (arg_memb.compare(0, 2, "t:") == 0) {
for (auto &it : mod->cells_)
if (match_ids(it.second->type, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "p:") {
if (arg_memb.compare(0, 2, "p:") == 0) {
for (auto &it : mod->processes)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "a:") {
if (arg_memb.compare(0, 2, "a:") == 0) {
for (auto &it : mod->wires_)
if (match_attr(it.second->attributes, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
@ -871,12 +871,12 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
if (match_attr(it.second->attributes, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "r:") {
if (arg_memb.compare(0, 2, "r:") == 0) {
for (auto &it : mod->cells_)
if (match_attr(it.second->parameters, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else {
if (arg_memb.substr(0, 2) == "n:")
if (arg_memb.compare(0, 2, "n:") == 0)
arg_memb = arg_memb.substr(2);
for (auto &it : mod->wires_)
if (match_ids(it.first, arg_memb))
@ -927,7 +927,7 @@ void handle_extra_select_args(Pass *pass, vector<string> args, size_t argidx, si
{
work_stack.clear();
for (; argidx < args_size; argidx++) {
if (args[argidx].substr(0, 1) == "-") {
if (args[argidx].compare(0, 1, "-") == 0) {
if (pass != NULL)
pass->cmd_error(args, argidx, "Unexpected option in selection arguments.");
else

View File

@ -34,7 +34,7 @@ struct setunset_t
setunset_t(std::string set_name, std::string set_value) : name(RTLIL::escape_id(set_name)), value(), unset(false)
{
if (set_value.substr(0, 1) == "\"" && set_value.substr(GetSize(set_value)-1) == "\"") {
if (set_value.compare(0, 1, "\"") == 0 && set_value.compare(GetSize(set_value)-1, std::string::npos, "\"") == 0) {
value = RTLIL::Const(set_value.substr(1, GetSize(set_value)-2));
} else {
RTLIL::SigSpec sig_value;

View File

@ -527,11 +527,11 @@ struct ShowWorker
{
currentColor = xorshift32(currentColor);
if (wires_on_demand.count(it.first) > 0) {
if (it.second.in.size() == 1 && it.second.out.size() > 1 && it.second.in.begin()->substr(0, 1) == "p")
if (it.second.in.size() == 1 && it.second.out.size() > 1 && it.second.in.begin()->compare(0, 1, "p") == 0)
it.second.out.erase(*it.second.in.begin());
if (it.second.in.size() == 1 && it.second.out.size() == 1) {
std::string from = *it.second.in.begin(), to = *it.second.out.begin();
if (from != to || from.substr(0, 1) != "p")
if (from != to || from.compare(0, 1, "p") != 0)
fprintf(f, "%s:e -> %s:w [%s, %s];\n", from.c_str(), to.c_str(), nextColor(it.second.color).c_str(), widthLabel(it.second.bits).c_str());
continue;
}
@ -808,7 +808,7 @@ struct ShowPass : public Pass {
if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design;
Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "ilang" : "verilog"));
libs.push_back(lib);
}

View File

@ -17,11 +17,10 @@
*
*/
#include "kernel/register.h"
#include "kernel/yosys.h"
#include "kernel/celltypes.h"
#include "passes/techmap/libparse.h"
#include "kernel/log.h"
#include "kernel/cost.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@ -223,6 +222,28 @@ struct statdata_t
log("\n");
log(" Estimated number of LCs: %10d\n", lc_cnt);
}
if (tech == "cmos")
{
int tran_cnt = 0;
bool tran_cnt_exact = true;
auto &gate_costs = CellCosts::cmos_gate_cost();
for (auto it : num_cells_by_type) {
auto ctype = it.first;
auto cnum = it.second;
if (gate_costs.count(ctype))
tran_cnt += cnum * gate_costs.at(ctype);
else if (ctype.in("$_DFF_P_", "$_DFF_N_"))
tran_cnt += cnum * 16;
else
tran_cnt_exact = false;
}
log("\n");
log(" Estimated number of transistors: %10d%s\n", tran_cnt, tran_cnt_exact ? "" : "+");
}
}
};
@ -286,7 +307,7 @@ struct StatPass : public Pass {
log("\n");
log(" -tech <technology>\n");
log(" print area estemate for the specified technology. Currently supported\n");
log(" values for <technology>: xilinx\n");
log(" values for <technology>: xilinx, cmos\n");
log("\n");
log(" -width\n");
log(" annotate internal cell types with their word width.\n");
@ -330,7 +351,7 @@ struct StatPass : public Pass {
}
extra_args(args, argidx, design);
if (techname != "" && techname != "xilinx")
if (techname != "" && techname != "xilinx" && techname != "cmos")
log_cmd_error("Unsupported technology: '%s'\n", techname.c_str());
for (auto mod : design->selected_modules())

View File

@ -97,7 +97,7 @@ struct EquivOptPass:public ScriptPass
for (; argidx < args.size(); argidx++) {
if (command.empty()) {
if (args[argidx].substr(0, 1) == "-")
if (args[argidx].compare(0, 1, "-") == 0)
cmd_error(args, argidx, "Unknown option.");
} else {
command += " ";

View File

@ -215,9 +215,9 @@ struct EquivStructWorker
if (c != nullptr) {
string n = cell_name.str();
cells_type = c->type;
if (GetSize(n) > 5 && n.substr(GetSize(n)-5) == "_gold")
if (GetSize(n) > 5 && n.compare(GetSize(n)-5, std::string::npos, "_gold") == 0)
gold_cells.push_back(c);
else if (GetSize(n) > 5 && n.substr(GetSize(n)-5) == "_gate")
else if (GetSize(n) > 5 && n.compare(GetSize(n)-5, std::string::npos, "_gate") == 0)
gate_cells.push_back(c);
else
other_cells.push_back(c);

View File

@ -50,7 +50,7 @@ struct FsmExpand
if (full_mode || cell->type == "$_MUX_")
return true;
if (cell->type == "$mux" || cell->type == "$pmux")
if (cell->type.in("$mux", "$pmux"))
if (cell->getPort("\\A").size() < 2)
return true;

View File

@ -168,7 +168,7 @@ undef_bit_in_next_state:
ctrl_in_bit_indices[ctrl_in[i]] = i;
for (auto &it : ctrl_in_bit_indices)
if (tr.ctrl_in.bits.at(it.second) == RTLIL::S1 && exclusive_ctrls.count(it.first) != 0)
if (tr.ctrl_in.bits.at(it.second) == State::S1 && exclusive_ctrls.count(it.first) != 0)
for (auto &dc_bit : exclusive_ctrls.at(it.first))
if (ctrl_in_bit_indices.count(dc_bit))
tr.ctrl_in.bits.at(ctrl_in_bit_indices.at(dc_bit)) = RTLIL::State::Sa;
@ -216,13 +216,13 @@ undef_bit_in_next_state:
ce.push();
dont_care.append(undef);
ce.set(undef, constval.as_const());
if (exclusive_ctrls.count(undef) && constval == RTLIL::S1)
if (exclusive_ctrls.count(undef) && constval == State::S1)
for (auto &bit : exclusive_ctrls.at(undef)) {
RTLIL::SigSpec bitval = bit;
if (ce.eval(bitval) && bitval != RTLIL::S0)
if (ce.eval(bitval) && bitval != State::S0)
goto found_contradiction_1;
else
ce.set(bit, RTLIL::S0);
ce.set(bit, State::S0);
}
find_transitions(ce, ce_nostop, fsm_data, states, state_in, ctrl_in, ctrl_out, dff_in, dont_care);
found_contradiction_1:
@ -231,21 +231,21 @@ undef_bit_in_next_state:
else
{
ce.push(), ce_nostop.push();
ce.set(undef, RTLIL::S0);
ce_nostop.set(undef, RTLIL::S0);
ce.set(undef, State::S0);
ce_nostop.set(undef, State::S0);
find_transitions(ce, ce_nostop, fsm_data, states, state_in, ctrl_in, ctrl_out, dff_in, dont_care);
ce.pop(), ce_nostop.pop();
ce.push(), ce_nostop.push();
ce.set(undef, RTLIL::S1);
ce_nostop.set(undef, RTLIL::S1);
ce.set(undef, State::S1);
ce_nostop.set(undef, State::S1);
if (exclusive_ctrls.count(undef))
for (auto &bit : exclusive_ctrls.at(undef)) {
RTLIL::SigSpec bitval = bit;
if ((ce.eval(bitval) || ce_nostop.eval(bitval)) && bitval != RTLIL::S0)
if ((ce.eval(bitval) || ce_nostop.eval(bitval)) && bitval != State::S0)
goto found_contradiction_2;
else
ce.set(bit, RTLIL::S0), ce_nostop.set(bit, RTLIL::S0);
ce.set(bit, State::S0), ce_nostop.set(bit, RTLIL::S0);
}
find_transitions(ce, ce_nostop, fsm_data, states, state_in, ctrl_in, ctrl_out, dff_in, dont_care);
found_contradiction_2:
@ -263,8 +263,8 @@ static void extract_fsm(RTLIL::Wire *wire)
RTLIL::SigSpec dff_in(RTLIL::State::Sm, wire->width);
RTLIL::Const reset_state(RTLIL::State::Sx, wire->width);
RTLIL::SigSpec clk = RTLIL::S0;
RTLIL::SigSpec arst = RTLIL::S0;
RTLIL::SigSpec clk = State::S0;
RTLIL::SigSpec arst = State::S0;
bool clk_polarity = true;
bool arst_polarity = true;
@ -371,8 +371,8 @@ static void extract_fsm(RTLIL::Wire *wire)
RTLIL::Cell *fsm_cell = module->addCell(stringf("$fsm$%s$%d", wire->name.c_str(), autoidx++), "$fsm");
fsm_cell->setPort("\\CLK", clk);
fsm_cell->setPort("\\ARST", arst);
fsm_cell->parameters["\\CLK_POLARITY"] = clk_polarity ? RTLIL::S1 : RTLIL::S0;
fsm_cell->parameters["\\ARST_POLARITY"] = arst_polarity ? RTLIL::S1 : RTLIL::S0;
fsm_cell->parameters["\\CLK_POLARITY"] = clk_polarity ? State::S1 : State::S0;
fsm_cell->parameters["\\ARST_POLARITY"] = arst_polarity ? State::S1 : State::S0;
fsm_cell->setPort("\\CTRL_IN", ctrl_in);
fsm_cell->setPort("\\CTRL_OUT", ctrl_out);
fsm_cell->parameters["\\NAME"] = RTLIL::Const(wire->name.str());

View File

@ -133,7 +133,7 @@ static void implement_pattern_cache(RTLIL::Module *module, std::map<RTLIL::Const
cases_vector.append(and_sig);
break;
case 0:
cases_vector.append(RTLIL::SigSpec(1, 1));
cases_vector.append(State::S1);
break;
default:
log_abort();
@ -150,7 +150,7 @@ static void implement_pattern_cache(RTLIL::Module *module, std::map<RTLIL::Const
} else if (cases_vector.size() == 1) {
module->connect(RTLIL::SigSig(output, cases_vector));
} else {
module->connect(RTLIL::SigSig(output, RTLIL::SigSpec(0, 1)));
module->connect(RTLIL::SigSig(output, State::S0));
}
}

View File

@ -48,7 +48,7 @@ void generate(RTLIL::Design *design, const std::vector<std::string> &celltypes,
RTLIL::Cell *cell = i2.second;
if (design->has(cell->type))
continue;
if (cell->type.substr(0, 1) == "$" && cell->type.substr(0, 3) != "$__")
if (cell->type.begins_with("$__"))
continue;
for (auto &pattern : celltypes)
if (patmatch(pattern.c_str(), RTLIL::unescape_id(cell->type).c_str()))
@ -143,7 +143,7 @@ void generate(RTLIL::Design *design, const std::vector<std::string> &celltypes,
// Return the "basic" type for an array item.
std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) {
std::string basicType = celltype;
if (celltype.substr(0, 7) == "$array:") {
if (celltype.compare(0, strlen("$array:"), "$array:") == 0) {
int pos_idx = celltype.find_first_of(':');
int pos_num = celltype.find_first_of(':', pos_idx + 1);
int pos_type = celltype.find_first_of(':', pos_num + 1);
@ -194,16 +194,16 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
std::vector<RTLIL::IdString> connections_to_add_name;
std::vector<RTLIL::SigSpec> connections_to_add_signal;
if (cell->type.substr(0, 7) == "$array:") {
if (cell->type.begins_with("$array:")) {
int pos[3];
basic_cell_type(cell->type.str(), pos);
int pos_idx = pos[0];
int pos_num = pos[1];
int pos_type = pos[2];
int idx = atoi(cell->type.str().substr(pos_idx + 1, pos_num).c_str());
int num = atoi(cell->type.str().substr(pos_num + 1, pos_type).c_str());
int idx = atoi(cell->type.substr(pos_idx + 1, pos_num).c_str());
int num = atoi(cell->type.substr(pos_num + 1, pos_type).c_str());
array_cells[cell] = std::pair<int, int>(idx, num);
cell->type = cell->type.str().substr(pos_type + 1);
cell->type = cell->type.substr(pos_type + 1);
}
dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule;
dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_submodule;
@ -422,7 +422,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
for (auto &conn : cell->connections_) {
int conn_size = conn.second.size();
RTLIL::IdString portname = conn.first;
if (portname.substr(0, 1) == "$") {
if (portname.begins_with("$")) {
int port_id = atoi(portname.substr(1).c_str());
for (auto &wire_it : mod->wires_)
if (wire_it.second->port_id == port_id) {
@ -457,9 +457,8 @@ void hierarchy_worker(RTLIL::Design *design, std::set<RTLIL::Module*, IdString::
for (auto cell : mod->cells()) {
std::string celltype = cell->type.str();
if (celltype.substr(0, 7) == "$array:") {
if (celltype.compare(0, strlen("$array:"), "$array:") == 0)
celltype = basic_cell_type(celltype);
}
if (design->module(celltype))
hierarchy_worker(design, used, design->module(celltype), indent+4);
}
@ -521,9 +520,8 @@ int find_top_mod_score(Design *design, Module *module, dict<Module*, int> &db)
for (auto cell : module->cells()) {
std::string celltype = cell->type.str();
// Is this an array instance
if (celltype.substr(0, 7) == "$array:") {
if (celltype.compare(0, strlen("$array:"), "$array:") == 0)
celltype = basic_cell_type(celltype);
}
// Is this cell a module instance?
auto instModule = design->module(celltype);
// If there is no instance for this, issue a warning.

View File

@ -194,8 +194,8 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
log_assert(sig_wr_en.size() == wr_ports * memory->width);
mem->parameters["\\WR_PORTS"] = Const(wr_ports);
mem->parameters["\\WR_CLK_ENABLE"] = wr_ports ? sig_wr_clk_enable.as_const() : Const(0, 1);
mem->parameters["\\WR_CLK_POLARITY"] = wr_ports ? sig_wr_clk_polarity.as_const() : Const(0, 1);
mem->parameters["\\WR_CLK_ENABLE"] = wr_ports ? sig_wr_clk_enable.as_const() : State::S0;
mem->parameters["\\WR_CLK_POLARITY"] = wr_ports ? sig_wr_clk_polarity.as_const() : State::S0;
mem->setPort("\\WR_CLK", sig_wr_clk);
mem->setPort("\\WR_ADDR", sig_wr_addr);
@ -209,9 +209,9 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
log_assert(sig_rd_data.size() == rd_ports * memory->width);
mem->parameters["\\RD_PORTS"] = Const(rd_ports);
mem->parameters["\\RD_CLK_ENABLE"] = rd_ports ? sig_rd_clk_enable.as_const() : Const(0, 1);
mem->parameters["\\RD_CLK_POLARITY"] = rd_ports ? sig_rd_clk_polarity.as_const() : Const(0, 1);
mem->parameters["\\RD_TRANSPARENT"] = rd_ports ? sig_rd_transparent.as_const() : Const(0, 1);
mem->parameters["\\RD_CLK_ENABLE"] = rd_ports ? sig_rd_clk_enable.as_const() : State::S0;
mem->parameters["\\RD_CLK_POLARITY"] = rd_ports ? sig_rd_clk_polarity.as_const() : State::S0;
mem->parameters["\\RD_TRANSPARENT"] = rd_ports ? sig_rd_transparent.as_const() : State::S0;
mem->setPort("\\RD_CLK", sig_rd_clk);
mem->setPort("\\RD_ADDR", sig_rd_addr);

View File

@ -262,7 +262,7 @@ struct MemoryDffWorker
mux_cells_a[sigmap(cell->getPort("\\A"))] = cell;
mux_cells_b[sigmap(cell->getPort("\\B"))] = cell;
}
if (cell->type == "$not" || cell->type == "$_NOT_" || (cell->type == "$logic_not" && GetSize(cell->getPort("\\A")) == 1)) {
if (cell->type.in("$not", "$_NOT_") || (cell->type == "$logic_not" && GetSize(cell->getPort("\\A")) == 1)) {
SigSpec sig_a = cell->getPort("\\A");
SigSpec sig_y = cell->getPort("\\Y");
if (cell->type == "$not")

View File

@ -301,7 +301,7 @@ struct MemoryMapWorker
RTLIL::Wire *w = w_seladdr;
if (wr_bit != RTLIL::SigSpec(1, 1))
if (wr_bit != State::S1)
{
RTLIL::Cell *c = module->addCell(genid(cell->name, "$wren", i, "", j, "", wr_offset), "$and");
c->parameters["\\A_SIGNED"] = RTLIL::Const(0);

View File

@ -155,7 +155,7 @@ struct MemoryShareWorker
{
bool ignore_data_port = false;
if (cell->type == "$mux" || cell->type == "$pmux")
if (cell->type.in("$mux", "$pmux"))
{
std::vector<RTLIL::SigBit> sig_a = sigmap(cell->getPort("\\A"));
std::vector<RTLIL::SigBit> sig_b = sigmap(cell->getPort("\\B"));
@ -173,7 +173,7 @@ struct MemoryShareWorker
continue;
}
if ((cell->type == "$memwr" || cell->type == "$memrd") &&
if (cell->type.in("$memwr", "$memrd") &&
cell->parameters.at("\\MEMID").decode_string() == memid)
ignore_data_port = true;
@ -690,7 +690,7 @@ struct MemoryShareWorker
sigmap_xmux.add(cell->getPort("\\Y"), sig_a);
}
if (cell->type == "$mux" || cell->type == "$pmux")
if (cell->type.in("$mux", "$pmux"))
{
std::vector<RTLIL::SigBit> sig_y = sigmap(cell->getPort("\\Y"));
for (int i = 0; i < int(sig_y.size()); i++)

View File

@ -4,6 +4,7 @@ OBJS += passes/opt/opt_merge.o
OBJS += passes/opt/opt_muxtree.o
OBJS += passes/opt/opt_reduce.o
OBJS += passes/opt/opt_rmdff.o
OBJS += passes/opt/opt_share.o
OBJS += passes/opt/opt_clean.o
OBJS += passes/opt/opt_expr.o
@ -16,4 +17,3 @@ OBJS += passes/opt/opt_lut.o
OBJS += passes/opt/pmux2shiftx.o
OBJS += passes/opt/muxpack.o
endif

View File

@ -37,22 +37,22 @@ struct ExclusiveDatabase
SigBit y_port;
pool<Cell*> reduce_or;
for (auto cell : module->cells()) {
if (cell->type == "$eq") {
nonconst_sig = sigmap(cell->getPort("\\A"));
const_sig = sigmap(cell->getPort("\\B"));
if (cell->type == ID($eq)) {
nonconst_sig = sigmap(cell->getPort(ID::A));
const_sig = sigmap(cell->getPort(ID::B));
if (!const_sig.is_fully_const()) {
if (!nonconst_sig.is_fully_const())
continue;
std::swap(nonconst_sig, const_sig);
}
y_port = sigmap(cell->getPort("\\Y"));
y_port = sigmap(cell->getPort(ID::Y));
}
else if (cell->type == "$logic_not") {
nonconst_sig = sigmap(cell->getPort("\\A"));
const_sig = Const(RTLIL::S0, GetSize(nonconst_sig));
y_port = sigmap(cell->getPort("\\Y"));
else if (cell->type == ID($logic_not)) {
nonconst_sig = sigmap(cell->getPort(ID::A));
const_sig = Const(State::S0, GetSize(nonconst_sig));
y_port = sigmap(cell->getPort(ID::Y));
}
else if (cell->type == "$reduce_or") {
else if (cell->type == ID($reduce_or)) {
reduce_or.insert(cell);
continue;
}
@ -66,7 +66,7 @@ struct ExclusiveDatabase
for (auto cell : reduce_or) {
nonconst_sig = SigSpec();
std::vector<Const> values;
SigSpec a_port = sigmap(cell->getPort("\\A"));
SigSpec a_port = sigmap(cell->getPort(ID::A));
for (auto bit : a_port) {
auto it = sig_cmp_prev.find(bit);
if (it == sig_cmp_prev.end()) {
@ -84,7 +84,7 @@ struct ExclusiveDatabase
}
if (nonconst_sig.empty())
continue;
y_port = sigmap(cell->getPort("\\Y"));
y_port = sigmap(cell->getPort(ID::Y));
sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values));
}
}
@ -135,7 +135,7 @@ struct MuxpackWorker
{
for (auto wire : module->wires())
{
if (wire->port_output || wire->get_bool_attribute("\\keep")) {
if (wire->port_output || wire->get_bool_attribute(ID::keep)) {
for (auto bit : sigmap(wire))
sigbit_with_non_chain_users.insert(bit);
}
@ -143,13 +143,13 @@ struct MuxpackWorker
for (auto cell : module->cells())
{
if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep"))
if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID::keep))
{
SigSpec a_sig = sigmap(cell->getPort("\\A"));
SigSpec a_sig = sigmap(cell->getPort(ID::A));
SigSpec b_sig;
if (cell->type == "$mux")
b_sig = sigmap(cell->getPort("\\B"));
SigSpec y_sig = sigmap(cell->getPort("\\Y"));
if (cell->type == ID($mux))
b_sig = sigmap(cell->getPort(ID::B));
SigSpec y_sig = sigmap(cell->getPort(ID::Y));
if (sig_chain_next.count(a_sig))
for (auto a_bit : a_sig.bits())
@ -186,16 +186,16 @@ struct MuxpackWorker
{
log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type));
SigSpec a_sig = sigmap(cell->getPort("\\A"));
if (cell->type == "$mux") {
SigSpec b_sig = sigmap(cell->getPort("\\B"));
SigSpec a_sig = sigmap(cell->getPort(ID::A));
if (cell->type == ID($mux)) {
SigSpec b_sig = sigmap(cell->getPort(ID::B));
if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
goto start_cell;
if (!sig_chain_prev.count(a_sig))
a_sig = b_sig;
}
else if (cell->type == "$pmux") {
else if (cell->type == ID($pmux)) {
if (!sig_chain_prev.count(a_sig))
goto start_cell;
}
@ -208,8 +208,8 @@ struct MuxpackWorker
{
Cell *prev_cell = sig_chain_prev.at(a_sig);
log_assert(prev_cell);
SigSpec s_sig = sigmap(cell->getPort("\\S"));
s_sig.append(sigmap(prev_cell->getPort("\\S")));
SigSpec s_sig = sigmap(cell->getPort(ID(S)));
s_sig.append(sigmap(prev_cell->getPort(ID(S))));
if (!excl_db.query(s_sig))
goto start_cell;
}
@ -230,7 +230,7 @@ struct MuxpackWorker
{
chain.push_back(c);
SigSpec y_sig = sigmap(c->getPort("\\Y"));
SigSpec y_sig = sigmap(c->getPort(ID::Y));
if (sig_chain_next.count(y_sig) == 0)
break;
@ -269,29 +269,29 @@ struct MuxpackWorker
mux_count += cases;
pmux_count += 1;
first_cell->type = "$pmux";
SigSpec b_sig = first_cell->getPort("\\B");
SigSpec s_sig = first_cell->getPort("\\S");
first_cell->type = ID($pmux);
SigSpec b_sig = first_cell->getPort(ID::B);
SigSpec s_sig = first_cell->getPort(ID(S));
for (int i = 1; i < cases; i++) {
Cell* prev_cell = chain[cursor+i-1];
Cell* cursor_cell = chain[cursor+i];
if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) {
b_sig.append(cursor_cell->getPort("\\B"));
s_sig.append(cursor_cell->getPort("\\S"));
if (sigmap(prev_cell->getPort(ID::Y)) == sigmap(cursor_cell->getPort(ID::A))) {
b_sig.append(cursor_cell->getPort(ID::B));
s_sig.append(cursor_cell->getPort(ID(S)));
}
else {
log_assert(cursor_cell->type == "$mux");
b_sig.append(cursor_cell->getPort("\\A"));
s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S")));
log_assert(cursor_cell->type == ID($mux));
b_sig.append(cursor_cell->getPort(ID::A));
s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort(ID(S))));
}
remove_cells.insert(cursor_cell);
}
first_cell->setPort("\\B", b_sig);
first_cell->setPort("\\S", s_sig);
first_cell->setParam("\\S_WIDTH", GetSize(s_sig));
first_cell->setPort("\\Y", last_cell->getPort("\\Y"));
first_cell->setPort(ID::B, b_sig);
first_cell->setPort(ID(S), s_sig);
first_cell->setParam(ID(S_WIDTH), GetSize(s_sig));
first_cell->setPort(ID::Y, last_cell->getPort(ID::Y));
cursor += cases;
}

View File

@ -44,6 +44,7 @@ struct OptPass : public Pass {
log(" opt_muxtree\n");
log(" opt_reduce [-fine] [-full]\n");
log(" opt_merge [-share_all]\n");
log(" opt_share (-full only)\n");
log(" opt_rmdff [-keepdc] [-sat]\n");
log(" opt_clean [-purge]\n");
log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
@ -70,6 +71,7 @@ struct OptPass : public Pass {
std::string opt_reduce_args;
std::string opt_merge_args;
std::string opt_rmdff_args;
bool opt_share = false;
bool fast_mode = false;
log_header(design, "Executing OPT pass (performing simple optimizations).\n");
@ -105,6 +107,7 @@ struct OptPass : public Pass {
if (args[argidx] == "-full") {
opt_expr_args += " -full";
opt_reduce_args += " -full";
opt_share = true;
continue;
}
if (args[argidx] == "-keepdc") {
@ -151,6 +154,8 @@ struct OptPass : public Pass {
Pass::call(design, "opt_muxtree");
Pass::call(design, "opt_reduce" + opt_reduce_args);
Pass::call(design, "opt_merge" + opt_merge_args);
if (opt_share)
Pass::call(design, "opt_share");
Pass::call(design, "opt_rmdff" + opt_rmdff_args);
Pass::call(design, "opt_clean" + opt_clean_args);
Pass::call(design, "opt_expr" + opt_expr_args);

View File

@ -52,7 +52,7 @@ struct keep_cache_t
return cache.at(module);
cache[module] = true;
if (!module->get_bool_attribute("\\keep")) {
if (!module->get_bool_attribute(ID::keep)) {
bool found_keep = false;
for (auto cell : module->cells())
if (query(cell)) found_keep = true;
@ -64,7 +64,7 @@ struct keep_cache_t
bool query(Cell *cell)
{
if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3", "$specrule"))
if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover), ID($specify2), ID($specify3), ID($specrule)))
return true;
if (cell->has_keep_attr())
@ -122,7 +122,7 @@ void rmunused_module_cells(Module *module, bool verbose)
for (auto &it : module->wires_) {
Wire *wire = it.second;
if (wire->port_output || wire->get_bool_attribute("\\keep")) {
if (wire->port_output || wire->get_bool_attribute(ID::keep)) {
for (auto bit : sigmap(wire))
for (auto c : wire2driver[bit])
queue.insert(c), unused.erase(c);
@ -177,8 +177,8 @@ void rmunused_module_cells(Module *module, bool verbose)
int count_nontrivial_wire_attrs(RTLIL::Wire *w)
{
int count = w->attributes.size();
count -= w->attributes.count("\\src");
count -= w->attributes.count("\\unused_bits");
count -= w->attributes.count(ID(src));
count -= w->attributes.count(ID(unused_bits));
return count;
}
@ -222,10 +222,10 @@ bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool &regs, SigPoo
bool check_public_name(RTLIL::IdString id)
{
const std::string &id_str = id.str();
if (id_str[0] == '$')
if (id.begins_with("$"))
return false;
if (id_str.substr(0, 2) == "\\_" && (id_str[id_str.size()-1] == '_' || id_str.find("_[") != std::string::npos))
const std::string &id_str = id.str();
if (id.begins_with("\\_") && (id.ends_with("_") || id_str.find("_[") != std::string::npos))
return false;
if (id_str.find(".$") != std::string::npos)
return false;
@ -297,7 +297,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
if (!wire->port_input)
used_signals_nodrivers.add(sig);
}
if (wire->get_bool_attribute("\\keep")) {
if (wire->get_bool_attribute(ID::keep)) {
RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
assign_map.apply(sig);
used_signals.add(sig);
@ -311,19 +311,19 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
log_assert(GetSize(s1) == GetSize(s2));
Const initval;
if (wire->attributes.count("\\init"))
initval = wire->attributes.at("\\init");
if (wire->attributes.count(ID(init)))
initval = wire->attributes.at(ID(init));
if (GetSize(initval) != GetSize(wire))
initval.bits.resize(GetSize(wire), State::Sx);
if (initval.is_fully_undef())
wire->attributes.erase("\\init");
wire->attributes.erase(ID(init));
if (GetSize(wire) == 0) {
// delete zero-width wires, unless they are module ports
if (wire->port_id == 0)
goto delete_this_wire;
} else
if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) {
if (wire->port_id != 0 || wire->get_bool_attribute(ID::keep) || !initval.is_fully_undef()) {
// do not delete anything with "keep" or module ports or initialized wires
} else
if (!purge_mode && check_public_name(wire->name) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) {
@ -357,9 +357,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
}
if (new_conn.first.size() > 0) {
if (initval.is_fully_undef())
wire->attributes.erase("\\init");
wire->attributes.erase(ID(init));
else
wire->attributes.at("\\init") = initval;
wire->attributes.at(ID(init)) = initval;
used_signals.add(new_conn.first);
used_signals.add(new_conn.second);
module->connect(new_conn);
@ -377,11 +377,11 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
}
}
if (unused_bits.empty() || wire->port_id != 0)
wire->attributes.erase("\\unused_bits");
wire->attributes.erase(ID(unused_bits));
else
wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits);
wire->attributes[ID(unused_bits)] = RTLIL::Const(unused_bits);
} else {
wire->attributes.erase("\\unused_bits");
wire->attributes.erase(ID(unused_bits));
}
}
}
@ -413,18 +413,18 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
dict<SigBit, State> qbits;
for (auto cell : module->cells())
if (fftypes.cell_known(cell->type) && cell->hasPort("\\Q"))
if (fftypes.cell_known(cell->type) && cell->hasPort(ID(Q)))
{
SigSpec sig = cell->getPort("\\Q");
SigSpec sig = cell->getPort(ID(Q));
for (int i = 0; i < GetSize(sig); i++)
{
SigBit bit = sig[i];
if (bit.wire == nullptr || bit.wire->attributes.count("\\init") == 0)
if (bit.wire == nullptr || bit.wire->attributes.count(ID(init)) == 0)
continue;
Const init = bit.wire->attributes.at("\\init");
Const init = bit.wire->attributes.at(ID(init));
if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz)
continue;
@ -439,10 +439,10 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
if (!purge_mode && wire->name[0] == '\\')
continue;
if (wire->attributes.count("\\init") == 0)
if (wire->attributes.count(ID(init)) == 0)
continue;
Const init = wire->attributes.at("\\init");
Const init = wire->attributes.at(ID(init));
for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++)
{
@ -465,7 +465,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
if (verbose)
log_debug(" removing redundant init attribute on %s.\n", log_id(wire));
wire->attributes.erase("\\init");
wire->attributes.erase(ID(init));
did_something = true;
next_wire:;
}
@ -480,10 +480,10 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
std::vector<RTLIL::Cell*> delcells;
for (auto cell : module->cells())
if (cell->type.in("$pos", "$_BUF_") && !cell->has_keep_attr()) {
bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool();
RTLIL::SigSpec a = cell->getPort("\\A");
RTLIL::SigSpec y = cell->getPort("\\Y");
if (cell->type.in(ID($pos), ID($_BUF_)) && !cell->has_keep_attr()) {
bool is_signed = cell->type == ID($pos) && cell->getParam(ID(A_SIGNED)).as_bool();
RTLIL::SigSpec a = cell->getPort(ID::A);
RTLIL::SigSpec y = cell->getPort(ID::Y);
a.extend_u0(GetSize(y), is_signed);
module->connect(y, a);
delcells.push_back(cell);
@ -491,7 +491,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
for (auto cell : delcells) {
if (verbose)
log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
log_signal(cell->getPort("\\Y")), log_signal(cell->getPort("\\A")));
log_signal(cell->getPort(ID::Y)), log_signal(cell->getPort(ID::A)));
module->remove(cell);
}
if (!delcells.empty())

View File

@ -35,10 +35,10 @@ void demorgan_worker(
//TODO: Add support for reduce_xor
//DeMorgan of XOR is either XOR (if even number of inputs) or XNOR (if odd number)
if( (cell->type != "$reduce_and") && (cell->type != "$reduce_or") )
if( (cell->type != ID($reduce_and)) && (cell->type != ID($reduce_or)) )
return;
auto insig = sigmap(cell->getPort("\\A"));
auto insig = sigmap(cell->getPort(ID::A));
log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig));
int num_inverted = 0;
for(int i=0; i<GetSize(insig); i++)
@ -51,7 +51,7 @@ void demorgan_worker(
bool inverted = false;
for(auto x : ports)
{
if(x.port == "\\Y" && x.cell->type == "$_NOT_")
if(x.port == ID::Y && x.cell->type == ID($_NOT_))
{
inverted = true;
break;
@ -85,7 +85,7 @@ void demorgan_worker(
RTLIL::Cell* srcinv = NULL;
for(auto x : ports)
{
if(x.port == "\\Y" && x.cell->type == "$_NOT_")
if(x.port == ID::Y && x.cell->type == ID($_NOT_))
{
srcinv = x.cell;
break;
@ -103,7 +103,7 @@ void demorgan_worker(
//We ARE inverted - bypass it
//Don't automatically delete the inverter since other stuff might still use it
else
insig[i] = srcinv->getPort("\\A");
insig[i] = srcinv->getPort(ID::A);
}
//Cosmetic fixup: If our input is just a scrambled version of one bus, rearrange it
@ -151,20 +151,20 @@ void demorgan_worker(
}
//Push the new input signal back to the reduction (after bypassing/adding inverters)
cell->setPort("\\A", insig);
cell->setPort(ID::A, insig);
//Change the cell type
if(cell->type == "$reduce_and")
cell->type = "$reduce_or";
else if(cell->type == "$reduce_or")
cell->type = "$reduce_and";
if(cell->type == ID($reduce_and))
cell->type = ID($reduce_or);
else if(cell->type == ID($reduce_or))
cell->type = ID($reduce_and);
//don't change XOR
//Add an inverter to the output
auto inverted_output = cell->getPort("\\Y");
auto inverted_output = cell->getPort(ID::Y);
auto uninverted_output = m->addWire(NEW_ID);
m->addNot(NEW_ID, RTLIL::SigSpec(uninverted_output), inverted_output);
cell->setPort("\\Y", uninverted_output);
cell->setPort(ID::Y, uninverted_output);
}
struct OptDemorganPass : public Pass {

File diff suppressed because it is too large Load Diff

View File

@ -40,9 +40,9 @@ struct OptLutWorker
bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs)
{
SigSpec lut_input = sigmap(lut->getPort("\\A"));
int lut_width = lut->getParam("\\WIDTH").as_int();
Const lut_table = lut->getParam("\\LUT");
SigSpec lut_input = sigmap(lut->getPort(ID::A));
int lut_width = lut->getParam(ID(WIDTH)).as_int();
Const lut_table = lut->getParam(ID(LUT));
int lut_index = 0;
for (int i = 0; i < lut_width; i++)
@ -81,7 +81,7 @@ struct OptLutWorker
}
}
log("Number of LUTs: %8zu\n", luts.size());
log("Number of LUTs: %8d\n", GetSize(luts));
for (int arity = 1; arity <= max_arity; arity++)
{
if (arity_counts[arity])
@ -99,10 +99,16 @@ struct OptLutWorker
log("Discovering LUTs.\n");
for (auto cell : module->selected_cells())
{
if (cell->type == "$lut")
if (cell->type == ID($lut))
{
int lut_width = cell->getParam("\\WIDTH").as_int();
SigSpec lut_input = cell->getPort("\\A");
if (cell->has_keep_attr())
continue;
SigBit lut_output = cell->getPort(ID::Y);
if (lut_output.wire->get_bool_attribute(ID::keep))
continue;
int lut_width = cell->getParam(ID(WIDTH)).as_int();
SigSpec lut_input = cell->getPort(ID::A);
int lut_arity = 0;
log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
@ -199,7 +205,7 @@ struct OptLutWorker
}
auto lut = worklist.pop();
SigSpec lut_input = sigmap(lut->getPort("\\A"));
SigSpec lut_input = sigmap(lut->getPort(ID::A));
pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut];
vector<SigBit> lut_inputs;
@ -261,7 +267,7 @@ struct OptLutWorker
log_debug(" Not eliminating cell (connected to dedicated logic).\n");
else
{
SigSpec lut_output = lut->getPort("\\Y");
SigSpec lut_output = lut->getPort(ID::Y);
for (auto &port : index.query_ports(lut_output))
{
if (port.cell != lut && luts.count(port.cell))
@ -297,13 +303,13 @@ struct OptLutWorker
}
auto lutA = worklist.pop();
SigSpec lutA_input = sigmap(lutA->getPort("\\A"));
SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]);
int lutA_width = lutA->getParam("\\WIDTH").as_int();
SigSpec lutA_input = sigmap(lutA->getPort(ID::A));
SigSpec lutA_output = sigmap(lutA->getPort(ID::Y)[0]);
int lutA_width = lutA->getParam(ID(WIDTH)).as_int();
int lutA_arity = luts_arity[lutA];
pool<int> &lutA_dlogic_inputs = luts_dlogic_inputs[lutA];
auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y"));
auto lutA_output_ports = index.query_ports(lutA->getPort(ID::Y));
if (lutA_output_ports.size() != 2)
continue;
@ -315,15 +321,15 @@ struct OptLutWorker
if (luts.count(port.cell))
{
auto lutB = port.cell;
SigSpec lutB_input = sigmap(lutB->getPort("\\A"));
SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]);
int lutB_width = lutB->getParam("\\WIDTH").as_int();
SigSpec lutB_input = sigmap(lutB->getPort(ID::A));
SigSpec lutB_output = sigmap(lutB->getPort(ID::Y)[0]);
int lutB_width = lutB->getParam(ID(WIDTH)).as_int();
int lutB_arity = luts_arity[lutB];
pool<int> &lutB_dlogic_inputs = luts_dlogic_inputs[lutB];
log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
if (index.query_is_output(lutA->getPort("\\Y")))
if (index.query_is_output(lutA->getPort(ID::Y)))
{
log_debug(" Not combining LUTs (cascade connection feeds module output).\n");
continue;
@ -351,14 +357,14 @@ struct OptLutWorker
int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size();
if (lutA_dlogic_inputs.size())
log_debug(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size());
log_debug(" Cell A is a %d-LUT with %d dedicated connections. ", lutA_arity, GetSize(lutA_dlogic_inputs));
else
log_debug(" Cell A is a %d-LUT. ", lutA_arity);
if (lutB_dlogic_inputs.size())
log_debug("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size());
log_debug("Cell B is a %d-LUT with %d dedicated connections.\n", lutB_arity, GetSize(lutB_dlogic_inputs));
else
log_debug("Cell B is a %d-LUT.\n", lutB_arity);
log_debug(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity);
log_debug(" Cells share %d input(s) and can be merged into one %d-LUT.\n", GetSize(common_inputs), lutM_arity);
const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B;
int combine_mask = 0;
@ -366,7 +372,7 @@ struct OptLutWorker
log_debug(" Not combining LUTs into cell A (combined LUT wider than cell A).\n");
else if (lutB_dlogic_inputs.size() > 0)
log_debug(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n");
else if (lutB->get_bool_attribute("\\lut_keep"))
else if (lutB->get_bool_attribute(ID(lut_keep)))
log_debug(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
else
combine_mask |= COMBINE_A;
@ -374,7 +380,7 @@ struct OptLutWorker
log_debug(" Not combining LUTs into cell B (combined LUT wider than cell B).\n");
else if (lutA_dlogic_inputs.size() > 0)
log_debug(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n");
else if (lutA->get_bool_attribute("\\lut_keep"))
else if (lutA->get_bool_attribute(ID(lut_keep)))
log_debug(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
else
combine_mask |= COMBINE_B;
@ -434,8 +440,8 @@ struct OptLutWorker
lutR_unique.insert(bit);
}
int lutM_width = lutM->getParam("\\WIDTH").as_int();
SigSpec lutM_input = sigmap(lutM->getPort("\\A"));
int lutM_width = lutM->getParam(ID(WIDTH)).as_int();
SigSpec lutM_input = sigmap(lutM->getPort(ID::A));
std::vector<SigBit> lutM_new_inputs;
for (int i = 0; i < lutM_width; i++)
{
@ -476,13 +482,13 @@ struct OptLutWorker
lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs);
}
log_debug(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str());
log_debug(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str());
log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID(LUT)).as_string().c_str());
log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID(LUT)).as_string().c_str());
log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
lutM->setParam("\\LUT", lutM_new_table);
lutM->setPort("\\A", lutM_new_inputs);
lutM->setPort("\\Y", lutB_output);
lutM->setParam(ID(LUT), lutM_new_table);
lutM->setPort(ID::A, lutM_new_inputs);
lutM->setPort(ID::Y, lutB_output);
luts_arity[lutM] = lutM_arity;
luts.erase(lutR);

View File

@ -47,8 +47,8 @@ struct OptMergeWorker
static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
{
SigSpec sig_s = conn.at("\\S");
SigSpec sig_b = conn.at("\\B");
SigSpec sig_s = conn.at(ID(S));
SigSpec sig_b = conn.at(ID::B);
int s_width = GetSize(sig_s);
int width = GetSize(sig_b) / s_width;
@ -59,12 +59,12 @@ struct OptMergeWorker
std::sort(sb_pairs.begin(), sb_pairs.end());
conn["\\S"] = SigSpec();
conn["\\B"] = SigSpec();
conn[ID(S)] = SigSpec();
conn[ID::B] = SigSpec();
for (auto &it : sb_pairs) {
conn["\\S"].append(it.first);
conn["\\B"].append(it.second);
conn[ID(S)].append(it.first);
conn[ID::B].append(it.second);
}
}
@ -94,32 +94,32 @@ struct OptMergeWorker
const dict<RTLIL::IdString, RTLIL::SigSpec> *conn = &cell->connections();
dict<RTLIL::IdString, RTLIL::SigSpec> alt_conn;
if (cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor" || cell->type == "$add" || cell->type == "$mul" ||
cell->type == "$logic_and" || cell->type == "$logic_or" || cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_") {
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
alt_conn = *conn;
if (assign_map(alt_conn.at("\\A")) < assign_map(alt_conn.at("\\B"))) {
alt_conn["\\A"] = conn->at("\\B");
alt_conn["\\B"] = conn->at("\\A");
if (assign_map(alt_conn.at(ID::A)) < assign_map(alt_conn.at(ID::B))) {
alt_conn[ID::A] = conn->at(ID::B);
alt_conn[ID::B] = conn->at(ID::A);
}
conn = &alt_conn;
} else
if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor") {
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
alt_conn = *conn;
assign_map.apply(alt_conn.at("\\A"));
alt_conn.at("\\A").sort();
assign_map.apply(alt_conn.at(ID::A));
alt_conn.at(ID::A).sort();
conn = &alt_conn;
} else
if (cell->type == "$reduce_and" || cell->type == "$reduce_or" || cell->type == "$reduce_bool") {
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
alt_conn = *conn;
assign_map.apply(alt_conn.at("\\A"));
alt_conn.at("\\A").sort_and_unify();
assign_map.apply(alt_conn.at(ID::A));
alt_conn.at(ID::A).sort_and_unify();
conn = &alt_conn;
} else
if (cell->type == "$pmux") {
if (cell->type == ID($pmux)) {
alt_conn = *conn;
assign_map.apply(alt_conn.at("\\A"));
assign_map.apply(alt_conn.at("\\B"));
assign_map.apply(alt_conn.at("\\S"));
assign_map.apply(alt_conn.at(ID::A));
assign_map.apply(alt_conn.at(ID::B));
assign_map.apply(alt_conn.at(ID(S)));
sort_pmux_conn(alt_conn);
conn = &alt_conn;
}
@ -189,28 +189,28 @@ struct OptMergeWorker
assign_map.apply(it.second);
}
if (cell1->type == "$and" || cell1->type == "$or" || cell1->type == "$xor" || cell1->type == "$xnor" || cell1->type == "$add" || cell1->type == "$mul" ||
cell1->type == "$logic_and" || cell1->type == "$logic_or" || cell1->type == "$_AND_" || cell1->type == "$_OR_" || cell1->type == "$_XOR_") {
if (conn1.at("\\A") < conn1.at("\\B")) {
RTLIL::SigSpec tmp = conn1["\\A"];
conn1["\\A"] = conn1["\\B"];
conn1["\\B"] = tmp;
if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) ||
cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) {
if (conn1.at(ID::A) < conn1.at(ID::B)) {
RTLIL::SigSpec tmp = conn1[ID::A];
conn1[ID::A] = conn1[ID::B];
conn1[ID::B] = tmp;
}
if (conn2.at("\\A") < conn2.at("\\B")) {
RTLIL::SigSpec tmp = conn2["\\A"];
conn2["\\A"] = conn2["\\B"];
conn2["\\B"] = tmp;
if (conn2.at(ID::A) < conn2.at(ID::B)) {
RTLIL::SigSpec tmp = conn2[ID::A];
conn2[ID::A] = conn2[ID::B];
conn2[ID::B] = tmp;
}
} else
if (cell1->type == "$reduce_xor" || cell1->type == "$reduce_xnor") {
conn1["\\A"].sort();
conn2["\\A"].sort();
if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) {
conn1[ID::A].sort();
conn2[ID::A].sort();
} else
if (cell1->type == "$reduce_and" || cell1->type == "$reduce_or" || cell1->type == "$reduce_bool") {
conn1["\\A"].sort_and_unify();
conn2["\\A"].sort_and_unify();
if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) {
conn1[ID::A].sort_and_unify();
conn2[ID::A].sort_and_unify();
} else
if (cell1->type == "$pmux") {
if (cell1->type == ID($pmux)) {
sort_pmux_conn(conn1);
sort_pmux_conn(conn2);
}
@ -222,9 +222,9 @@ struct OptMergeWorker
return true;
}
if (cell1->type.substr(0, 1) == "$" && conn1.count("\\Q") != 0) {
std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort("\\Q")).to_sigbit_vector();
std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort("\\Q")).to_sigbit_vector();
if (cell1->type.begins_with("$") && conn1.count(ID(Q)) != 0) {
std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector();
std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort(ID(Q))).to_sigbit_vector();
for (size_t i = 0; i < q1.size(); i++)
if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) {
lt = q1.at(i) < q2.at(i);
@ -271,24 +271,24 @@ struct OptMergeWorker
ct.setup_stdcells_mem();
if (mode_nomux) {
ct.cell_types.erase("$mux");
ct.cell_types.erase("$pmux");
ct.cell_types.erase(ID($mux));
ct.cell_types.erase(ID($pmux));
}
ct.cell_types.erase("$tribuf");
ct.cell_types.erase("$_TBUF_");
ct.cell_types.erase("$anyseq");
ct.cell_types.erase("$anyconst");
ct.cell_types.erase("$allseq");
ct.cell_types.erase("$allconst");
ct.cell_types.erase(ID($tribuf));
ct.cell_types.erase(ID($_TBUF_));
ct.cell_types.erase(ID($anyseq));
ct.cell_types.erase(ID($anyconst));
ct.cell_types.erase(ID($allseq));
ct.cell_types.erase(ID($allconst));
log("Finding identical cells in module `%s'.\n", module->name.c_str());
assign_map.set(module);
dff_init_map.set(module);
for (auto &it : module->wires_)
if (it.second->attributes.count("\\init") != 0) {
Const initval = it.second->attributes.at("\\init");
if (it.second->attributes.count(ID(init)) != 0) {
Const initval = it.second->attributes.at(ID(init));
for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++)
if (initval[i] == State::S0 || initval[i] == State::S1)
dff_init_map.add(SigBit(it.second, i), initval[i]);

View File

@ -84,12 +84,12 @@ struct OptMuxtreeWorker
// .const_deactivated
for (auto cell : module->cells())
{
if (cell->type == "$mux" || cell->type == "$pmux")
if (cell->type.in(ID($mux), ID($pmux)))
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_b = cell->getPort("\\B");
RTLIL::SigSpec sig_s = cell->getPort("\\S");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_s = cell->getPort(ID(S));
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
muxinfo_t muxinfo;
muxinfo.cell = cell;
@ -137,7 +137,7 @@ struct OptMuxtreeWorker
}
}
for (auto wire : module->wires()) {
if (wire->port_output || wire->get_bool_attribute("\\keep"))
if (wire->port_output || wire->get_bool_attribute(ID::keep))
for (int idx : sig2bits(RTLIL::SigSpec(wire)))
bit2info[idx].seen_non_mux = true;
}
@ -227,10 +227,10 @@ struct OptMuxtreeWorker
continue;
}
RTLIL::SigSpec sig_a = mi.cell->getPort("\\A");
RTLIL::SigSpec sig_b = mi.cell->getPort("\\B");
RTLIL::SigSpec sig_s = mi.cell->getPort("\\S");
RTLIL::SigSpec sig_y = mi.cell->getPort("\\Y");
RTLIL::SigSpec sig_a = mi.cell->getPort(ID::A);
RTLIL::SigSpec sig_b = mi.cell->getPort(ID::B);
RTLIL::SigSpec sig_s = mi.cell->getPort(ID(S));
RTLIL::SigSpec sig_y = mi.cell->getPort(ID::Y);
RTLIL::SigSpec sig_ports = sig_b;
sig_ports.append(sig_a);
@ -255,14 +255,14 @@ struct OptMuxtreeWorker
}
}
mi.cell->setPort("\\A", new_sig_a);
mi.cell->setPort("\\B", new_sig_b);
mi.cell->setPort("\\S", new_sig_s);
mi.cell->setPort(ID::A, new_sig_a);
mi.cell->setPort(ID::B, new_sig_b);
mi.cell->setPort(ID(S), new_sig_s);
if (GetSize(new_sig_s) == 1) {
mi.cell->type = "$mux";
mi.cell->parameters.erase("\\S_WIDTH");
mi.cell->type = ID($mux);
mi.cell->parameters.erase(ID(S_WIDTH));
} else {
mi.cell->parameters["\\S_WIDTH"] = RTLIL::Const(GetSize(new_sig_s));
mi.cell->parameters[ID(S_WIDTH)] = RTLIL::Const(GetSize(new_sig_s));
}
}
}
@ -364,9 +364,9 @@ struct OptMuxtreeWorker
int width = 0;
idict<int> ctrl_bits;
if (portname == "\\B")
width = GetSize(muxinfo.cell->getPort("\\A"));
for (int bit : sig2bits(muxinfo.cell->getPort("\\S"), false))
if (portname == ID::B)
width = GetSize(muxinfo.cell->getPort(ID::A));
for (int bit : sig2bits(muxinfo.cell->getPort(ID(S)), false))
ctrl_bits(bit);
int port_idx = 0, port_off = 0;
@ -414,8 +414,8 @@ struct OptMuxtreeWorker
// set input ports to constants if we find known active or inactive signals
if (do_replace_known) {
replace_known(knowledge, muxinfo, "\\A");
replace_known(knowledge, muxinfo, "\\B");
replace_known(knowledge, muxinfo, ID::A);
replace_known(knowledge, muxinfo, ID::B);
}
// if there is a constant activated port we just use it

View File

@ -43,13 +43,13 @@ struct OptReduceWorker
return;
cells.erase(cell);
RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
pool<RTLIL::SigBit> new_sig_a_bits;
for (auto &bit : sig_a.to_sigbit_set())
{
if (bit == RTLIL::State::S0) {
if (cell->type == "$reduce_and") {
if (cell->type == ID($reduce_and)) {
new_sig_a_bits.clear();
new_sig_a_bits.insert(RTLIL::State::S0);
break;
@ -57,7 +57,7 @@ struct OptReduceWorker
continue;
}
if (bit == RTLIL::State::S1) {
if (cell->type == "$reduce_or") {
if (cell->type == ID($reduce_or)) {
new_sig_a_bits.clear();
new_sig_a_bits.insert(RTLIL::State::S1);
break;
@ -73,8 +73,8 @@ struct OptReduceWorker
for (auto child_cell : drivers.find(bit)) {
if (child_cell->type == cell->type) {
opt_reduce(cells, drivers, child_cell);
if (child_cell->getPort("\\Y")[0] == bit) {
pool<RTLIL::SigBit> child_sig_a_bits = assign_map(child_cell->getPort("\\A")).to_sigbit_pool();
if (child_cell->getPort(ID::Y)[0] == bit) {
pool<RTLIL::SigBit> child_sig_a_bits = assign_map(child_cell->getPort(ID::A)).to_sigbit_pool();
new_sig_a_bits.insert(child_sig_a_bits.begin(), child_sig_a_bits.end());
} else
new_sig_a_bits.insert(RTLIL::State::S0);
@ -87,22 +87,22 @@ struct OptReduceWorker
RTLIL::SigSpec new_sig_a(new_sig_a_bits);
if (new_sig_a != sig_a || sig_a.size() != cell->getPort("\\A").size()) {
if (new_sig_a != sig_a || sig_a.size() != cell->getPort(ID::A).size()) {
log(" New input vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_a));
did_something = true;
total_count++;
}
cell->setPort("\\A", new_sig_a);
cell->parameters["\\A_WIDTH"] = RTLIL::Const(new_sig_a.size());
cell->setPort(ID::A, new_sig_a);
cell->parameters[ID(A_WIDTH)] = RTLIL::Const(new_sig_a.size());
return;
}
void opt_mux(RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
RTLIL::SigSpec sig_s = assign_map(cell->getPort("\\S"));
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID(S)));
RTLIL::SigSpec new_sig_b, new_sig_s;
pool<RTLIL::SigSpec> handled_sig;
@ -123,15 +123,15 @@ struct OptReduceWorker
if (this_s.size() > 1)
{
RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, "$reduce_or");
reduce_or_cell->setPort("\\A", this_s);
reduce_or_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
reduce_or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(this_s.size());
reduce_or_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or));
reduce_or_cell->setPort(ID::A, this_s);
reduce_or_cell->parameters[ID(A_SIGNED)] = RTLIL::Const(0);
reduce_or_cell->parameters[ID(A_WIDTH)] = RTLIL::Const(this_s.size());
reduce_or_cell->parameters[ID(Y_WIDTH)] = RTLIL::Const(1);
RTLIL::Wire *reduce_or_wire = module->addWire(NEW_ID);
this_s = RTLIL::SigSpec(reduce_or_wire);
reduce_or_cell->setPort("\\Y", this_s);
reduce_or_cell->setPort(ID::Y, this_s);
}
new_sig_b.append(this_b);
@ -147,28 +147,28 @@ struct OptReduceWorker
if (new_sig_s.size() == 0)
{
module->connect(RTLIL::SigSig(cell->getPort("\\Y"), cell->getPort("\\A")));
assign_map.add(cell->getPort("\\Y"), cell->getPort("\\A"));
module->connect(RTLIL::SigSig(cell->getPort(ID::Y), cell->getPort(ID::A)));
assign_map.add(cell->getPort(ID::Y), cell->getPort(ID::A));
module->remove(cell);
}
else
{
cell->setPort("\\B", new_sig_b);
cell->setPort("\\S", new_sig_s);
cell->setPort(ID::B, new_sig_b);
cell->setPort(ID(S), new_sig_s);
if (new_sig_s.size() > 1) {
cell->parameters["\\S_WIDTH"] = RTLIL::Const(new_sig_s.size());
cell->parameters[ID(S_WIDTH)] = RTLIL::Const(new_sig_s.size());
} else {
cell->type = "$mux";
cell->parameters.erase("\\S_WIDTH");
cell->type = ID($mux);
cell->parameters.erase(ID(S_WIDTH));
}
}
}
void opt_mux_bits(RTLIL::Cell *cell)
{
std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort("\\A")).to_sigbit_vector();
std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort("\\B")).to_sigbit_vector();
std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort("\\Y")).to_sigbit_vector();
std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort(ID::A)).to_sigbit_vector();
std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort(ID::B)).to_sigbit_vector();
std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort(ID::Y)).to_sigbit_vector();
std::vector<RTLIL::SigBit> new_sig_y;
RTLIL::SigSig old_sig_conn;
@ -209,29 +209,29 @@ struct OptReduceWorker
if (new_sig_y.size() != sig_y.size())
{
log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort("\\A")),
log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\Y")));
log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
cell->setPort("\\A", RTLIL::SigSpec());
cell->setPort(ID::A, RTLIL::SigSpec());
for (auto &in_tuple : consolidated_in_tuples) {
RTLIL::SigSpec new_a = cell->getPort("\\A");
RTLIL::SigSpec new_a = cell->getPort(ID::A);
new_a.append(in_tuple.at(0));
cell->setPort("\\A", new_a);
cell->setPort(ID::A, new_a);
}
cell->setPort("\\B", RTLIL::SigSpec());
for (int i = 1; i <= cell->getPort("\\S").size(); i++)
cell->setPort(ID::B, RTLIL::SigSpec());
for (int i = 1; i <= cell->getPort(ID(S)).size(); i++)
for (auto &in_tuple : consolidated_in_tuples) {
RTLIL::SigSpec new_b = cell->getPort("\\B");
RTLIL::SigSpec new_b = cell->getPort(ID::B);
new_b.append(in_tuple.at(i));
cell->setPort("\\B", new_b);
cell->setPort(ID::B, new_b);
}
cell->parameters["\\WIDTH"] = RTLIL::Const(new_sig_y.size());
cell->setPort("\\Y", new_sig_y);
cell->parameters[ID(WIDTH)] = RTLIL::Const(new_sig_y.size());
cell->setPort(ID::Y, new_sig_y);
log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort("\\A")),
log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\Y")));
log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
module->connect(old_sig_conn);
@ -253,15 +253,15 @@ struct OptReduceWorker
SigPool mem_wren_sigs;
for (auto &cell_it : module->cells_) {
RTLIL::Cell *cell = cell_it.second;
if (cell->type == "$mem")
mem_wren_sigs.add(assign_map(cell->getPort("\\WR_EN")));
if (cell->type == "$memwr")
mem_wren_sigs.add(assign_map(cell->getPort("\\EN")));
if (cell->type == ID($mem))
mem_wren_sigs.add(assign_map(cell->getPort(ID(WR_EN))));
if (cell->type == ID($memwr))
mem_wren_sigs.add(assign_map(cell->getPort(ID(EN))));
}
for (auto &cell_it : module->cells_) {
RTLIL::Cell *cell = cell_it.second;
if (cell->type == "$dff" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\Q"))))
mem_wren_sigs.add(assign_map(cell->getPort("\\D")));
if (cell->type == ID($dff) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Q)))))
mem_wren_sigs.add(assign_map(cell->getPort(ID(D))));
}
bool keep_expanding_mem_wren_sigs = true;
@ -269,12 +269,12 @@ struct OptReduceWorker
keep_expanding_mem_wren_sigs = false;
for (auto &cell_it : module->cells_) {
RTLIL::Cell *cell = cell_it.second;
if (cell->type == "$mux" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\Y")))) {
if (!mem_wren_sigs.check_all(assign_map(cell->getPort("\\A"))) ||
!mem_wren_sigs.check_all(assign_map(cell->getPort("\\B"))))
if (cell->type == ID($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y)))) {
if (!mem_wren_sigs.check_all(assign_map(cell->getPort(ID::A))) ||
!mem_wren_sigs.check_all(assign_map(cell->getPort(ID::B))))
keep_expanding_mem_wren_sigs = true;
mem_wren_sigs.add(assign_map(cell->getPort("\\A")));
mem_wren_sigs.add(assign_map(cell->getPort("\\B")));
mem_wren_sigs.add(assign_map(cell->getPort(ID::A)));
mem_wren_sigs.add(assign_map(cell->getPort(ID::B)));
}
}
}
@ -286,7 +286,7 @@ struct OptReduceWorker
// merge trees of reduce_* cells to one single cell and unify input vectors
// (only handle reduce_and and reduce_or for various reasons)
const char *type_list[] = { "$reduce_or", "$reduce_and" };
const IdString type_list[] = { ID($reduce_or), ID($reduce_and) };
for (auto type : type_list)
{
SigSet<RTLIL::Cell*> drivers;
@ -296,7 +296,7 @@ struct OptReduceWorker
RTLIL::Cell *cell = cell_it.second;
if (cell->type != type || !design->selected(module, cell))
continue;
drivers.insert(assign_map(cell->getPort("\\Y")), cell);
drivers.insert(assign_map(cell->getPort(ID::Y)), cell);
cells.insert(cell);
}
@ -311,14 +311,14 @@ struct OptReduceWorker
std::vector<RTLIL::Cell*> cells;
for (auto &it : module->cells_)
if ((it.second->type == "$mux" || it.second->type == "$pmux") && design->selected(module, it.second))
if ((it.second->type == ID($mux) || it.second->type == ID($pmux)) && design->selected(module, it.second))
cells.push_back(it.second);
for (auto cell : cells)
{
// this optimization is to aggressive for most coarse-grain applications.
// but we always want it for multiplexers driving write enable ports.
if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort("\\Y"))))
if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y))))
opt_mux_bits(cell);
opt_mux(cell);

View File

@ -41,7 +41,7 @@ void remove_init_attr(SigSpec sig)
for (auto bit : assign_map(sig))
if (init_attributes.count(bit))
for (auto wbit : init_attributes.at(bit))
wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx;
wbit.wire->attributes.at(ID(init))[wbit.offset] = State::Sx;
}
bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
@ -49,39 +49,39 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
SigSpec sig_set, sig_clr;
State pol_set, pol_clr;
if (cell->hasPort("\\S"))
sig_set = cell->getPort("\\S");
if (cell->hasPort(ID(S)))
sig_set = cell->getPort(ID(S));
if (cell->hasPort("\\R"))
sig_clr = cell->getPort("\\R");
if (cell->hasPort(ID(R)))
sig_clr = cell->getPort(ID(R));
if (cell->hasPort("\\SET"))
sig_set = cell->getPort("\\SET");
if (cell->hasPort(ID(SET)))
sig_set = cell->getPort(ID(SET));
if (cell->hasPort("\\CLR"))
sig_clr = cell->getPort("\\CLR");
if (cell->hasPort(ID(CLR)))
sig_clr = cell->getPort(ID(CLR));
log_assert(GetSize(sig_set) == GetSize(sig_clr));
if (cell->type.substr(0,8) == "$_DFFSR_") {
if (cell->type.begins_with("$_DFFSR_")) {
pol_set = cell->type[9] == 'P' ? State::S1 : State::S0;
pol_clr = cell->type[10] == 'P' ? State::S1 : State::S0;
} else
if (cell->type.substr(0,11) == "$_DLATCHSR_") {
if (cell->type.begins_with("$_DLATCHSR_")) {
pol_set = cell->type[12] == 'P' ? State::S1 : State::S0;
pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0;
} else
if (cell->type == "$dffsr" || cell->type == "$dlatchsr") {
pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0;
pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0;
if (cell->type.in(ID($dffsr), ID($dlatchsr))) {
pol_set = cell->parameters[ID(SET_POLARITY)].as_bool() ? State::S1 : State::S0;
pol_clr = cell->parameters[ID(CLR_POLARITY)].as_bool() ? State::S1 : State::S0;
} else
log_abort();
State npol_set = pol_set == State::S0 ? State::S1 : State::S0;
State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0;
SigSpec sig_d = cell->getPort("\\D");
SigSpec sig_q = cell->getPort("\\Q");
SigSpec sig_d = cell->getPort(ID(D));
SigSpec sig_q = cell->getPort(ID(Q));
bool did_something = false;
bool proper_sr = false;
@ -137,20 +137,20 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
return true;
}
if (cell->type == "$dffsr" || cell->type == "$dlatchsr")
if (cell->type.in(ID($dffsr), ID($dlatchsr)))
{
cell->setParam("\\WIDTH", GetSize(sig_d));
cell->setPort("\\SET", sig_set);
cell->setPort("\\CLR", sig_clr);
cell->setPort("\\D", sig_d);
cell->setPort("\\Q", sig_q);
cell->setParam(ID(WIDTH), GetSize(sig_d));
cell->setPort(ID(SET), sig_set);
cell->setPort(ID(CLR), sig_clr);
cell->setPort(ID(D), sig_d);
cell->setPort(ID(Q), sig_q);
}
else
{
cell->setPort("\\S", sig_set);
cell->setPort("\\R", sig_clr);
cell->setPort("\\D", sig_d);
cell->setPort("\\Q", sig_q);
cell->setPort(ID(S), sig_set);
cell->setPort(ID(R), sig_clr);
cell->setPort(ID(D), sig_d);
cell->setPort(ID(Q), sig_q);
}
if (proper_sr)
@ -159,36 +159,36 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
if (used_pol_set && used_pol_clr && pol_set != pol_clr)
return did_something;
if (cell->type == "$dlatchsr")
if (cell->type == ID($dlatchsr))
return did_something;
State unified_pol = used_pol_set ? pol_set : pol_clr;
if (cell->type == "$dffsr")
if (cell->type == ID($dffsr))
{
if (hasreset)
{
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod));
cell->type = "$adff";
cell->setParam("\\ARST_POLARITY", unified_pol);
cell->setParam("\\ARST_VALUE", reset_val);
cell->setPort("\\ARST", sig_reset);
cell->type = ID($adff);
cell->setParam(ID(ARST_POLARITY), unified_pol);
cell->setParam(ID(ARST_VALUE), reset_val);
cell->setPort(ID(ARST), sig_reset);
cell->unsetParam("\\SET_POLARITY");
cell->unsetParam("\\CLR_POLARITY");
cell->unsetPort("\\SET");
cell->unsetPort("\\CLR");
cell->unsetParam(ID(SET_POLARITY));
cell->unsetParam(ID(CLR_POLARITY));
cell->unsetPort(ID(SET));
cell->unsetPort(ID(CLR));
}
else
{
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod));
cell->type = "$dff";
cell->unsetParam("\\SET_POLARITY");
cell->unsetParam("\\CLR_POLARITY");
cell->unsetPort("\\SET");
cell->unsetPort("\\CLR");
cell->type = ID($dff);
cell->unsetParam(ID(SET_POLARITY));
cell->unsetParam(ID(CLR_POLARITY));
cell->unsetPort(ID(SET));
cell->unsetPort(ID(CLR));
}
return true;
@ -198,9 +198,9 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
{
IdString new_type;
if (cell->type.substr(0,8) == "$_DFFSR_")
if (cell->type.begins_with("$_DFFSR_"))
new_type = stringf("$_DFF_%c_", cell->type[8]);
else if (cell->type.substr(0,11) == "$_DLATCHSR_")
else if (cell->type.begins_with("$_DLATCHSR_"))
new_type = stringf("$_DLATCH_%c_", cell->type[11]);
else
log_abort();
@ -208,8 +208,8 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod));
cell->type = new_type;
cell->unsetPort("\\S");
cell->unsetPort("\\R");
cell->unsetPort(ID(S));
cell->unsetPort(ID(R));
return true;
}
@ -222,18 +222,18 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
SigSpec sig_e;
State on_state, off_state;
if (dlatch->type == "$dlatch") {
sig_e = assign_map(dlatch->getPort("\\EN"));
on_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S1 : State::S0;
off_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S0 : State::S1;
if (dlatch->type == ID($dlatch)) {
sig_e = assign_map(dlatch->getPort(ID(EN)));
on_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S1 : State::S0;
off_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S0 : State::S1;
} else
if (dlatch->type == "$_DLATCH_P_") {
sig_e = assign_map(dlatch->getPort("\\E"));
if (dlatch->type == ID($_DLATCH_P_)) {
sig_e = assign_map(dlatch->getPort(ID(E)));
on_state = State::S1;
off_state = State::S0;
} else
if (dlatch->type == "$_DLATCH_N_") {
sig_e = assign_map(dlatch->getPort("\\E"));
if (dlatch->type == ID($_DLATCH_N_)) {
sig_e = assign_map(dlatch->getPort(ID(E)));
on_state = State::S0;
off_state = State::S1;
} else
@ -242,15 +242,15 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
if (sig_e == off_state)
{
RTLIL::Const val_init;
for (auto bit : dff_init_map(dlatch->getPort("\\Q")))
for (auto bit : dff_init_map(dlatch->getPort(ID(Q))))
val_init.bits.push_back(bit.wire == NULL ? bit.data : State::Sx);
mod->connect(dlatch->getPort("\\Q"), val_init);
mod->connect(dlatch->getPort(ID(Q)), val_init);
goto delete_dlatch;
}
if (sig_e == on_state)
{
mod->connect(dlatch->getPort("\\Q"), dlatch->getPort("\\D"));
mod->connect(dlatch->getPort(ID(Q)), dlatch->getPort(ID(D)));
goto delete_dlatch;
}
@ -258,7 +258,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
delete_dlatch:
log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod));
remove_init_attr(dlatch->getPort("\\Q"));
remove_init_attr(dlatch->getPort(ID(Q)));
mod->remove(dlatch);
return true;
}
@ -268,64 +268,64 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e;
RTLIL::Const val_cp, val_rp, val_rv, val_ep;
if (dff->type == "$_FF_") {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
if (dff->type == ID($_FF_)) {
sig_d = dff->getPort(ID(D));
sig_q = dff->getPort(ID(Q));
}
else if (dff->type == "$_DFF_N_" || dff->type == "$_DFF_P_") {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\C");
val_cp = RTLIL::Const(dff->type == "$_DFF_P_", 1);
else if (dff->type == ID($_DFF_N_) || dff->type == ID($_DFF_P_)) {
sig_d = dff->getPort(ID(D));
sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort(ID(C));
val_cp = RTLIL::Const(dff->type == ID($_DFF_P_), 1);
}
else if (dff->type.substr(0,6) == "$_DFF_" && dff->type.substr(9) == "_" &&
else if (dff->type.begins_with("$_DFF_") && dff->type.compare(9, 1, "_") == 0 &&
(dff->type[6] == 'N' || dff->type[6] == 'P') &&
(dff->type[7] == 'N' || dff->type[7] == 'P') &&
(dff->type[8] == '0' || dff->type[8] == '1')) {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\C");
sig_r = dff->getPort("\\R");
sig_d = dff->getPort(ID(D));
sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort(ID(C));
sig_r = dff->getPort(ID(R));
val_cp = RTLIL::Const(dff->type[6] == 'P', 1);
val_rp = RTLIL::Const(dff->type[7] == 'P', 1);
val_rv = RTLIL::Const(dff->type[8] == '1', 1);
}
else if (dff->type.substr(0,7) == "$_DFFE_" && dff->type.substr(9) == "_" &&
else if (dff->type.begins_with("$_DFFE_") && dff->type.compare(9, 1, "_") == 0 &&
(dff->type[7] == 'N' || dff->type[7] == 'P') &&
(dff->type[8] == 'N' || dff->type[8] == 'P')) {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\C");
sig_e = dff->getPort("\\E");
sig_d = dff->getPort(ID(D));
sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort(ID(C));
sig_e = dff->getPort(ID(E));
val_cp = RTLIL::Const(dff->type[7] == 'P', 1);
val_ep = RTLIL::Const(dff->type[8] == 'P', 1);
}
else if (dff->type == "$ff") {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
else if (dff->type == ID($ff)) {
sig_d = dff->getPort(ID(D));
sig_q = dff->getPort(ID(Q));
}
else if (dff->type == "$dff") {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\CLK");
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
else if (dff->type == ID($dff)) {
sig_d = dff->getPort(ID(D));
sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort(ID(CLK));
val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
}
else if (dff->type == "$dffe") {
sig_e = dff->getPort("\\EN");
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\CLK");
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1);
else if (dff->type == ID($dffe)) {
sig_e = dff->getPort(ID(EN));
sig_d = dff->getPort(ID(D));
sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort(ID(CLK));
val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
val_ep = RTLIL::Const(dff->parameters[ID(EN_POLARITY)].as_bool(), 1);
}
else if (dff->type == "$adff") {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\CLK");
sig_r = dff->getPort("\\ARST");
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
val_rp = RTLIL::Const(dff->parameters["\\ARST_POLARITY"].as_bool(), 1);
val_rv = dff->parameters["\\ARST_VALUE"];
else if (dff->type == ID($adff)) {
sig_d = dff->getPort(ID(D));
sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort(ID(CLK));
sig_r = dff->getPort(ID(ARST));
val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
val_rp = RTLIL::Const(dff->parameters[ID(ARST_POLARITY)].as_bool(), 1);
val_rv = dff->parameters[ID(ARST_VALUE)];
}
else
log_abort();
@ -343,12 +343,12 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
}
if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) {
if (dff->type.in(ID($ff), ID($dff)) && mux_drivers.has(sig_d)) {
std::set<RTLIL::Cell*> muxes;
mux_drivers.find(sig_d, muxes);
for (auto mux : muxes) {
RTLIL::SigSpec sig_a = assign_map(mux->getPort("\\A"));
RTLIL::SigSpec sig_b = assign_map(mux->getPort("\\B"));
RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID::A));
RTLIL::SigSpec sig_b = assign_map(mux->getPort(ID::B));
if (sig_a == sig_q && sig_b.is_fully_const() && (!has_init || val_init == sig_b.as_const())) {
mod->connect(sig_q, sig_b);
goto delete_dff;
@ -420,17 +420,17 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
log("Removing unused reset from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
if (dff->type == "$adff") {
dff->type = "$dff";
dff->unsetPort("\\ARST");
dff->unsetParam("\\ARST_POLARITY");
dff->unsetParam("\\ARST_VALUE");
if (dff->type == ID($adff)) {
dff->type = ID($dff);
dff->unsetPort(ID(ARST));
dff->unsetParam(ID(ARST_POLARITY));
dff->unsetParam(ID(ARST_VALUE));
return true;
}
log_assert(dff->type.substr(0,6) == "$_DFF_");
log_assert(dff->type.begins_with("$_DFF_"));
dff->type = stringf("$_DFF_%c_", + dff->type[6]);
dff->unsetPort("\\R");
dff->unsetPort(ID(R));
}
// If enable signal is present, and is fully constant
@ -445,16 +445,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
if (dff->type == "$dffe") {
dff->type = "$dff";
dff->unsetPort("\\EN");
dff->unsetParam("\\EN_POLARITY");
if (dff->type == ID($dffe)) {
dff->type = ID($dff);
dff->unsetPort(ID(EN));
dff->unsetParam(ID(EN_POLARITY));
return true;
}
log_assert(dff->type.substr(0,7) == "$_DFFE_");
log_assert(dff->type.begins_with("$_DFFE_"));
dff->type = stringf("$_DFF_%c_", + dff->type[7]);
dff->unsetPort("\\E");
dff->unsetPort(ID(E));
}
if (sat && has_init && (!sig_r.size() || val_init == val_rv))
@ -509,9 +509,9 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0,
position, log_id(dff), log_id(dff->type), log_id(mod));
SigSpec tmp = dff->getPort("\\D");
SigSpec tmp = dff->getPort(ID(D));
tmp[position] = sigbit_init_val;
dff->setPort("\\D", tmp);
dff->setPort(ID(D), tmp);
removed_sigbits = true;
}
@ -528,7 +528,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
delete_dff:
log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
remove_init_attr(dff->getPort("\\Q"));
remove_init_attr(dff->getPort(ID(Q)));
mod->remove(dff);
for (auto &entry : bit2driver)
@ -588,8 +588,8 @@ struct OptRmdffPass : public Pass {
for (auto wire : module->wires())
{
if (wire->attributes.count("\\init") != 0) {
Const initval = wire->attributes.at("\\init");
if (wire->attributes.count(ID(init)) != 0) {
Const initval = wire->attributes.at(ID(init));
for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++)
if (initval[i] == State::S0 || initval[i] == State::S1)
dff_init_map.add(SigBit(wire, i), initval[i]);
@ -624,29 +624,29 @@ struct OptRmdffPass : public Pass {
}
}
if (cell->type == "$mux" || cell->type == "$pmux") {
if (cell->getPort("\\A").size() == cell->getPort("\\B").size())
mux_drivers.insert(assign_map(cell->getPort("\\Y")), cell);
if (cell->type.in(ID($mux), ID($pmux))) {
if (cell->getPort(ID::A).size() == cell->getPort(ID::B).size())
mux_drivers.insert(assign_map(cell->getPort(ID::Y)), cell);
continue;
}
if (!design->selected(module, cell))
continue;
if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_",
"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_", "$dffsr",
"$_DLATCHSR_NNN_", "$_DLATCHSR_NNP_", "$_DLATCHSR_NPN_", "$_DLATCHSR_NPP_",
"$_DLATCHSR_PNN_", "$_DLATCHSR_PNP_", "$_DLATCHSR_PPN_", "$_DLATCHSR_PPP_", "$dlatchsr"))
if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), ID($dffsr),
ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), ID($dlatchsr)))
dffsr_list.push_back(cell->name);
if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_",
"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_",
"$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_",
"$ff", "$dff", "$dffe", "$adff"))
if (cell->type.in(ID($_FF_), ID($_DFF_N_), ID($_DFF_P_),
ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
ID($ff), ID($dff), ID($dffe), ID($adff)))
dff_list.push_back(cell->name);
if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_"))
if (cell->type.in(ID($dlatch), ID($_DLATCH_P_), ID($_DLATCH_N_)))
dlatch_list.push_back(cell->name);
}

649
passes/opt/opt_share.cc Normal file
View File

@ -0,0 +1,649 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* 2019 Bogdan Vukobratovic <bogdan.vukobratovic@gmail.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 "kernel/log.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/sigtools.h"
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
SigMap assign_map;
struct OpMuxConn {
RTLIL::SigSpec sig;
RTLIL::Cell *mux;
RTLIL::Cell *op;
int mux_port_id;
int mux_port_offset;
int op_outsig_offset;
bool operator<(const OpMuxConn &other) const
{
if (mux != other.mux)
return mux < other.mux;
if (mux_port_id != other.mux_port_id)
return mux_port_id < other.mux_port_id;
return mux_port_offset < other.mux_port_offset;
}
};
// Helper class to track additiona information about a SigSpec, like whether it is signed and the semantics of the port it is connected to
struct ExtSigSpec {
RTLIL::SigSpec sig;
RTLIL::SigSpec sign;
bool is_signed;
RTLIL::IdString semantics;
ExtSigSpec() {}
ExtSigSpec(RTLIL::SigSpec s, RTLIL::SigSpec sign = RTLIL::Const(0, 1), bool is_signed = false, RTLIL::IdString semantics = RTLIL::IdString()) : sig(s), sign(sign), is_signed(is_signed), semantics(semantics) {}
bool empty() const { return sig.empty(); }
bool operator<(const ExtSigSpec &other) const
{
if (sig != other.sig)
return sig < other.sig;
if (sign != other.sign)
return sign < other.sign;
if (is_signed != other.is_signed)
return is_signed < other.is_signed;
return semantics < other.semantics;
}
bool operator==(const RTLIL::SigSpec &other) const { return (sign != RTLIL::Const(0, 1)) ? false : sig == other; }
bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig && semantics == other.semantics; }
};
#define BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($and), ID($or), ID($xor), ID($xnor)
#define REDUCTION_OPS ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($reduce_nand)
#define LOGICAL_OPS ID($logic_and), ID($logic_or)
#define SHIFT_OPS ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)
#define RELATIONAL_OPS ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt)
bool cell_supported(RTLIL::Cell *cell)
{
if (cell->type.in(ID($alu))) {
RTLIL::SigSpec sig_bi = cell->getPort(ID(BI));
RTLIL::SigSpec sig_ci = cell->getPort(ID(CI));
if (sig_bi.is_fully_const() && sig_ci.is_fully_const() && sig_bi == sig_ci)
return true;
} else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($concat))) {
return true;
}
return false;
}
std::map<IdString, IdString> mergeable_type_map{
{ID($sub), ID($add)},
};
bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b)
{
auto a_type = a->type;
if (mergeable_type_map.count(a_type))
a_type = mergeable_type_map.at(a_type);
auto b_type = b->type;
if (mergeable_type_map.count(b_type))
b_type = mergeable_type_map.at(b_type);
return a_type == b_type;
}
RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_name)
{
if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt), ID($div), ID($mod), ID($concat), SHIFT_OPS) && port_name == ID::B)
return port_name;
return "";
}
RTLIL::SigSpec decode_port_sign(RTLIL::Cell *cell, RTLIL::IdString port_name) {
if (cell->type == ID($alu) && port_name == ID::B)
return cell->getPort(ID(BI));
else if (cell->type == ID($sub) && port_name == ID::B)
return RTLIL::Const(1, 1);
return RTLIL::Const(0, 1);
}
bool decode_port_signed(RTLIL::Cell *cell, RTLIL::IdString port_name)
{
if (cell->type.in(BITWISE_OPS, LOGICAL_OPS))
return false;
if (cell->hasParam(port_name.str() + "_SIGNED"))
return cell->getParam(port_name.str() + "_SIGNED").as_bool();
return false;
}
ExtSigSpec decode_port(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sigmap)
{
auto sig = (*sigmap)(cell->getPort(port_name));
RTLIL::SigSpec sign = decode_port_sign(cell, port_name);
RTLIL::IdString semantics = decode_port_semantics(cell, port_name);
bool is_signed = decode_port_signed(cell, port_name);
return ExtSigSpec(sig, sign, is_signed, semantics);
}
void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<OpMuxConn> &ports, const ExtSigSpec &operand)
{
std::vector<ExtSigSpec> muxed_operands;
int max_width = 0;
for (const auto& p : ports) {
auto op = p.op;
RTLIL::IdString muxed_port_name = ID::A;
if (decode_port(op, ID::A, &assign_map) == operand)
muxed_port_name = ID::B;
auto operand = decode_port(op, muxed_port_name, &assign_map);
if (operand.sig.size() > max_width)
max_width = operand.sig.size();
muxed_operands.push_back(operand);
}
auto shared_op = ports[0].op;
if (std::any_of(muxed_operands.begin(), muxed_operands.end(), [&](ExtSigSpec &op) { return op.sign != muxed_operands[0].sign; }))
max_width = std::max(max_width, shared_op->getParam(ID(Y_WIDTH)).as_int());
for (auto &operand : muxed_operands)
operand.sig.extend_u0(max_width, operand.is_signed);
for (const auto& p : ports) {
auto op = p.op;
if (op == shared_op)
continue;
module->remove(op);
}
for (auto &muxed_op : muxed_operands)
if (muxed_op.sign != muxed_operands[0].sign)
muxed_op = ExtSigSpec(module->Neg(NEW_ID, muxed_op.sig, muxed_op.is_signed));
RTLIL::SigSpec mux_y = mux->getPort(ID::Y);
RTLIL::SigSpec mux_a = mux->getPort(ID::A);
RTLIL::SigSpec mux_b = mux->getPort(ID::B);
RTLIL::SigSpec mux_s = mux->getPort(ID(S));
RTLIL::SigSpec shared_pmux_a = RTLIL::Const(RTLIL::State::Sx, max_width);
RTLIL::SigSpec shared_pmux_b;
RTLIL::SigSpec shared_pmux_s;
int conn_width = ports[0].sig.size();
int conn_offset = ports[0].mux_port_offset;
shared_op->setPort(ID::Y, shared_op->getPort(ID::Y).extract(0, conn_width));
if (mux->type == ID($pmux)) {
shared_pmux_s = RTLIL::SigSpec();
for (const auto &p : ports) {
shared_pmux_s.append(mux_s[p.mux_port_id]);
mux_b.replace(p.mux_port_id * mux_a.size() + conn_offset, shared_op->getPort(ID::Y));
}
} else {
shared_pmux_s = RTLIL::SigSpec{mux_s, module->Not(NEW_ID, mux_s)};
mux_a.replace(conn_offset, shared_op->getPort(ID::Y));
mux_b.replace(conn_offset, shared_op->getPort(ID::Y));
}
mux->setPort(ID::A, mux_a);
mux->setPort(ID::B, mux_b);
mux->setPort(ID::Y, mux_y);
mux->setPort(ID(S), mux_s);
for (const auto &op : muxed_operands)
shared_pmux_b.append(op.sig);
auto mux_to_oper = module->Pmux(NEW_ID, shared_pmux_a, shared_pmux_b, shared_pmux_s);
if (shared_op->type.in(ID($alu))) {
RTLIL::SigSpec alu_x = shared_op->getPort(ID(X));
RTLIL::SigSpec alu_co = shared_op->getPort(ID(CO));
shared_op->setPort(ID(X), alu_x.extract(0, conn_width));
shared_op->setPort(ID(CO), alu_co.extract(0, conn_width));
}
shared_op->setParam(ID(Y_WIDTH), conn_width);
if (decode_port(shared_op, ID::A, &assign_map) == operand) {
shared_op->setPort(ID::B, mux_to_oper);
shared_op->setParam(ID(B_WIDTH), max_width);
} else {
shared_op->setPort(ID::A, mux_to_oper);
shared_op->setParam(ID(A_WIDTH), max_width);
}
}
typedef struct {
RTLIL::Cell *mux;
std::vector<OpMuxConn> ports;
ExtSigSpec shared_operand;
} merged_op_t;
template <typename T> void remove_val(std::vector<T> &v, const std::vector<T> &vals)
{
auto val_iter = vals.rbegin();
for (auto i = v.rbegin(); i != v.rend(); ++i)
if ((val_iter != vals.rend()) && (*i == *val_iter)) {
v.erase(i.base() - 1);
++val_iter;
}
}
void check_muxed_operands(std::vector<const OpMuxConn *> &ports, const ExtSigSpec &shared_operand)
{
auto it = ports.begin();
ExtSigSpec seed;
while (it != ports.end()) {
auto p = *it;
auto op = p->op;
RTLIL::IdString muxed_port_name = ID::A;
if (decode_port(op, ID::A, &assign_map) == shared_operand) {
muxed_port_name = ID::B;
}
auto operand = decode_port(op, muxed_port_name, &assign_map);
if (seed.empty())
seed = operand;
if (operand.is_signed != seed.is_signed) {
ports.erase(it);
} else {
++it;
}
}
}
ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vector<const OpMuxConn *> &ports, const std::map<ExtSigSpec, std::set<RTLIL::Cell *>> &operand_to_users)
{
std::set<RTLIL::Cell *> ops_using_operand;
std::set<RTLIL::Cell *> ops_set;
for(const auto& p: ports)
ops_set.insert(p->op);
ExtSigSpec oper;
auto op_a = seed->op;
for (RTLIL::IdString port_name : {ID::A, ID::B}) {
oper = decode_port(op_a, port_name, &assign_map);
auto operand_users = operand_to_users.at(oper);
if (operand_users.size() == 1)
continue;
ops_using_operand.clear();
for (auto mux_ops: ops_set)
if (operand_users.count(mux_ops))
ops_using_operand.insert(mux_ops);
if (ops_using_operand.size() > 1) {
ports.erase(std::remove_if(ports.begin(), ports.end(), [&](const OpMuxConn *p) { return !ops_using_operand.count(p->op); }),
ports.end());
return oper;
}
}
return ExtSigSpec();
}
dict<RTLIL::SigSpec, OpMuxConn> find_valid_op_mux_conns(RTLIL::Module *module, dict<RTLIL::SigBit, RTLIL::SigSpec> &op_outbit_to_outsig,
dict<RTLIL::SigSpec, RTLIL::Cell *> outsig_to_operator,
dict<RTLIL::SigBit, RTLIL::SigSpec> &op_aux_to_outsig)
{
dict<RTLIL::SigSpec, int> op_outsig_user_track;
dict<RTLIL::SigSpec, OpMuxConn> op_mux_conn_map;
std::function<void(RTLIL::SigSpec)> remove_outsig = [&](RTLIL::SigSpec outsig) {
for (auto op_outbit : outsig)
op_outbit_to_outsig.erase(op_outbit);
if (op_mux_conn_map.count(outsig))
op_mux_conn_map.erase(outsig);
};
std::function<void(RTLIL::SigBit)> remove_outsig_from_aux_bit = [&](RTLIL::SigBit auxbit) {
auto aux_outsig = op_aux_to_outsig.at(auxbit);
auto op = outsig_to_operator.at(aux_outsig);
auto op_outsig = assign_map(op->getPort(ID::Y));
remove_outsig(op_outsig);
for (auto aux_outbit : aux_outsig)
op_aux_to_outsig.erase(aux_outbit);
};
std::function<void(RTLIL::Cell *)> find_op_mux_conns = [&](RTLIL::Cell *mux) {
RTLIL::SigSpec sig;
int mux_port_size;
if (mux->type.in(ID($mux), ID($_MUX_))) {
mux_port_size = mux->getPort(ID::A).size();
sig = RTLIL::SigSpec{mux->getPort(ID::B), mux->getPort(ID::A)};
} else {
mux_port_size = mux->getPort(ID::A).size();
sig = mux->getPort(ID::B);
}
auto mux_insig = assign_map(sig);
for (int i = 0; i < mux_insig.size(); ++i) {
if (op_aux_to_outsig.count(mux_insig[i])) {
remove_outsig_from_aux_bit(mux_insig[i]);
continue;
}
if (!op_outbit_to_outsig.count(mux_insig[i]))
continue;
auto op_outsig = op_outbit_to_outsig.at(mux_insig[i]);
if (op_mux_conn_map.count(op_outsig)) {
remove_outsig(op_outsig);
continue;
}
int mux_port_id = i / mux_port_size;
int mux_port_offset = i % mux_port_size;
int op_outsig_offset;
for (op_outsig_offset = 0; op_outsig[op_outsig_offset] != mux_insig[i]; ++op_outsig_offset)
;
int j = op_outsig_offset;
do {
if (!op_outbit_to_outsig.count(mux_insig[i]))
break;
if (op_outbit_to_outsig.at(mux_insig[i]) != op_outsig)
break;
++i;
++j;
} while ((i / mux_port_size == mux_port_id) && (j < op_outsig.size()));
int op_conn_width = j - op_outsig_offset;
OpMuxConn inp = {
op_outsig.extract(op_outsig_offset, op_conn_width),
mux,
outsig_to_operator.at(op_outsig),
mux_port_id,
mux_port_offset,
op_outsig_offset,
};
op_mux_conn_map[op_outsig] = inp;
--i;
}
};
std::function<void(RTLIL::SigSpec)> remove_connected_ops = [&](RTLIL::SigSpec sig) {
auto mux_insig = assign_map(sig);
for (auto outbit : mux_insig) {
if (op_aux_to_outsig.count(outbit)) {
remove_outsig_from_aux_bit(outbit);
continue;
}
if (!op_outbit_to_outsig.count(outbit))
continue;
remove_outsig(op_outbit_to_outsig.at(outbit));
}
};
for (auto cell : module->cells()) {
if (cell->type.in(ID($mux), ID($_MUX_), ID($pmux))) {
remove_connected_ops(cell->getPort(ID(S)));
find_op_mux_conns(cell);
} else {
for (auto &conn : cell->connections())
if (cell->input(conn.first))
remove_connected_ops(conn.second);
}
}
for (auto w : module->wires()) {
if (!w->port_output)
continue;
remove_connected_ops(w);
}
return op_mux_conn_map;
}
struct OptSharePass : public Pass {
OptSharePass() : Pass("opt_share", "merge mutually exclusive cells of the same type that share an input signal") {}
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" opt_share [selection]\n");
log("\n");
log("This pass identifies mutually exclusive cells of the same type that:\n");
log(" (a) share an input signal,\n");
log(" (b) drive the same $mux, $_MUX_, or $pmux multiplexing cell,\n");
log("\n");
log("allowing the cell to be merged and the multiplexer to be moved from\n");
log("multiplexing its output to multiplexing the non-shared input signals.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing OPT_SHARE pass.\n");
extra_args(args, 1, design);
for (auto module : design->selected_modules()) {
assign_map.clear();
assign_map.set(module);
std::map<ExtSigSpec, std::set<RTLIL::Cell *>> operand_to_users;
dict<RTLIL::SigSpec, RTLIL::Cell *> outsig_to_operator;
dict<RTLIL::SigBit, RTLIL::SigSpec> op_outbit_to_outsig;
dict<RTLIL::SigBit, RTLIL::SigSpec> op_aux_to_outsig;
bool any_shared_operands = false;
std::vector<ExtSigSpec> op_insigs;
for (auto cell : module->cells()) {
if (!cell_supported(cell))
continue;
if (cell->type == ID($alu)) {
for (RTLIL::IdString port_name : {ID(X), ID(CO)}) {
auto mux_insig = assign_map(cell->getPort(port_name));
outsig_to_operator[mux_insig] = cell;
for (auto outbit : mux_insig)
op_aux_to_outsig[outbit] = mux_insig;
}
}
auto mux_insig = assign_map(cell->getPort(ID::Y));
outsig_to_operator[mux_insig] = cell;
for (auto outbit : mux_insig)
op_outbit_to_outsig[outbit] = mux_insig;
for (RTLIL::IdString port_name : {ID::A, ID::B}) {
auto op_insig = decode_port(cell, port_name, &assign_map);
op_insigs.push_back(op_insig);
operand_to_users[op_insig].insert(cell);
if (operand_to_users[op_insig].size() > 1)
any_shared_operands = true;
}
}
if (!any_shared_operands)
continue;
// Operator outputs need to be exclusively connected to the $mux inputs in order to be mergeable. Hence we count to
// how many points are operator output bits connected.
dict<RTLIL::SigSpec, OpMuxConn> op_mux_conn_map =
find_valid_op_mux_conns(module, op_outbit_to_outsig, outsig_to_operator, op_aux_to_outsig);
// Group op connections connected to same ports of the same $mux. Sort them in ascending order of their port offset
dict<RTLIL::Cell*, std::vector<std::set<OpMuxConn>>> mux_port_op_conns;
for (auto& val: op_mux_conn_map) {
OpMuxConn p = val.second;
auto& mux_port_conns = mux_port_op_conns[p.mux];
if (mux_port_conns.size() == 0) {
int mux_port_num;
if (p.mux->type.in(ID($mux), ID($_MUX_)))
mux_port_num = 2;
else
mux_port_num = p.mux->getPort(ID(S)).size();
mux_port_conns.resize(mux_port_num);
}
mux_port_conns[p.mux_port_id].insert(p);
}
std::vector<merged_op_t> merged_ops;
for (auto& val: mux_port_op_conns) {
RTLIL::Cell* cell = val.first;
auto &mux_port_conns = val.second;
const OpMuxConn *seed = NULL;
// Look through the bits of the $mux inputs and see which of them are connected to the operator
// results. Operator results can be concatenated with other signals before led to the $mux.
while (true) {
// Remove either the merged ports from the last iteration or the seed that failed to yield a merger
if (seed != NULL) {
mux_port_conns[seed->mux_port_id].erase(*seed);
seed = NULL;
}
// For a new merger, find the seed op connection that starts at lowest port offset among port connections
for (auto &port_conns : mux_port_conns) {
if (!port_conns.size())
continue;
const OpMuxConn *next_p = &(*port_conns.begin());
if ((seed == NULL) || (seed->mux_port_offset > next_p->mux_port_offset))
seed = next_p;
}
// Cannot find the seed -> nothing to do for this $mux anymore
if (seed == NULL)
break;
// Find all other op connections that start from the same port offset, and whose ops can be merged with the seed op
std::vector<const OpMuxConn *> mergeable_conns;
for (auto &port_conns : mux_port_conns) {
if (!port_conns.size())
continue;
const OpMuxConn *next_p = &(*port_conns.begin());
if ((next_p->op_outsig_offset == seed->op_outsig_offset) &&
(next_p->mux_port_offset == seed->mux_port_offset) && mergeable(next_p->op, seed->op) &&
next_p->sig.size() == seed->sig.size())
mergeable_conns.push_back(next_p);
}
// We need at least two mergeable connections for the merger
if (mergeable_conns.size() < 2)
continue;
// Filter mergeable connections whose ops share an operand with seed connection's op
auto shared_operand = find_shared_operand(seed, mergeable_conns, operand_to_users);
if (shared_operand.empty())
continue;
check_muxed_operands(mergeable_conns, shared_operand);
if (mergeable_conns.size() < 2)
continue;
// Remember the combination for the merger
std::vector<OpMuxConn> merged_ports;
for (auto p : mergeable_conns) {
merged_ports.push_back(*p);
mux_port_conns[p->mux_port_id].erase(*p);
}
seed = NULL;
merged_ops.push_back(merged_op_t{cell, merged_ports, shared_operand});
design->scratchpad_set_bool("opt.did_something", true);
}
}
for (auto &shared : merged_ops) {
log(" Found cells that share an operand and can be merged by moving the %s %s in front "
"of "
"them:\n",
log_id(shared.mux->type), log_id(shared.mux));
for (const auto& op : shared.ports)
log(" %s\n", log_id(op.op));
log("\n");
merge_operators(module, shared.mux, shared.ports, shared.shared_operand);
}
}
}
} OptSharePass;
PRIVATE_NAMESPACE_END

View File

@ -46,7 +46,7 @@ struct OnehotDatabase
for (auto wire : module->wires())
{
auto it = wire->attributes.find("\\init");
auto it = wire->attributes.find(ID(init));
if (it == wire->attributes.end())
continue;
@ -63,19 +63,19 @@ struct OnehotDatabase
vector<SigSpec> inputs;
SigSpec output;
if (cell->type.in("$adff", "$dff", "$dffe", "$dlatch", "$ff"))
if (cell->type.in(ID($adff), ID($dff), ID($dffe), ID($dlatch), ID($ff)))
{
output = cell->getPort("\\Q");
if (cell->type == "$adff")
inputs.push_back(cell->getParam("\\ARST_VALUE"));
inputs.push_back(cell->getPort("\\D"));
output = cell->getPort(ID(Q));
if (cell->type == ID($adff))
inputs.push_back(cell->getParam(ID(ARST_VALUE)));
inputs.push_back(cell->getPort(ID(D)));
}
if (cell->type.in("$mux", "$pmux"))
if (cell->type.in(ID($mux), ID($pmux)))
{
output = cell->getPort("\\Y");
inputs.push_back(cell->getPort("\\A"));
SigSpec B = cell->getPort("\\B");
output = cell->getPort(ID::Y);
inputs.push_back(cell->getPort(ID::A));
SigSpec B = cell->getPort(ID::B);
for (int i = 0; i < GetSize(B); i += GetSize(output))
inputs.push_back(B.extract(i, GetSize(output)));
}
@ -292,23 +292,23 @@ struct Pmux2ShiftxPass : public Pass {
for (auto cell : module->cells())
{
if (cell->type == "$eq")
if (cell->type == ID($eq))
{
dict<SigBit, State> bits;
SigSpec A = sigmap(cell->getPort("\\A"));
SigSpec B = sigmap(cell->getPort("\\B"));
SigSpec A = sigmap(cell->getPort(ID::A));
SigSpec B = sigmap(cell->getPort(ID::B));
int a_width = cell->getParam("\\A_WIDTH").as_int();
int b_width = cell->getParam("\\B_WIDTH").as_int();
int a_width = cell->getParam(ID(A_WIDTH)).as_int();
int b_width = cell->getParam(ID(B_WIDTH)).as_int();
if (a_width < b_width) {
bool a_signed = cell->getParam("\\A_SIGNED").as_int();
bool a_signed = cell->getParam(ID(A_SIGNED)).as_int();
A.extend_u0(b_width, a_signed);
}
if (b_width < a_width) {
bool b_signed = cell->getParam("\\B_SIGNED").as_int();
bool b_signed = cell->getParam(ID(B_SIGNED)).as_int();
B.extend_u0(a_width, b_signed);
}
@ -335,15 +335,15 @@ struct Pmux2ShiftxPass : public Pass {
entry.second.bits.push_back(it.second);
}
eqdb[sigmap(cell->getPort("\\Y")[0])] = entry;
eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry;
goto next_cell;
}
if (cell->type == "$logic_not")
if (cell->type == ID($logic_not))
{
dict<SigBit, State> bits;
SigSpec A = sigmap(cell->getPort("\\A"));
SigSpec A = sigmap(cell->getPort(ID::A));
for (int i = 0; i < GetSize(A); i++)
bits[A[i]] = State::S0;
@ -356,7 +356,7 @@ struct Pmux2ShiftxPass : public Pass {
entry.second.bits.push_back(it.second);
}
eqdb[sigmap(cell->getPort("\\Y")[0])] = entry;
eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry;
goto next_cell;
}
next_cell:;
@ -364,11 +364,11 @@ struct Pmux2ShiftxPass : public Pass {
for (auto cell : module->selected_cells())
{
if (cell->type != "$pmux")
if (cell->type != ID($pmux))
continue;
string src = cell->get_src_attribute();
int width = cell->getParam("\\WIDTH").as_int();
int width = cell->getParam(ID(WIDTH)).as_int();
int width_bits = ceil_log2(width);
int extwidth = width;
@ -377,9 +377,9 @@ struct Pmux2ShiftxPass : public Pass {
dict<SigSpec, pool<int>> seldb;
SigSpec A = cell->getPort("\\A");
SigSpec B = cell->getPort("\\B");
SigSpec S = sigmap(cell->getPort("\\S"));
SigSpec A = cell->getPort(ID::A);
SigSpec B = cell->getPort(ID::B);
SigSpec S = sigmap(cell->getPort(ID(S)));
for (int i = 0; i < GetSize(S); i++)
{
if (!eqdb.count(S[i]))
@ -400,8 +400,8 @@ struct Pmux2ShiftxPass : public Pass {
log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits);
}
SigSpec updated_S = cell->getPort("\\S");
SigSpec updated_B = cell->getPort("\\B");
SigSpec updated_S = cell->getPort(ID(S));
SigSpec updated_B = cell->getPort(ID::B);
while (!seldb.empty())
{
@ -727,9 +727,9 @@ struct Pmux2ShiftxPass : public Pass {
}
// update $pmux cell
cell->setPort("\\S", updated_S);
cell->setPort("\\B", updated_B);
cell->setParam("\\S_WIDTH", GetSize(updated_S));
cell->setPort(ID(S), updated_S);
cell->setPort(ID::B, updated_B);
cell->setParam(ID(S_WIDTH), GetSize(updated_S));
}
}
}
@ -779,22 +779,22 @@ struct OnehotPass : public Pass {
for (auto cell : module->selected_cells())
{
if (cell->type != "$eq")
if (cell->type != ID($eq))
continue;
SigSpec A = sigmap(cell->getPort("\\A"));
SigSpec B = sigmap(cell->getPort("\\B"));
SigSpec A = sigmap(cell->getPort(ID::A));
SigSpec B = sigmap(cell->getPort(ID::B));
int a_width = cell->getParam("\\A_WIDTH").as_int();
int b_width = cell->getParam("\\B_WIDTH").as_int();
int a_width = cell->getParam(ID(A_WIDTH)).as_int();
int b_width = cell->getParam(ID(B_WIDTH)).as_int();
if (a_width < b_width) {
bool a_signed = cell->getParam("\\A_SIGNED").as_int();
bool a_signed = cell->getParam(ID(A_SIGNED)).as_int();
A.extend_u0(b_width, a_signed);
}
if (b_width < a_width) {
bool b_signed = cell->getParam("\\B_SIGNED").as_int();
bool b_signed = cell->getParam(ID(B_SIGNED)).as_int();
B.extend_u0(a_width, b_signed);
}
@ -830,7 +830,7 @@ struct OnehotPass : public Pass {
continue;
}
SigSpec Y = cell->getPort("\\Y");
SigSpec Y = cell->getPort(ID::Y);
if (not_onehot)
{

View File

@ -171,7 +171,7 @@ struct RmportsPassPass : public Pass {
wire->port_output = false;
wire->port_id = 0;
}
log("Removed %zu unused ports.\n", unused_ports.size());
log("Removed %d unused ports.\n", GetSize(unused_ports));
// Re-number all of the wires that DO have ports still on them
for(size_t i=0; i<module->ports.size(); i++)

View File

@ -89,8 +89,8 @@ struct ShareWorker
queue_bits.clear();
for (auto &pbit : portbits) {
if (pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") {
pool<RTLIL::SigBit> bits = modwalker.sigmap(pbit.cell->getPort("\\S")).to_sigbit_pool();
if (pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) {
pool<RTLIL::SigBit> bits = modwalker.sigmap(pbit.cell->getPort(ID(S))).to_sigbit_pool();
terminal_bits.insert(bits.begin(), bits.end());
queue_bits.insert(bits.begin(), bits.end());
visited_cells.insert(pbit.cell);
@ -128,7 +128,7 @@ struct ShareWorker
static int bits_macc(RTLIL::Cell *c)
{
Macc m(c);
int width = GetSize(c->getPort("\\Y"));
int width = GetSize(c->getPort(ID::Y));
return bits_macc(m, width);
}
@ -242,7 +242,7 @@ struct ShareWorker
{
Macc m1(c1), m2(c2), supermacc;
int w1 = GetSize(c1->getPort("\\Y")), w2 = GetSize(c2->getPort("\\Y"));
int w1 = GetSize(c1->getPort(ID::Y)), w2 = GetSize(c2->getPort(ID::Y));
int width = max(w1, w2);
m1.optimize(w1);
@ -328,11 +328,11 @@ struct ShareWorker
{
RTLIL::SigSpec sig_y = module->addWire(NEW_ID, width);
supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort("\\Y")));
supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort("\\Y")));
supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort(ID::Y)));
supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID::Y)));
supercell->setParam("\\Y_WIDTH", width);
supercell->setPort("\\Y", sig_y);
supercell->setParam(ID(Y_WIDTH), width);
supercell->setPort(ID::Y, sig_y);
supermacc.optimize(width);
supermacc.to_cell(supercell);
@ -368,22 +368,22 @@ struct ShareWorker
continue;
}
if (cell->type == "$memrd") {
if (cell->parameters.at("\\CLK_ENABLE").as_bool())
if (cell->type == ID($memrd)) {
if (cell->parameters.at(ID(CLK_ENABLE)).as_bool())
continue;
if (config.opt_aggressive || !modwalker.sigmap(cell->getPort("\\ADDR")).is_fully_const())
if (config.opt_aggressive || !modwalker.sigmap(cell->getPort(ID(ADDR))).is_fully_const())
shareable_cells.insert(cell);
continue;
}
if (cell->type == "$mul" || cell->type == "$div" || cell->type == "$mod") {
if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 4)
if (cell->type.in(ID($mul), ID($div), ID($mod))) {
if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 4)
shareable_cells.insert(cell);
continue;
}
if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr") {
if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 8)
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 8)
shareable_cells.insert(cell);
continue;
}
@ -401,9 +401,9 @@ struct ShareWorker
if (c1->type != c2->type)
return false;
if (c1->type == "$memrd")
if (c1->type == ID($memrd))
{
if (c1->parameters.at("\\MEMID").decode_string() != c2->parameters.at("\\MEMID").decode_string())
if (c1->parameters.at(ID(MEMID)).decode_string() != c2->parameters.at(ID(MEMID)).decode_string())
return false;
return true;
@ -413,11 +413,11 @@ struct ShareWorker
{
if (!config.opt_aggressive)
{
int a1_width = c1->parameters.at("\\A_WIDTH").as_int();
int y1_width = c1->parameters.at("\\Y_WIDTH").as_int();
int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
int a2_width = c2->parameters.at("\\A_WIDTH").as_int();
int y2_width = c2->parameters.at("\\Y_WIDTH").as_int();
int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false;
if (max(y1_width, y2_width) > 2 * min(y1_width, y2_width)) return false;
@ -426,17 +426,17 @@ struct ShareWorker
return true;
}
if (config.generic_bin_ops.count(c1->type) || c1->type == "$alu")
if (config.generic_bin_ops.count(c1->type) || c1->type == ID($alu))
{
if (!config.opt_aggressive)
{
int a1_width = c1->parameters.at("\\A_WIDTH").as_int();
int b1_width = c1->parameters.at("\\B_WIDTH").as_int();
int y1_width = c1->parameters.at("\\Y_WIDTH").as_int();
int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int();
int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
int a2_width = c2->parameters.at("\\A_WIDTH").as_int();
int b2_width = c2->parameters.at("\\B_WIDTH").as_int();
int y2_width = c2->parameters.at("\\Y_WIDTH").as_int();
int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int();
int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false;
if (max(b1_width, b2_width) > 2 * min(b1_width, b2_width)) return false;
@ -450,13 +450,13 @@ struct ShareWorker
{
if (!config.opt_aggressive)
{
int a1_width = c1->parameters.at("\\A_WIDTH").as_int();
int b1_width = c1->parameters.at("\\B_WIDTH").as_int();
int y1_width = c1->parameters.at("\\Y_WIDTH").as_int();
int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int();
int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
int a2_width = c2->parameters.at("\\A_WIDTH").as_int();
int b2_width = c2->parameters.at("\\B_WIDTH").as_int();
int y2_width = c2->parameters.at("\\Y_WIDTH").as_int();
int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int();
int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
int min1_width = min(a1_width, b1_width);
int max1_width = max(a1_width, b1_width);
@ -472,7 +472,7 @@ struct ShareWorker
return true;
}
if (c1->type == "$macc")
if (c1->type == ID($macc))
{
if (!config.opt_aggressive)
if (share_macc(c1, c2) > 2 * min(bits_macc(c1), bits_macc(c2))) return false;
@ -510,27 +510,27 @@ struct ShareWorker
if (config.generic_uni_ops.count(c1->type))
{
if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\A_SIGNED").as_bool())
if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool())
{
RTLIL::Cell *unsigned_cell = c1->parameters.at("\\A_SIGNED").as_bool() ? c2 : c1;
if (unsigned_cell->getPort("\\A").to_sigbit_vector().back() != RTLIL::State::S0) {
unsigned_cell->parameters.at("\\A_WIDTH") = unsigned_cell->parameters.at("\\A_WIDTH").as_int() + 1;
RTLIL::SigSpec new_a = unsigned_cell->getPort("\\A");
RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
if (unsigned_cell->getPort(ID::A).to_sigbit_vector().back() != RTLIL::State::S0) {
unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
RTLIL::SigSpec new_a = unsigned_cell->getPort(ID::A);
new_a.append_bit(RTLIL::State::S0);
unsigned_cell->setPort("\\A", new_a);
unsigned_cell->setPort(ID::A, new_a);
}
unsigned_cell->parameters.at("\\A_SIGNED") = true;
unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
unsigned_cell->check();
}
bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool();
log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool());
bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
RTLIL::SigSpec a1 = c1->getPort("\\A");
RTLIL::SigSpec y1 = c1->getPort("\\Y");
RTLIL::SigSpec a1 = c1->getPort(ID::A);
RTLIL::SigSpec y1 = c1->getPort(ID::Y);
RTLIL::SigSpec a2 = c2->getPort("\\A");
RTLIL::SigSpec y2 = c2->getPort("\\Y");
RTLIL::SigSpec a2 = c2->getPort(ID::A);
RTLIL::SigSpec y2 = c2->getPort(ID::Y);
int a_width = max(a1.size(), a2.size());
int y_width = max(y1.size(), y2.size());
@ -544,11 +544,11 @@ struct ShareWorker
RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
supercell->parameters["\\A_SIGNED"] = a_signed;
supercell->parameters["\\A_WIDTH"] = a_width;
supercell->parameters["\\Y_WIDTH"] = y_width;
supercell->setPort("\\A", a);
supercell->setPort("\\Y", y);
supercell->parameters[ID(A_SIGNED)] = a_signed;
supercell->parameters[ID(A_WIDTH)] = a_width;
supercell->parameters[ID(Y_WIDTH)] = y_width;
supercell->setPort(ID::A, a);
supercell->setPort(ID::Y, y);
supercell_aux.insert(module->addPos(NEW_ID, y, y1));
supercell_aux.insert(module->addPos(NEW_ID, y, y2));
@ -557,54 +557,54 @@ struct ShareWorker
return supercell;
}
if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == "$alu")
if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == ID($alu))
{
bool modified_src_cells = false;
if (config.generic_cbin_ops.count(c1->type))
{
int score_unflipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int()) +
max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int());
int score_unflipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int()) +
max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int());
int score_flipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int()) +
max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int());
int score_flipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int()) +
max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int());
if (score_flipped < score_unflipped)
{
RTLIL::SigSpec tmp = c2->getPort("\\A");
c2->setPort("\\A", c2->getPort("\\B"));
c2->setPort("\\B", tmp);
RTLIL::SigSpec tmp = c2->getPort(ID::A);
c2->setPort(ID::A, c2->getPort(ID::B));
c2->setPort(ID::B, tmp);
std::swap(c2->parameters.at("\\A_WIDTH"), c2->parameters.at("\\B_WIDTH"));
std::swap(c2->parameters.at("\\A_SIGNED"), c2->parameters.at("\\B_SIGNED"));
std::swap(c2->parameters.at(ID(A_WIDTH)), c2->parameters.at(ID(B_WIDTH)));
std::swap(c2->parameters.at(ID(A_SIGNED)), c2->parameters.at(ID(B_SIGNED)));
modified_src_cells = true;
}
}
if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\A_SIGNED").as_bool())
if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool())
{
RTLIL::Cell *unsigned_cell = c1->parameters.at("\\A_SIGNED").as_bool() ? c2 : c1;
if (unsigned_cell->getPort("\\A").to_sigbit_vector().back() != RTLIL::State::S0) {
unsigned_cell->parameters.at("\\A_WIDTH") = unsigned_cell->parameters.at("\\A_WIDTH").as_int() + 1;
RTLIL::SigSpec new_a = unsigned_cell->getPort("\\A");
RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
if (unsigned_cell->getPort(ID::A).to_sigbit_vector().back() != RTLIL::State::S0) {
unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
RTLIL::SigSpec new_a = unsigned_cell->getPort(ID::A);
new_a.append_bit(RTLIL::State::S0);
unsigned_cell->setPort("\\A", new_a);
unsigned_cell->setPort(ID::A, new_a);
}
unsigned_cell->parameters.at("\\A_SIGNED") = true;
unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
modified_src_cells = true;
}
if (c1->parameters.at("\\B_SIGNED").as_bool() != c2->parameters.at("\\B_SIGNED").as_bool())
if (c1->parameters.at(ID(B_SIGNED)).as_bool() != c2->parameters.at(ID(B_SIGNED)).as_bool())
{
RTLIL::Cell *unsigned_cell = c1->parameters.at("\\B_SIGNED").as_bool() ? c2 : c1;
if (unsigned_cell->getPort("\\B").to_sigbit_vector().back() != RTLIL::State::S0) {
unsigned_cell->parameters.at("\\B_WIDTH") = unsigned_cell->parameters.at("\\B_WIDTH").as_int() + 1;
RTLIL::SigSpec new_b = unsigned_cell->getPort("\\B");
RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(B_SIGNED)).as_bool() ? c2 : c1;
if (unsigned_cell->getPort(ID::B).to_sigbit_vector().back() != RTLIL::State::S0) {
unsigned_cell->parameters.at(ID(B_WIDTH)) = unsigned_cell->parameters.at(ID(B_WIDTH)).as_int() + 1;
RTLIL::SigSpec new_b = unsigned_cell->getPort(ID::B);
new_b.append_bit(RTLIL::State::S0);
unsigned_cell->setPort("\\B", new_b);
unsigned_cell->setPort(ID::B, new_b);
}
unsigned_cell->parameters.at("\\B_SIGNED") = true;
unsigned_cell->parameters.at(ID(B_SIGNED)) = true;
modified_src_cells = true;
}
@ -613,28 +613,28 @@ struct ShareWorker
c2->check();
}
bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool();
bool b_signed = c1->parameters.at("\\B_SIGNED").as_bool();
bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
bool b_signed = c1->parameters.at(ID(B_SIGNED)).as_bool();
log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool());
log_assert(b_signed == c2->parameters.at("\\B_SIGNED").as_bool());
log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
log_assert(b_signed == c2->parameters.at(ID(B_SIGNED)).as_bool());
if (c1->type == "$shl" || c1->type == "$shr" || c1->type == "$sshl" || c1->type == "$sshr")
if (c1->type == ID($shl) || c1->type == ID($shr) || c1->type == ID($sshl) || c1->type == ID($sshr))
b_signed = false;
RTLIL::SigSpec a1 = c1->getPort("\\A");
RTLIL::SigSpec b1 = c1->getPort("\\B");
RTLIL::SigSpec y1 = c1->getPort("\\Y");
RTLIL::SigSpec a1 = c1->getPort(ID::A);
RTLIL::SigSpec b1 = c1->getPort(ID::B);
RTLIL::SigSpec y1 = c1->getPort(ID::Y);
RTLIL::SigSpec a2 = c2->getPort("\\A");
RTLIL::SigSpec b2 = c2->getPort("\\B");
RTLIL::SigSpec y2 = c2->getPort("\\Y");
RTLIL::SigSpec a2 = c2->getPort(ID::A);
RTLIL::SigSpec b2 = c2->getPort(ID::B);
RTLIL::SigSpec y2 = c2->getPort(ID::Y);
int a_width = max(a1.size(), a2.size());
int b_width = max(b1.size(), b2.size());
int y_width = max(y1.size(), y2.size());
if (c1->type == "$shr" && a_signed)
if (c1->type == ID($shr) && a_signed)
{
a_width = max(y_width, a_width);
@ -660,43 +660,43 @@ struct ShareWorker
supercell_aux.insert(module->addMux(NEW_ID, b2, b1, act, b));
RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
RTLIL::Wire *x = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr;
RTLIL::Wire *co = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr;
RTLIL::Wire *x = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr;
RTLIL::Wire *co = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr;
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
supercell->parameters["\\A_SIGNED"] = a_signed;
supercell->parameters["\\B_SIGNED"] = b_signed;
supercell->parameters["\\A_WIDTH"] = a_width;
supercell->parameters["\\B_WIDTH"] = b_width;
supercell->parameters["\\Y_WIDTH"] = y_width;
supercell->setPort("\\A", a);
supercell->setPort("\\B", b);
supercell->setPort("\\Y", y);
if (c1->type == "$alu") {
supercell->parameters[ID(A_SIGNED)] = a_signed;
supercell->parameters[ID(B_SIGNED)] = b_signed;
supercell->parameters[ID(A_WIDTH)] = a_width;
supercell->parameters[ID(B_WIDTH)] = b_width;
supercell->parameters[ID(Y_WIDTH)] = y_width;
supercell->setPort(ID::A, a);
supercell->setPort(ID::B, b);
supercell->setPort(ID::Y, y);
if (c1->type == ID($alu)) {
RTLIL::Wire *ci = module->addWire(NEW_ID), *bi = module->addWire(NEW_ID);
supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\CI"), c1->getPort("\\CI"), act, ci));
supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\BI"), c1->getPort("\\BI"), act, bi));
supercell->setPort("\\CI", ci);
supercell->setPort("\\BI", bi);
supercell->setPort("\\CO", co);
supercell->setPort("\\X", x);
supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(CI)), c1->getPort(ID(CI)), act, ci));
supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(BI)), c1->getPort(ID(BI)), act, bi));
supercell->setPort(ID(CI), ci);
supercell->setPort(ID(BI), bi);
supercell->setPort(ID(CO), co);
supercell->setPort(ID(X), x);
}
supercell->check();
supercell_aux.insert(module->addPos(NEW_ID, y, y1));
supercell_aux.insert(module->addPos(NEW_ID, y, y2));
if (c1->type == "$alu") {
supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort("\\CO")));
supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort("\\CO")));
supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort("\\X")));
supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort("\\X")));
if (c1->type == ID($alu)) {
supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort(ID(CO))));
supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort(ID(CO))));
supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort(ID(X))));
supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort(ID(X))));
}
supercell_aux.insert(supercell);
return supercell;
}
if (c1->type == "$macc")
if (c1->type == ID($macc))
{
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
supercell_aux.insert(supercell);
@ -705,18 +705,18 @@ struct ShareWorker
return supercell;
}
if (c1->type == "$memrd")
if (c1->type == ID($memrd))
{
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1);
RTLIL::SigSpec addr1 = c1->getPort("\\ADDR");
RTLIL::SigSpec addr2 = c2->getPort("\\ADDR");
RTLIL::SigSpec addr1 = c1->getPort(ID(ADDR));
RTLIL::SigSpec addr2 = c2->getPort(ID(ADDR));
if (GetSize(addr1) < GetSize(addr2))
addr1.extend_u0(GetSize(addr2));
else
addr2.extend_u0(GetSize(addr1));
supercell->setPort("\\ADDR", addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1);
supercell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr1));
supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort("\\DATA"), c2->getPort("\\DATA")));
supercell->setPort(ID(ADDR), addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1);
supercell->parameters[ID(ABITS)] = RTLIL::Const(GetSize(addr1));
supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort(ID(DATA)), c2->getPort(ID(DATA))));
supercell_aux.insert(supercell);
return supercell;
}
@ -747,8 +747,8 @@ struct ShareWorker
modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]);
for (auto &bit : pbits) {
if ((bit.cell->type == "$mux" || bit.cell->type == "$pmux") && bit.port == "\\S")
forbidden_controls_cache[cell].insert(bit.cell->getPort("\\S").extract(bit.offset, 1));
if ((bit.cell->type == ID($mux) || bit.cell->type == ID($pmux)) && bit.port == ID(S))
forbidden_controls_cache[cell].insert(bit.cell->getPort(ID(S)).extract(bit.offset, 1));
consumer_cells.insert(bit.cell);
}
@ -874,7 +874,7 @@ struct ShareWorker
}
for (auto &pbit : modwalker.signal_consumers[bit]) {
log_assert(fwd_ct.cell_known(pbit.cell->type));
if ((pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") && (pbit.port == "\\A" || pbit.port == "\\B"))
if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID::A || pbit.port == ID::B))
driven_data_muxes.insert(pbit.cell);
else
driven_cells.insert(pbit.cell);
@ -890,10 +890,10 @@ struct ShareWorker
bool used_in_a = false;
std::set<int> used_in_b_parts;
int width = c->parameters.at("\\WIDTH").as_int();
std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort("\\A"));
std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort("\\B"));
std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort("\\S"));
int width = c->parameters.at(ID(WIDTH)).as_int();
std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort(ID::A));
std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort(ID::B));
std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort(ID(S)));
for (auto &bit : sig_a)
if (cell_out_bits.count(bit))
@ -1132,14 +1132,14 @@ struct ShareWorker
fwd_ct.setup_internals();
cone_ct.setup_internals();
cone_ct.cell_types.erase("$mul");
cone_ct.cell_types.erase("$mod");
cone_ct.cell_types.erase("$div");
cone_ct.cell_types.erase("$pow");
cone_ct.cell_types.erase("$shl");
cone_ct.cell_types.erase("$shr");
cone_ct.cell_types.erase("$sshl");
cone_ct.cell_types.erase("$sshr");
cone_ct.cell_types.erase(ID($mul));
cone_ct.cell_types.erase(ID($mod));
cone_ct.cell_types.erase(ID($div));
cone_ct.cell_types.erase(ID($pow));
cone_ct.cell_types.erase(ID($shl));
cone_ct.cell_types.erase(ID($shr));
cone_ct.cell_types.erase(ID($sshl));
cone_ct.cell_types.erase(ID($sshr));
modwalker.setup(design, module);
@ -1153,9 +1153,9 @@ struct ShareWorker
GetSize(shareable_cells), log_id(module));
for (auto cell : module->cells())
if (cell->type == "$pmux")
for (auto bit : cell->getPort("\\S"))
for (auto other_bit : cell->getPort("\\S"))
if (cell->type == ID($pmux))
for (auto bit : cell->getPort(ID(S)))
for (auto other_bit : cell->getPort(ID(S)))
if (bit < other_bit)
exclusive_ctrls.push_back(std::pair<RTLIL::SigBit, RTLIL::SigBit>(bit, other_bit));
@ -1466,43 +1466,43 @@ struct SharePass : public Pass {
config.opt_aggressive = false;
config.opt_fast = false;
config.generic_uni_ops.insert("$not");
// config.generic_uni_ops.insert("$pos");
config.generic_uni_ops.insert("$neg");
config.generic_uni_ops.insert(ID($not));
// config.generic_uni_ops.insert(ID($pos));
config.generic_uni_ops.insert(ID($neg));
config.generic_cbin_ops.insert("$and");
config.generic_cbin_ops.insert("$or");
config.generic_cbin_ops.insert("$xor");
config.generic_cbin_ops.insert("$xnor");
config.generic_cbin_ops.insert(ID($and));
config.generic_cbin_ops.insert(ID($or));
config.generic_cbin_ops.insert(ID($xor));
config.generic_cbin_ops.insert(ID($xnor));
config.generic_bin_ops.insert("$shl");
config.generic_bin_ops.insert("$shr");
config.generic_bin_ops.insert("$sshl");
config.generic_bin_ops.insert("$sshr");
config.generic_bin_ops.insert(ID($shl));
config.generic_bin_ops.insert(ID($shr));
config.generic_bin_ops.insert(ID($sshl));
config.generic_bin_ops.insert(ID($sshr));
config.generic_bin_ops.insert("$lt");
config.generic_bin_ops.insert("$le");
config.generic_bin_ops.insert("$eq");
config.generic_bin_ops.insert("$ne");
config.generic_bin_ops.insert("$eqx");
config.generic_bin_ops.insert("$nex");
config.generic_bin_ops.insert("$ge");
config.generic_bin_ops.insert("$gt");
config.generic_bin_ops.insert(ID($lt));
config.generic_bin_ops.insert(ID($le));
config.generic_bin_ops.insert(ID($eq));
config.generic_bin_ops.insert(ID($ne));
config.generic_bin_ops.insert(ID($eqx));
config.generic_bin_ops.insert(ID($nex));
config.generic_bin_ops.insert(ID($ge));
config.generic_bin_ops.insert(ID($gt));
config.generic_cbin_ops.insert("$add");
config.generic_cbin_ops.insert("$mul");
config.generic_cbin_ops.insert(ID($add));
config.generic_cbin_ops.insert(ID($mul));
config.generic_bin_ops.insert("$sub");
config.generic_bin_ops.insert("$div");
config.generic_bin_ops.insert("$mod");
// config.generic_bin_ops.insert("$pow");
config.generic_bin_ops.insert(ID($sub));
config.generic_bin_ops.insert(ID($div));
config.generic_bin_ops.insert(ID($mod));
// config.generic_bin_ops.insert(ID($pow));
config.generic_uni_ops.insert("$logic_not");
config.generic_cbin_ops.insert("$logic_and");
config.generic_cbin_ops.insert("$logic_or");
config.generic_uni_ops.insert(ID($logic_not));
config.generic_cbin_ops.insert(ID($logic_and));
config.generic_cbin_ops.insert(ID($logic_or));
config.generic_other_ops.insert("$alu");
config.generic_other_ops.insert("$macc");
config.generic_other_ops.insert(ID($alu));
config.generic_other_ops.insert(ID($macc));
log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n");

View File

@ -22,7 +22,6 @@
#include "kernel/modtools.h"
USING_YOSYS_NAMESPACE
using namespace RTLIL;
PRIVATE_NAMESPACE_BEGIN
@ -34,13 +33,13 @@ struct WreduceConfig
WreduceConfig()
{
supported_cell_types = pool<IdString>({
"$not", "$pos", "$neg",
"$and", "$or", "$xor", "$xnor",
"$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
"$add", "$sub", "$mul", // "$div", "$mod", "$pow",
"$mux", "$pmux",
"$dff", "$adff"
ID($not), ID($pos), ID($neg),
ID($and), ID($or), ID($xor), ID($xnor),
ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
ID($add), ID($sub), ID($mul), // ID($div), ID($mod), ID($pow),
ID($mux), ID($pmux),
ID($dff), ID($adff)
});
}
};
@ -64,10 +63,10 @@ struct WreduceWorker
{
// Reduce size of MUX if inputs agree on a value for a bit or a output bit is unused
SigSpec sig_a = mi.sigmap(cell->getPort("\\A"));
SigSpec sig_b = mi.sigmap(cell->getPort("\\B"));
SigSpec sig_s = mi.sigmap(cell->getPort("\\S"));
SigSpec sig_y = mi.sigmap(cell->getPort("\\Y"));
SigSpec sig_a = mi.sigmap(cell->getPort(ID::A));
SigSpec sig_b = mi.sigmap(cell->getPort(ID::B));
SigSpec sig_s = mi.sigmap(cell->getPort(ID(S)));
SigSpec sig_y = mi.sigmap(cell->getPort(ID::Y));
std::vector<SigBit> bits_removed;
if (sig_y.has_const())
@ -77,15 +76,15 @@ struct WreduceWorker
{
auto info = mi.query(sig_y[i]);
if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_y[i]))) {
bits_removed.push_back(Sx);
bits_removed.push_back(State::Sx);
continue;
}
SigBit ref = sig_a[i];
for (int k = 0; k < GetSize(sig_s); k++) {
if ((config->keepdc || (ref != Sx && sig_b[k*GetSize(sig_a) + i] != Sx)) && ref != sig_b[k*GetSize(sig_a) + i])
if ((config->keepdc || (ref != State::Sx && sig_b[k*GetSize(sig_a) + i] != State::Sx)) && ref != sig_b[k*GetSize(sig_a) + i])
goto no_match_ab;
if (sig_b[k*GetSize(sig_a) + i] != Sx)
if (sig_b[k*GetSize(sig_a) + i] != State::Sx)
ref = sig_b[k*GetSize(sig_a) + i];
}
if (0)
@ -130,9 +129,9 @@ struct WreduceWorker
for (auto bit : new_work_queue_bits)
work_queue_bits.insert(bit);
cell->setPort("\\A", new_sig_a);
cell->setPort("\\B", new_sig_b);
cell->setPort("\\Y", new_sig_y);
cell->setPort(ID::A, new_sig_a);
cell->setPort(ID::B, new_sig_b);
cell->setPort(ID::Y, new_sig_y);
cell->fixup_parameters();
module->connect(sig_y.extract(n_kept, n_removed), sig_removed);
@ -142,8 +141,8 @@ struct WreduceWorker
{
// Reduce size of FF if inputs are just sign/zero extended or output bit is not used
SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
SigSpec sig_d = mi.sigmap(cell->getPort(ID(D)));
SigSpec sig_q = mi.sigmap(cell->getPort(ID(Q)));
Const initval;
int width_before = GetSize(sig_q);
@ -214,14 +213,14 @@ struct WreduceWorker
work_queue_bits.insert(bit);
// Narrow ARST_VALUE parameter to new size.
if (cell->parameters.count("\\ARST_VALUE")) {
Const arst_value = cell->getParam("\\ARST_VALUE");
if (cell->parameters.count(ID(ARST_VALUE))) {
Const arst_value = cell->getParam(ID(ARST_VALUE));
arst_value.bits.resize(GetSize(sig_q));
cell->setParam("\\ARST_VALUE", arst_value);
cell->setParam(ID(ARST_VALUE), arst_value);
}
cell->setPort("\\D", sig_d);
cell->setPort("\\Q", sig_q);
cell->setPort(ID(D), sig_d);
cell->setPort(ID(Q), sig_q);
cell->fixup_parameters();
}
@ -230,7 +229,7 @@ struct WreduceWorker
port_signed = cell->getParam(stringf("\\%c_SIGNED", port)).as_bool();
SigSpec sig = mi.sigmap(cell->getPort(stringf("\\%c", port)));
if (port == 'B' && cell->type.in("$shl", "$shr", "$sshl", "$sshr"))
if (port == 'B' && cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr)))
port_signed = false;
int bits_removed = 0;
@ -245,7 +244,7 @@ struct WreduceWorker
while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == sig[GetSize(sig)-2])
work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++;
} else {
while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == S0)
while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == State::S0)
work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++;
}
@ -264,13 +263,13 @@ struct WreduceWorker
if (!cell->type.in(config->supported_cell_types))
return;
if (cell->type.in("$mux", "$pmux"))
if (cell->type.in(ID($mux), ID($pmux)))
return run_cell_mux(cell);
if (cell->type.in("$dff", "$adff"))
if (cell->type.in(ID($dff), ID($adff)))
return run_cell_dff(cell);
SigSpec sig = mi.sigmap(cell->getPort("\\Y"));
SigSpec sig = mi.sigmap(cell->getPort(ID::Y));
if (sig.has_const())
return;
@ -278,10 +277,10 @@ struct WreduceWorker
// Reduce size of ports A and B based on constant input bits and size of output port
int max_port_a_size = cell->hasPort("\\A") ? GetSize(cell->getPort("\\A")) : -1;
int max_port_b_size = cell->hasPort("\\B") ? GetSize(cell->getPort("\\B")) : -1;
int max_port_a_size = cell->hasPort(ID::A) ? GetSize(cell->getPort(ID::A)) : -1;
int max_port_b_size = cell->hasPort(ID::B) ? GetSize(cell->getPort(ID::B)) : -1;
if (cell->type.in("$not", "$pos", "$neg", "$and", "$or", "$xor", "$add", "$sub")) {
if (cell->type.in(ID($not), ID($pos), ID($neg), ID($and), ID($or), ID($xor), ID($add), ID($sub))) {
max_port_a_size = min(max_port_a_size, GetSize(sig));
max_port_b_size = min(max_port_b_size, GetSize(sig));
}
@ -289,32 +288,32 @@ struct WreduceWorker
bool port_a_signed = false;
bool port_b_signed = false;
if (max_port_a_size >= 0 && cell->type != "$shiftx")
if (max_port_a_size >= 0 && cell->type != ID($shiftx))
run_reduce_inport(cell, 'A', max_port_a_size, port_a_signed, did_something);
if (max_port_b_size >= 0)
run_reduce_inport(cell, 'B', max_port_b_size, port_b_signed, did_something);
if (cell->hasPort("\\A") && cell->hasPort("\\B") && port_a_signed && port_b_signed) {
SigSpec sig_a = mi.sigmap(cell->getPort("\\A")), sig_b = mi.sigmap(cell->getPort("\\B"));
if (cell->hasPort(ID::A) && cell->hasPort(ID::B) && port_a_signed && port_b_signed) {
SigSpec sig_a = mi.sigmap(cell->getPort(ID::A)), sig_b = mi.sigmap(cell->getPort(ID::B));
if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 &&
GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) {
log("Converting cell %s.%s (%s) from signed to unsigned.\n",
log_id(module), log_id(cell), log_id(cell->type));
cell->setParam("\\A_SIGNED", 0);
cell->setParam("\\B_SIGNED", 0);
cell->setParam(ID(A_SIGNED), 0);
cell->setParam(ID(B_SIGNED), 0);
port_a_signed = false;
port_b_signed = false;
did_something = true;
}
}
if (cell->hasPort("\\A") && !cell->hasPort("\\B") && port_a_signed) {
SigSpec sig_a = mi.sigmap(cell->getPort("\\A"));
if (cell->hasPort(ID::A) && !cell->hasPort(ID::B) && port_a_signed) {
SigSpec sig_a = mi.sigmap(cell->getPort(ID::A));
if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) {
log("Converting cell %s.%s (%s) from signed to unsigned.\n",
log_id(module), log_id(cell), log_id(cell->type));
cell->setParam("\\A_SIGNED", 0);
cell->setParam(ID(A_SIGNED), 0);
port_a_signed = false;
did_something = true;
}
@ -324,7 +323,7 @@ struct WreduceWorker
// Reduce size of port Y based on sizes for A and B and unused bits in Y
int bits_removed = 0;
if (port_a_signed && cell->type == "$shr") {
if (port_a_signed && cell->type == ID($shr)) {
// do not reduce size of output on $shr cells with signed A inputs
} else {
while (GetSize(sig) > 0)
@ -342,24 +341,24 @@ struct WreduceWorker
}
}
if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor"))
if (cell->type.in(ID($pos), ID($add), ID($mul), ID($and), ID($or), ID($xor), ID($sub)))
{
bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool() || cell->type == ID($sub);
int a_size = 0, b_size = 0;
if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A"));
if (cell->hasPort("\\B")) b_size = GetSize(cell->getPort("\\B"));
if (cell->hasPort(ID::A)) a_size = GetSize(cell->getPort(ID::A));
if (cell->hasPort(ID::B)) b_size = GetSize(cell->getPort(ID::B));
int max_y_size = max(a_size, b_size);
if (cell->type == "$add")
if (cell->type.in(ID($add), ID($sub)))
max_y_size++;
if (cell->type == "$mul")
if (cell->type == ID($mul))
max_y_size = a_size + b_size;
while (GetSize(sig) > 1 && GetSize(sig) > max_y_size) {
module->connect(sig[GetSize(sig)-1], is_signed ? sig[GetSize(sig)-2] : S0);
module->connect(sig[GetSize(sig)-1], is_signed ? sig[GetSize(sig)-2] : State::S0);
sig.remove(GetSize(sig)-1);
bits_removed++;
}
@ -374,7 +373,7 @@ struct WreduceWorker
if (bits_removed) {
log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n",
bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type));
cell->setPort("\\Y", sig);
cell->setPort(ID::Y, sig);
did_something = true;
}
@ -387,8 +386,8 @@ struct WreduceWorker
static int count_nontrivial_wire_attrs(RTLIL::Wire *w)
{
int count = w->attributes.size();
count -= w->attributes.count("\\src");
count -= w->attributes.count("\\unused_bits");
count -= w->attributes.count(ID(src));
count -= w->attributes.count(ID(unused_bits));
return count;
}
@ -398,11 +397,11 @@ struct WreduceWorker
SigMap init_attr_sigmap = mi.sigmap;
for (auto w : module->wires()) {
if (w->get_bool_attribute("\\keep"))
if (w->get_bool_attribute(ID::keep))
for (auto bit : mi.sigmap(w))
keep_bits.insert(bit);
if (w->attributes.count("\\init")) {
Const initval = w->attributes.at("\\init");
if (w->attributes.count(ID(init))) {
Const initval = w->attributes.at(ID(init));
SigSpec initsig = init_attr_sigmap(w);
int width = std::min(GetSize(initval), GetSize(initsig));
for (int i = 0; i < width; i++)
@ -459,8 +458,8 @@ struct WreduceWorker
if (!remove_init_bits.empty()) {
for (auto w : module->wires()) {
if (w->attributes.count("\\init")) {
Const initval = w->attributes.at("\\init");
if (w->attributes.count(ID(init))) {
Const initval = w->attributes.at(ID(init));
Const new_initval(State::Sx, GetSize(w));
SigSpec initsig = init_attr_sigmap(w);
int width = std::min(GetSize(initval), GetSize(initsig));
@ -468,7 +467,7 @@ struct WreduceWorker
if (!remove_init_bits.count(initsig[i]))
new_initval[i] = initval[i];
}
w->attributes.at("\\init") = new_initval;
w->attributes.at(ID(init)) = new_initval;
}
}
}
@ -528,23 +527,23 @@ struct WreducePass : public Pass {
for (auto c : module->selected_cells())
{
if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
"$logic_not", "$logic_and", "$logic_or") && GetSize(c->getPort("\\Y")) > 1) {
SigSpec sig = c->getPort("\\Y");
if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(ID::Y)) > 1) {
SigSpec sig = c->getPort(ID::Y);
if (!sig.has_const()) {
c->setPort("\\Y", sig[0]);
c->setParam("\\Y_WIDTH", 1);
c->setPort(ID::Y, sig[0]);
c->setParam(ID(Y_WIDTH), 1);
sig.remove(0);
module->connect(sig, Const(0, GetSize(sig)));
}
}
if (c->type.in("$div", "$mod", "$pow"))
if (c->type.in(ID($div), ID($mod), ID($pow)))
{
SigSpec A = c->getPort("\\A");
SigSpec A = c->getPort(ID::A);
int original_a_width = GetSize(A);
if (c->getParam("\\A_SIGNED").as_bool()) {
if (c->getParam(ID(A_SIGNED)).as_bool()) {
while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0)
A.remove(GetSize(A)-1, 1);
} else {
@ -554,13 +553,13 @@ struct WreducePass : public Pass {
if (original_a_width != GetSize(A)) {
log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n",
original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type));
c->setPort("\\A", A);
c->setParam("\\A_WIDTH", GetSize(A));
c->setPort(ID::A, A);
c->setParam(ID(A_WIDTH), GetSize(A));
}
SigSpec B = c->getPort("\\B");
SigSpec B = c->getPort(ID::B);
int original_b_width = GetSize(B);
if (c->getParam("\\B_SIGNED").as_bool()) {
if (c->getParam(ID(B_SIGNED)).as_bool()) {
while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0)
B.remove(GetSize(B)-1, 1);
} else {
@ -570,24 +569,24 @@ struct WreducePass : public Pass {
if (original_b_width != GetSize(B)) {
log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n",
original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type));
c->setPort("\\B", B);
c->setParam("\\B_WIDTH", GetSize(B));
c->setPort(ID::B, B);
c->setParam(ID(B_WIDTH), GetSize(B));
}
}
if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) {
IdString memid = c->getParam("\\MEMID").decode_string();
if (!opt_memx && c->type.in(ID($memrd), ID($memwr), ID($meminit))) {
IdString memid = c->getParam(ID(MEMID)).decode_string();
RTLIL::Memory *mem = module->memories.at(memid);
if (mem->start_offset >= 0) {
int cur_addrbits = c->getParam("\\ABITS").as_int();
int cur_addrbits = c->getParam(ID(ABITS)).as_int();
int max_addrbits = ceil_log2(mem->start_offset + mem->size);
if (cur_addrbits > max_addrbits) {
log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n",
cur_addrbits-max_addrbits, cur_addrbits,
c->type == "$memrd" ? "read" : c->type == "$memwr" ? "write" : "init",
c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init",
log_id(module), log_id(c), log_id(memid));
c->setParam("\\ABITS", max_addrbits);
c->setPort("\\ADDR", c->getPort("\\ADDR").extract(0, max_addrbits));
c->setParam(ID(ABITS), max_addrbits);
c->setPort(ID(ADDR), c->getPort(ID(ADDR)).extract(0, max_addrbits));
}
}
}

View File

@ -1,2 +1 @@
/ice40_dsp_pm.h
/peepopt_pm.h
/*_pm.h

View File

@ -1,4 +1,5 @@
OBJS += passes/pmgen/ice40_dsp.o
OBJS += passes/pmgen/ice40_wrapcarry.o
OBJS += passes/pmgen/peepopt.o
# --------------------------------------
@ -12,6 +13,15 @@ passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
# --------------------------------------
passes/pmgen/ice40_wrapcarry.o: passes/pmgen/ice40_wrapcarry_pm.h
EXTRA_OBJS += passes/pmgen/ice40_wrapcarry_pm.h
.SECONDARY: passes/pmgen/ice40_wrapcarry_pm.h
passes/pmgen/ice40_wrapcarry_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_wrapcarry.pmg
$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p ice40_wrapcarry $(filter-out $<,$^)
# --------------------------------------
passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
EXTRA_OBJS += passes/pmgen/peepopt_pm.h
.SECONDARY: passes/pmgen/peepopt_pm.h

View File

@ -0,0 +1,90 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* 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 "kernel/yosys.h"
#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
#include "passes/pmgen/ice40_wrapcarry_pm.h"
void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
{
auto &st = pm.st_ice40_wrapcarry;
#if 0
log("\n");
log("carry: %s\n", log_id(st.carry, "--"));
log("lut: %s\n", log_id(st.lut, "--"));
#endif
log(" replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n");
Cell *cell = pm.module->addCell(NEW_ID, "$__ICE40_CARRY_WRAPPER");
pm.module->swap_names(cell, st.carry);
cell->setPort("\\A", st.carry->getPort("\\I0"));
cell->setPort("\\B", st.carry->getPort("\\I1"));
cell->setPort("\\CI", st.carry->getPort("\\CI"));
cell->setPort("\\CO", st.carry->getPort("\\CO"));
cell->setPort("\\I0", st.lut->getPort("\\I0"));
cell->setPort("\\I3", st.lut->getPort("\\I3"));
cell->setPort("\\O", st.lut->getPort("\\O"));
cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT"));
pm.autoremove(st.carry);
pm.autoremove(st.lut);
}
struct Ice40WrapCarryPass : public Pass {
Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" ice40_wrapcarry [selection]\n");
log("\n");
log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUTs,\n");
log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n");
log("mapping.");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
// if (args[argidx] == "-singleton") {
// singleton_mode = true;
// continue;
// }
break;
}
extra_args(args, argidx, design);
for (auto module : design->selected_modules())
ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry);
}
} Ice40WrapCarryPass;
PRIVATE_NAMESPACE_END

View File

@ -0,0 +1,11 @@
pattern ice40_wrapcarry
match carry
select carry->type.in(\SB_CARRY)
endmatch
match lut
select lut->type.in(\SB_LUT4)
index <SigSpec> port(lut, \I1) === port(carry, \I0)
index <SigSpec> port(lut, \I2) === port(carry, \I1)
endmatch

View File

@ -55,7 +55,7 @@ bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSpec ref,
return check_signal(mod, cell->getPort("\\A"), ref, polarity);
}
if ((cell->type == "$eq" || cell->type == "$eqx") && cell->getPort("\\Y") == signal) {
if (cell->type.in("$eq", "$eqx") && cell->getPort("\\Y") == signal) {
if (cell->getPort("\\A").is_fully_const()) {
if (!cell->getPort("\\A").as_bool())
polarity = !polarity;
@ -68,7 +68,7 @@ bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSpec ref,
}
}
if ((cell->type == "$ne" || cell->type == "$nex") && cell->getPort("\\Y") == signal) {
if (cell->type.in("$ne", "$nex") && cell->getPort("\\Y") == signal) {
if (cell->getPort("\\A").is_fully_const()) {
if (cell->getPort("\\A").as_bool())
polarity = !polarity;

View File

@ -65,8 +65,7 @@ struct PruneWorker
pool<RTLIL::SigBit> sw_assigned = do_switch((*it), assigned, affected);
assigned.insert(sw_assigned.begin(), sw_assigned.end());
}
pool<RTLIL::SigSig> remove;
for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ++it) {
for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ) {
RTLIL::SigSpec lhs = sigmap(it->first);
bool redundant = true;
for (auto &bit : lhs) {
@ -75,22 +74,32 @@ struct PruneWorker
break;
}
}
bool remove = false;
if (redundant) {
removed_count++;
remove.insert(*it);
remove = true;
} else {
if (root) {
bool promotable = true;
for (auto &bit : lhs) {
if (bit.wire && affected[bit]) {
if (bit.wire && affected[bit] && !assigned[bit]) {
promotable = false;
break;
}
}
if (promotable) {
RTLIL::SigSpec rhs = sigmap(it->second);
RTLIL::SigSig conn;
for (int i = 0; i < GetSize(lhs); i++) {
RTLIL::SigBit lhs_bit = lhs[i];
if (lhs_bit.wire && !assigned[lhs_bit]) {
conn.first.append_bit(lhs_bit);
conn.second.append(rhs.extract(i));
}
}
promoted_count++;
module->connect(*it);
remove.insert(*it);
module->connect(conn);
remove = true;
}
}
for (auto &bit : lhs)
@ -100,11 +109,9 @@ struct PruneWorker
if (bit.wire)
affected.insert(bit);
}
}
for (auto it = cs->actions.begin(); it != cs->actions.end(); ) {
if (remove[*it]) {
it = cs->actions.erase(it);
} else it++;
if (remove)
cs->actions.erase((it++).base() - 1);
else it++;
}
return assigned;
}

View File

@ -47,8 +47,8 @@ struct BruteForceEquivChecker
{
if (inputs.size() < mod1_inputs.size()) {
RTLIL::SigSpec inputs0 = inputs, inputs1 = inputs;
inputs0.append(RTLIL::Const(0, 1));
inputs1.append(RTLIL::Const(1, 1));
inputs0.append(State::S0);
inputs1.append(State::S1);
run_checker(inputs0);
run_checker(inputs1);
return;

View File

@ -143,7 +143,7 @@ void create_dff_dq_map(std::map<RTLIL::IdString, dff_map_info_t> &map, RTLIL::De
continue;
}
if (info.cell->type == "$_DFF_N_" || info.cell->type == "$_DFF_P_") {
if (info.cell->type.in("$_DFF_N_", "$_DFF_P_")) {
info.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit();
info.clk_polarity = info.cell->type == "$_DFF_P_";
info.bit_d = sigmap(info.cell->getPort("\\D")).as_bit();
@ -151,7 +151,7 @@ void create_dff_dq_map(std::map<RTLIL::IdString, dff_map_info_t> &map, RTLIL::De
continue;
}
if (info.cell->type.size() == 10 && info.cell->type.substr(0, 6) == "$_DFF_") {
if (info.cell->type.size() == 10 && info.cell->type.begins_with("$_DFF_")) {
info.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit();
info.bit_arst = sigmap(info.cell->getPort("\\R")).as_bit();
info.clk_polarity = info.cell->type[6] == 'P';

View File

@ -59,7 +59,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
}
break;
}
if (argidx+3 != args.size() || args[argidx].substr(0, 1) == "-")
if (argidx+3 != args.size() || args[argidx].compare(0, 1, "-") == 0)
that->cmd_error(args, argidx, "command argument error");
RTLIL::IdString gold_name = RTLIL::escape_id(args[argidx++]);
@ -236,7 +236,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
if (flag_make_assert) {
RTLIL::Cell *assert_cell = miter_module->addCell(NEW_ID, "$assert");
assert_cell->setPort("\\A", all_conditions);
assert_cell->setPort("\\EN", RTLIL::SigSpec(1, 1));
assert_cell->setPort("\\EN", State::S1);
}
RTLIL::Wire *w_trigger = miter_module->addWire("\\trigger");
@ -279,7 +279,7 @@ void create_miter_assert(struct Pass *that, std::vector<std::string> args, RTLIL
}
break;
}
if ((argidx+1 != args.size() && argidx+2 != args.size()) || args[argidx].substr(0, 1) == "-")
if ((argidx+1 != args.size() && argidx+2 != args.size()) || args[argidx].compare(0, 1, "-") == 0)
that->cmd_error(args, argidx, "command argument error");
IdString module_name = RTLIL::escape_id(args[argidx++]);

View File

@ -519,7 +519,7 @@ struct SatHelper
for (auto &p : d->connections()) {
if (d->type == "$dff" && p.first == "\\CLK")
continue;
if (d->type.substr(0, 6) == "$_DFF_" && p.first == "\\C")
if (d->type.begins_with("$_DFF_") && p.first == "\\C")
continue;
queued_signals.add(handled_signals.remove(sigmap(p.second)));
}
@ -797,7 +797,7 @@ struct SatHelper
vector<string> data;
string name = wd.first.c_str();
while (name.substr(0, 1) == "\\")
while (name.compare(0, 1, "\\") == 0)
name = name.substr(1);
fprintf(f, " { \"name\": \"%s\", \"wave\": \"", name.c_str());
@ -1353,7 +1353,7 @@ struct SatPass : public Pass {
if (show_regs) {
pool<Wire*> reg_wires;
for (auto cell : module->cells()) {
if (cell->type == "$dff" || cell->type.substr(0, 6) == "$_DFF_")
if (cell->type == "$dff" || cell->type.begins_with("$_DFF_"))
for (auto bit : cell->getPort("\\Q"))
if (bit.wire)
reg_wires.insert(bit.wire);

View File

@ -49,6 +49,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cctype>
#include <cerrno>
#include <sstream>
#include <climits>
@ -81,6 +82,7 @@ enum class gate_type_t {
G_ANDNOT,
G_ORNOT,
G_MUX,
G_NMUX,
G_AOI3,
G_OAI3,
G_AOI4,
@ -111,7 +113,7 @@ std::vector<gate_t> signal_list;
std::map<RTLIL::SigBit, int> signal_map;
std::map<RTLIL::SigBit, RTLIL::State> signal_init;
pool<std::string> enabled_gates;
bool recover_init;
bool recover_init, cmos_cost;
bool clk_polarity, en_polarity;
RTLIL::SigSpec clk_sig, en_sig;
@ -164,39 +166,39 @@ void mark_port(RTLIL::SigSpec sig)
void extract_cell(RTLIL::Cell *cell, bool keepff)
{
if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
{
if (clk_polarity != (cell->type == "$_DFF_P_"))
if (clk_polarity != (cell->type == ID($_DFF_P_)))
return;
if (clk_sig != assign_map(cell->getPort("\\C")))
if (clk_sig != assign_map(cell->getPort(ID(C))))
return;
if (GetSize(en_sig) != 0)
return;
goto matching_dff;
}
if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_")
if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
{
if (clk_polarity != (cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_"))
if (clk_polarity != cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)))
return;
if (en_polarity != (cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_"))
if (en_polarity != cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)))
return;
if (clk_sig != assign_map(cell->getPort("\\C")))
if (clk_sig != assign_map(cell->getPort(ID(C))))
return;
if (en_sig != assign_map(cell->getPort("\\E")))
if (en_sig != assign_map(cell->getPort(ID(E))))
return;
goto matching_dff;
}
if (0) {
matching_dff:
RTLIL::SigSpec sig_d = cell->getPort("\\D");
RTLIL::SigSpec sig_q = cell->getPort("\\Q");
RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
if (keepff)
for (auto &c : sig_q.chunks())
if (c.wire != NULL)
c.wire->attributes["\\keep"] = 1;
c.wire->attributes[ID::keep] = 1;
assign_map.apply(sig_d);
assign_map.apply(sig_q);
@ -207,25 +209,25 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
return;
}
if (cell->type.in("$_BUF_", "$_NOT_"))
if (cell->type.in(ID($_BUF_), ID($_NOT_)))
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
assign_map.apply(sig_a);
assign_map.apply(sig_y);
map_signal(sig_y, cell->type == "$_BUF_" ? G(BUF) : G(NOT), map_signal(sig_a));
map_signal(sig_y, cell->type == ID($_BUF_) ? G(BUF) : G(NOT), map_signal(sig_a));
module->remove(cell);
return;
}
if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_"))
if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)))
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_b = cell->getPort("\\B");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
assign_map.apply(sig_a);
assign_map.apply(sig_b);
@ -234,21 +236,21 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
int mapped_a = map_signal(sig_a);
int mapped_b = map_signal(sig_b);
if (cell->type == "$_AND_")
if (cell->type == ID($_AND_))
map_signal(sig_y, G(AND), mapped_a, mapped_b);
else if (cell->type == "$_NAND_")
else if (cell->type == ID($_NAND_))
map_signal(sig_y, G(NAND), mapped_a, mapped_b);
else if (cell->type == "$_OR_")
else if (cell->type == ID($_OR_))
map_signal(sig_y, G(OR), mapped_a, mapped_b);
else if (cell->type == "$_NOR_")
else if (cell->type == ID($_NOR_))
map_signal(sig_y, G(NOR), mapped_a, mapped_b);
else if (cell->type == "$_XOR_")
else if (cell->type == ID($_XOR_))
map_signal(sig_y, G(XOR), mapped_a, mapped_b);
else if (cell->type == "$_XNOR_")
else if (cell->type == ID($_XNOR_))
map_signal(sig_y, G(XNOR), mapped_a, mapped_b);
else if (cell->type == "$_ANDNOT_")
else if (cell->type == ID($_ANDNOT_))
map_signal(sig_y, G(ANDNOT), mapped_a, mapped_b);
else if (cell->type == "$_ORNOT_")
else if (cell->type == ID($_ORNOT_))
map_signal(sig_y, G(ORNOT), mapped_a, mapped_b);
else
log_abort();
@ -257,12 +259,12 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
return;
}
if (cell->type == "$_MUX_")
if (cell->type.in(ID($_MUX_), ID($_NMUX_)))
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_b = cell->getPort("\\B");
RTLIL::SigSpec sig_s = cell->getPort("\\S");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_s = cell->getPort(ID(S));
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
assign_map.apply(sig_a);
assign_map.apply(sig_b);
@ -273,18 +275,18 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
int mapped_b = map_signal(sig_b);
int mapped_s = map_signal(sig_s);
map_signal(sig_y, G(MUX), mapped_a, mapped_b, mapped_s);
map_signal(sig_y, cell->type == ID($_MUX_) ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s);
module->remove(cell);
return;
}
if (cell->type.in("$_AOI3_", "$_OAI3_"))
if (cell->type.in(ID($_AOI3_), ID($_OAI3_)))
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_b = cell->getPort("\\B");
RTLIL::SigSpec sig_c = cell->getPort("\\C");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_c = cell->getPort(ID(C));
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
assign_map.apply(sig_a);
assign_map.apply(sig_b);
@ -295,19 +297,19 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
int mapped_b = map_signal(sig_b);
int mapped_c = map_signal(sig_c);
map_signal(sig_y, cell->type == "$_AOI3_" ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c);
map_signal(sig_y, cell->type == ID($_AOI3_) ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c);
module->remove(cell);
return;
}
if (cell->type.in("$_AOI4_", "$_OAI4_"))
if (cell->type.in(ID($_AOI4_), ID($_OAI4_)))
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_b = cell->getPort("\\B");
RTLIL::SigSpec sig_c = cell->getPort("\\C");
RTLIL::SigSpec sig_d = cell->getPort("\\D");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_c = cell->getPort(ID(C));
RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
assign_map.apply(sig_a);
assign_map.apply(sig_b);
@ -320,7 +322,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
int mapped_c = map_signal(sig_c);
int mapped_d = map_signal(sig_d);
map_signal(sig_y, cell->type == "$_AOI4_" ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d);
map_signal(sig_y, cell->type == ID($_AOI4_) ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d);
module->remove(cell);
return;
@ -331,17 +333,17 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp
{
std::string abc_sname = abc_name.substr(1);
bool isnew = false;
if (abc_sname.substr(0, 4) == "new_")
if (abc_sname.compare(0, 4, "new_") == 0)
{
abc_sname.erase(0, 4);
isnew = true;
}
if (abc_sname.substr(0, 5) == "ys__n")
if (abc_sname.compare(0, 5, "ys__n") == 0)
{
abc_sname.erase(0, 5);
if (std::isdigit(abc_sname.at(0)))
{
int sid = std::stoi(abc_sname);
int sid = std::atoi(abc_sname.c_str());
size_t postfix_start = abc_sname.find_first_not_of("0123456789");
std::string postfix = postfix_start != std::string::npos ? abc_sname.substr(postfix_start) : "";
@ -350,23 +352,20 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp
auto sig = signal_list.at(sid);
if (sig.bit.wire != nullptr)
{
std::stringstream sstr;
sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1);
std::string s = stringf("$abc$%d$%s", map_autoidx, sig.bit.wire->name.c_str()+1);
if (sig.bit.wire->width != 1)
sstr << "[" << sig.bit.offset << "]";
s += stringf("[%d]", sig.bit.offset);
if (isnew)
sstr << "_new";
sstr << postfix;
s += "_new";
s += postfix;
if (orig_wire != nullptr)
*orig_wire = sig.bit.wire;
return sstr.str();
return s;
}
}
}
}
std::stringstream sstr;
sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1);
return sstr.str();
return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
}
void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edges, std::set<int> &workpool, std::vector<int> &in_counts)
@ -788,7 +787,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
extract_cell(c, keepff);
for (auto &wire_it : module->wires_) {
if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute("\\keep"))
if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute(ID::keep))
mark_port(RTLIL::SigSpec(wire_it.second));
}
@ -885,6 +884,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
fprintf(f, "1-0 1\n");
fprintf(f, "-11 1\n");
} else if (si.type == G(NMUX)) {
fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
fprintf(f, "0-0 1\n");
fprintf(f, "-01 1\n");
} else if (si.type == G(AOI3)) {
fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
fprintf(f, "-00 1\n");
@ -925,46 +928,50 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
{
log_header(design, "Executing ABC.\n");
auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost();
buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
f = fopen(buffer.c_str(), "wt");
if (f == NULL)
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
fprintf(f, "GATE ZERO 1 Y=CONST0;\n");
fprintf(f, "GATE ONE 1 Y=CONST1;\n");
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_BUF_"));
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOT_"));
if (enabled_gates.empty() || enabled_gates.count("AND"))
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_AND_"));
if (enabled_gates.empty() || enabled_gates.count("NAND"))
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NAND_"));
if (enabled_gates.empty() || enabled_gates.count("OR"))
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_OR_"));
if (enabled_gates.empty() || enabled_gates.count("NOR"))
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOR_"));
if (enabled_gates.empty() || enabled_gates.count("XOR"))
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_"));
if (enabled_gates.empty() || enabled_gates.count("XNOR"))
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_"));
if (enabled_gates.empty() || enabled_gates.count("ANDNOT"))
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ANDNOT_"));
if (enabled_gates.empty() || enabled_gates.count("ORNOT"))
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ORNOT_"));
if (enabled_gates.empty() || enabled_gates.count("AOI3"))
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI3_"));
if (enabled_gates.empty() || enabled_gates.count("OAI3"))
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI3_"));
if (enabled_gates.empty() || enabled_gates.count("AOI4"))
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI4_"));
if (enabled_gates.empty() || enabled_gates.count("OAI4"))
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_"));
if (enabled_gates.empty() || enabled_gates.count("MUX"))
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_MUX_"));
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_BUF_)));
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOT_)));
if (enabled_gates.count("AND"))
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_AND_)));
if (enabled_gates.count("NAND"))
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NAND_)));
if (enabled_gates.count("OR"))
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_OR_)));
if (enabled_gates.count("NOR"))
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOR_)));
if (enabled_gates.count("XOR"))
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XOR_)));
if (enabled_gates.count("XNOR"))
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XNOR_)));
if (enabled_gates.count("ANDNOT"))
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ANDNOT_)));
if (enabled_gates.count("ORNOT"))
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ORNOT_)));
if (enabled_gates.count("AOI3"))
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_AOI3_)));
if (enabled_gates.count("OAI3"))
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_OAI3_)));
if (enabled_gates.count("AOI4"))
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_AOI4_)));
if (enabled_gates.count("OAI4"))
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_OAI4_)));
if (enabled_gates.count("MUX"))
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_MUX_)));
if (enabled_gates.count("NMUX"))
fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_NMUX_)));
if (map_mux4)
fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*get_cell_cost("$_MUX_"));
fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at(ID($_MUX_)));
if (map_mux8)
fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_"));
fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at(ID($_MUX_)));
if (map_mux16)
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_"));
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at(ID($_MUX_)));
fclose(f);
if (!lut_costs.empty()) {
@ -1009,21 +1016,21 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
bool builtin_lib = liberty_file.empty();
RTLIL::Design *mapped_design = new RTLIL::Design;
parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode);
parse_blif(mapped_design, ifs, builtin_lib ? ID(DFF) : ID(_dff_), false, sop_mode);
ifs.close();
log_header(design, "Re-integrating ABC results.\n");
RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"];
RTLIL::Module *mapped_mod = mapped_design->modules_[ID(netlist)];
if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `netlist'.\n");
for (auto &it : mapped_mod->wires_) {
RTLIL::Wire *w = it.second;
RTLIL::Wire *orig_wire = nullptr;
RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire));
if (orig_wire != nullptr && orig_wire->attributes.count("\\src"))
wire->attributes["\\src"] = orig_wire->attributes["\\src"];
if (markgroups) wire->attributes["\\abcgroup"] = map_autoidx;
if (orig_wire != nullptr && orig_wire->attributes.count(ID(src)))
wire->attributes[ID(src)] = orig_wire->attributes[ID(src)];
if (markgroups) wire->attributes[ID(abcgroup)] = map_autoidx;
design->select(module, wire);
}
@ -1033,141 +1040,140 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (builtin_lib)
{
cell_stats[RTLIL::unescape_id(c->type)]++;
if (c->type == "\\ZERO" || c->type == "\\ONE") {
if (c->type.in(ID(ZERO), ID(ONE))) {
RTLIL::SigSig conn;
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]);
conn.second = RTLIL::SigSpec(c->type == "\\ZERO" ? 0 : 1, 1);
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]);
conn.second = RTLIL::SigSpec(c->type == ID(ZERO) ? 0 : 1, 1);
module->connect(conn);
continue;
}
if (c->type == "\\BUF") {
if (c->type == ID(BUF)) {
RTLIL::SigSig conn;
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]);
conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]);
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]);
conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]);
module->connect(conn);
continue;
}
if (c->type == "\\NOT") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_NOT_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
if (c->type == ID(NOT)) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_NOT_));
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
design->select(module, cell);
continue;
}
if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" ||
c->type == "\\XNOR" || c->type == "\\ANDNOT" || c->type == "\\ORNOT") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
if (c->type.in(ID(AND), ID(OR), ID(XOR), ID(NAND), ID(NOR), ID(XNOR), ID(ANDNOT), ID(ORNOT))) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
design->select(module, cell);
continue;
}
if (c->type == "\\MUX") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
if (c->type.in(ID(MUX), ID(NMUX))) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
design->select(module, cell);
continue;
}
if (c->type == "\\MUX4") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX4_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
if (c->type == ID(MUX4)) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX4_));
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
design->select(module, cell);
continue;
}
if (c->type == "\\MUX8") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX8_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
if (c->type == ID(MUX8)) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX8_));
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
cell->setPort(ID(F), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(F)).as_wire()->name)]));
cell->setPort(ID(G), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(G)).as_wire()->name)]));
cell->setPort(ID(H), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(H)).as_wire()->name)]));
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
design->select(module, cell);
continue;
}
if (c->type == "\\MUX16") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX16_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
cell->setPort("\\I", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\I").as_wire()->name)]));
cell->setPort("\\J", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\J").as_wire()->name)]));
cell->setPort("\\K", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\K").as_wire()->name)]));
cell->setPort("\\L", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\L").as_wire()->name)]));
cell->setPort("\\M", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\M").as_wire()->name)]));
cell->setPort("\\N", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\N").as_wire()->name)]));
cell->setPort("\\O", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\O").as_wire()->name)]));
cell->setPort("\\P", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\P").as_wire()->name)]));
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
cell->setPort("\\V", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\V").as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
if (c->type == ID(MUX16)) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX16_));
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
cell->setPort(ID(F), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(F)).as_wire()->name)]));
cell->setPort(ID(G), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(G)).as_wire()->name)]));
cell->setPort(ID(H), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(H)).as_wire()->name)]));
cell->setPort(ID(I), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(I)).as_wire()->name)]));
cell->setPort(ID(J), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(J)).as_wire()->name)]));
cell->setPort(ID(K), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(K)).as_wire()->name)]));
cell->setPort(ID(L), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(L)).as_wire()->name)]));
cell->setPort(ID(M), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(M)).as_wire()->name)]));
cell->setPort(ID(N), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(N)).as_wire()->name)]));
cell->setPort(ID(O), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(O)).as_wire()->name)]));
cell->setPort(ID(P), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(P)).as_wire()->name)]));
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
cell->setPort(ID(V), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(V)).as_wire()->name)]));
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
design->select(module, cell);
continue;
}
if (c->type == "\\AOI3" || c->type == "\\OAI3") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
if (c->type.in(ID(AOI3), ID(OAI3))) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
design->select(module, cell);
continue;
}
if (c->type == "\\AOI4" || c->type == "\\OAI4") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
if (c->type.in(ID(AOI4), ID(OAI4))) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
design->select(module, cell);
continue;
}
if (c->type == "\\DFF") {
if (c->type == ID(DFF)) {
log_assert(clk_sig.size() == 1);
RTLIL::Cell *cell;
if (en_sig.size() == 0) {
cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_));
} else {
log_assert(en_sig.size() == 1);
cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
cell->setPort("\\E", en_sig);
cell->setPort(ID(E), en_sig);
}
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
cell->setPort("\\C", clk_sig);
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort(ID(Q), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Q)).as_wire()->name)]));
cell->setPort(ID(C), clk_sig);
design->select(module, cell);
continue;
}
@ -1175,41 +1181,41 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
else
cell_stats[RTLIL::unescape_id(c->type)]++;
if (c->type == "\\_const0_" || c->type == "\\_const1_") {
if (c->type.in(ID(_const0_), ID(_const1_))) {
RTLIL::SigSig conn;
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->connections().begin()->second.as_wire()->name)]);
conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1);
conn.second = RTLIL::SigSpec(c->type == ID(_const0_) ? 0 : 1, 1);
module->connect(conn);
continue;
}
if (c->type == "\\_dff_") {
if (c->type == ID(_dff_)) {
log_assert(clk_sig.size() == 1);
RTLIL::Cell *cell;
if (en_sig.size() == 0) {
cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_));
} else {
log_assert(en_sig.size() == 1);
cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
cell->setPort("\\E", en_sig);
cell->setPort(ID(E), en_sig);
}
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
cell->setPort("\\C", clk_sig);
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort(ID(Q), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Q)).as_wire()->name)]));
cell->setPort(ID(C), clk_sig);
design->select(module, cell);
continue;
}
if (c->type == "$lut" && GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)];
SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)];
if (c->type == ID($lut) && GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)).as_int() == 2) {
SigSpec my_a = module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)];
SigSpec my_y = module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)];
module->connect(my_y, my_a);
continue;
}
RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type);
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->parameters = c->parameters;
for (auto &conn : c->connections()) {
RTLIL::SigSpec newsig;
@ -1234,10 +1240,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (recover_init)
for (auto wire : mapped_mod->wires()) {
if (wire->attributes.count("\\init")) {
if (wire->attributes.count(ID(init))) {
Wire *w = module->wires_[remap_name(wire->name)];
log_assert(w->attributes.count("\\init") == 0);
w->attributes["\\init"] = wire->attributes.at("\\init");
log_assert(w->attributes.count(ID(init)) == 0);
w->attributes[ID(init)] = wire->attributes.at(ID(init));
}
}
@ -1401,20 +1407,27 @@ struct AbcPass : public Pass {
// log("\n");
log(" -g type1,type2,...\n");
log(" Map to the specified list of gate types. Supported gates types are:\n");
log(" AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4.\n");
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log(" AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX,\n");
log(" NMUX, AOI3, OAI3, AOI4, OAI4.\n");
log(" (The NOT gate is always added to this list automatically.)\n");
log("\n");
log(" The following aliases can be used to reference common sets of gate types:\n");
log(" simple: AND OR XOR MUX\n");
log(" cmos2: NAND NOR\n");
log(" cmos3: NAND NOR AOI3 OAI3\n");
log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n");
log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n");
log(" cmos2: NAND NOR\n");
log(" cmos3: NAND NOR AOI3 OAI3\n");
log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n");
log(" cmos: NAND NOR AOI3 OAI3 AOI4 OAI4 NMUX MUX XOR XNOR\n");
log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n");
log("\n");
log(" The alias 'all' represent the full set of all gate types.\n");
log("\n");
log(" Prefix a gate type with a '-' to remove it from the list. For example\n");
log(" the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent.\n");
log("\n");
log(" The default is 'all,-NMUX,-AOI3,-OAI3,-AOI4,-OAI4'.\n");
log("\n");
log(" -dff\n");
log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n");
log(" clock domains are automatically partitioned in clock domains and each\n");
@ -1488,6 +1501,7 @@ struct AbcPass : public Pass {
map_mux8 = false;
map_mux16 = false;
enabled_gates.clear();
cmos_cost = false;
#ifdef _WIN32
#ifndef ABCEXTERNAL
@ -1572,7 +1586,7 @@ struct AbcPass : public Pass {
else if (GetSize(parts) == 1)
lut_costs.push_back(atoi(parts.at(0).c_str()));
else if (GetSize(parts) == 2)
while (GetSize(lut_costs) < atoi(parts.at(0).c_str()))
while (GetSize(lut_costs) < std::atoi(parts.at(0).c_str()))
lut_costs.push_back(atoi(parts.at(1).c_str()));
else
log_cmd_error("Invalid -luts syntax.\n");
@ -1616,6 +1630,7 @@ struct AbcPass : public Pass {
if (g == "ANDNOT") goto ok_gate;
if (g == "ORNOT") goto ok_gate;
if (g == "MUX") goto ok_gate;
if (g == "NMUX") goto ok_gate;
if (g == "AOI3") goto ok_gate;
if (g == "OAI3") goto ok_gate;
if (g == "AOI4") goto ok_gate;
@ -1628,11 +1643,15 @@ struct AbcPass : public Pass {
goto ok_alias;
}
if (g == "cmos2") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
goto ok_alias;
}
if (g == "cmos3") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
@ -1640,6 +1659,8 @@ struct AbcPass : public Pass {
goto ok_alias;
}
if (g == "cmos4") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
@ -1648,6 +1669,21 @@ struct AbcPass : public Pass {
gate_list.push_back("OAI4");
goto ok_alias;
}
if (g == "cmos") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
gate_list.push_back("AOI4");
gate_list.push_back("OAI4");
gate_list.push_back("NMUX");
gate_list.push_back("MUX");
gate_list.push_back("XOR");
gate_list.push_back("XNOR");
goto ok_alias;
}
if (g == "gates") {
gate_list.push_back("AND");
gate_list.push_back("NAND");
@ -1668,6 +1704,22 @@ struct AbcPass : public Pass {
gate_list.push_back("ORNOT");
goto ok_alias;
}
if (g == "all") {
gate_list.push_back("AND");
gate_list.push_back("NAND");
gate_list.push_back("OR");
gate_list.push_back("NOR");
gate_list.push_back("XOR");
gate_list.push_back("XNOR");
gate_list.push_back("ANDNOT");
gate_list.push_back("ORNOT");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
gate_list.push_back("AOI4");
gate_list.push_back("OAI4");
gate_list.push_back("MUX");
gate_list.push_back("NMUX");
}
cmd_error(args, argidx, stringf("Unsupported gate type: %s", g.c_str()));
ok_gate:
gate_list.push_back(g);
@ -1719,6 +1771,23 @@ struct AbcPass : public Pass {
if (!constr_file.empty() && liberty_file.empty())
log_cmd_error("Got -constr but no -liberty!\n");
if (enabled_gates.empty()) {
enabled_gates.insert("AND");
enabled_gates.insert("NAND");
enabled_gates.insert("OR");
enabled_gates.insert("NOR");
enabled_gates.insert("XOR");
enabled_gates.insert("XNOR");
enabled_gates.insert("ANDNOT");
enabled_gates.insert("ORNOT");
// enabled_gates.insert("AOI3");
// enabled_gates.insert("OAI3");
// enabled_gates.insert("AOI4");
// enabled_gates.insert("OAI4");
enabled_gates.insert("MUX");
// enabled_gates.insert("NMUX");
}
for (auto mod : design->selected_modules())
{
if (mod->processes.size() > 0) {
@ -1730,9 +1799,9 @@ struct AbcPass : public Pass {
signal_init.clear();
for (Wire *wire : mod->wires())
if (wire->attributes.count("\\init")) {
if (wire->attributes.count(ID(init))) {
SigSpec initsig = assign_map(wire);
Const initval = wire->attributes.at("\\init");
Const initval = wire->attributes.at(ID(init));
for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
switch (initval[i]) {
case State::S0:
@ -1789,16 +1858,16 @@ struct AbcPass : public Pass {
}
}
if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
{
key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec());
key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec());
}
else
if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_")
if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
{
bool this_clk_pol = cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_";
bool this_en_pol = cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_";
key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E")));
bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E))));
}
else
continue;

View File

@ -71,25 +71,23 @@ RTLIL::Module *module;
bool clk_polarity, en_polarity;
RTLIL::SigSpec clk_sig, en_sig;
std::string remap_name(RTLIL::IdString abc_name)
inline std::string remap_name(RTLIL::IdString abc_name)
{
std::stringstream sstr;
sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1);
return sstr.str();
return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
}
void handle_loops(RTLIL::Design *design)
{
Pass::call(design, "scc -set_attr abc_scc_id {}");
dict<IdString, vector<IdString>> abc_scc_break;
dict<IdString, vector<IdString>> abc_scc_break;
// For every unique SCC found, (arbitrarily) find the first
// cell in the component, and select (and mark) all its output
// wires
pool<RTLIL::Const> ids_seen;
for (auto cell : module->cells()) {
auto it = cell->attributes.find("\\abc_scc_id");
auto it = cell->attributes.find(ID(abc_scc_id));
if (it != cell->attributes.end()) {
auto r = ids_seen.insert(it->second);
if (r.second) {
@ -109,7 +107,7 @@ void handle_loops(RTLIL::Design *design)
log_assert(w->port_input);
log_assert(b.offset < GetSize(w));
}
w->set_bool_attribute("\\abc_scc_break");
w->set_bool_attribute(ID(abc_scc_break));
module->swap_names(b.wire, w);
c.second = RTLIL::SigBit(w, b.offset);
}
@ -123,7 +121,7 @@ void handle_loops(RTLIL::Design *design)
std::vector<IdString> ports;
RTLIL::Module* box_module = design->module(cell->type);
if (box_module) {
auto ports_csv = box_module->attributes.at("\\abc_scc_break", RTLIL::Const::from_string("")).decode_string();
auto ports_csv = box_module->attributes.at(ID(abc_scc_break), RTLIL::Const::from_string("")).decode_string();
for (const auto &port_name : split_tokens(ports_csv, ",")) {
auto port_id = RTLIL::escape_id(port_name);
auto kt = cell->connections_.find(port_id);
@ -142,7 +140,7 @@ void handle_loops(RTLIL::Design *design)
Wire *w = b.wire;
if (!w) continue;
w->port_output = true;
w->set_bool_attribute("\\abc_scc_break");
w->set_bool_attribute(ID(abc_scc_break));
w = module->wire(stringf("%s.abci", w->name.c_str()));
if (!w) {
w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire));
@ -290,7 +288,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
bool show_tempdir, std::string box_file, std::string lut_file,
std::string wire_delay)
std::string wire_delay, const dict<int,IdString> &box_lookup)
{
module = current_module;
map_autoidx = autoidx++;
@ -429,10 +427,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
RTLIL::Selection& sel = design->selection_stack.back();
sel.select(module);
Pass::call(design, "aigmap");
handle_loops(design);
Pass::call(design, "aigmap");
//log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
// count_gates, GetSize(signal_list), count_input, count_output);
@ -446,14 +444,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
if (ifs.fail())
log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
log_assert(!design->module("$__abc9__"));
log_assert(!design->module(ID($__abc9__)));
{
AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
reader.parse_xaiger();
}
ifs.close();
Pass::call(design, stringf("write_verilog -noexpr -norename"));
design->remove(design->module("$__abc9__"));
design->remove(design->module(ID($__abc9__)));
#endif
design->selection_stack.pop_back();
@ -462,7 +460,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
// the expose operation -- remove them from PO/PI
// and re-connecting them back together
for (auto wire : module->wires()) {
auto it = wire->attributes.find("\\abc_scc_break");
auto it = wire->attributes.find(ID(abc_scc_break));
if (it != wire->attributes.end()) {
wire->attributes.erase(it);
log_assert(wire->port_output);
@ -476,7 +474,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
}
module->fixup_ports();
log_header(design, "Executing ABC9.\n");
if (!lut_costs.empty()) {
@ -519,9 +516,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
log_assert(!design->module("$__abc9__"));
AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
reader.parse_xaiger();
log_assert(!design->module(ID($__abc9__)));
AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
reader.parse_xaiger(box_lookup);
ifs.close();
#if 0
@ -529,7 +527,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
#endif
log_header(design, "Re-integrating ABC9 results.\n");
RTLIL::Module *mapped_mod = design->module("$__abc9__");
RTLIL::Module *mapped_mod = design->module(ID($__abc9__));
if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `$__abc9__'.\n");
@ -537,7 +535,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
for (auto &it : mapped_mod->wires_) {
RTLIL::Wire *w = it.second;
RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w));
if (markgroups) remap_wire->attributes["\\abcgroup"] = map_autoidx;
if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx;
if (w->port_output) {
RTLIL::Wire *wire = module->wire(w->name);
log_assert(wire);
@ -559,14 +557,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
vector<RTLIL::Cell*> boxes;
for (const auto &it : module->cells_) {
auto cell = it.second;
if (cell->type.in("$_AND_", "$_NOT_")) {
if (cell->type.in(ID($_AND_), ID($_NOT_))) {
module->remove(cell);
continue;
}
auto jt = abc_box.find(cell->type);
if (jt == abc_box.end()) {
RTLIL::Module* box_module = design->module(cell->type);
jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count("\\abc_box_id"))).first;
jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc_box_id)))).first;
}
if (jt->second)
boxes.emplace_back(cell);
@ -577,23 +575,23 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
dict<RTLIL::Cell*,RTLIL::Cell*> not2drivers;
dict<SigBit, std::vector<RTLIL::Cell*>> bit2sinks;
std::map<std::string, int> cell_stats;
std::map<IdString, int> cell_stats;
for (auto c : mapped_mod->cells())
{
toposort.node(c->name);
RTLIL::Cell *cell = nullptr;
if (c->type == "$_NOT_") {
RTLIL::SigBit a_bit = c->getPort("\\A");
RTLIL::SigBit y_bit = c->getPort("\\Y");
if (c->type == ID($_NOT_)) {
RTLIL::SigBit a_bit = c->getPort(ID::A);
RTLIL::SigBit y_bit = c->getPort(ID::Y);
bit_users[a_bit].insert(c->name);
bit_drivers[y_bit].insert(c->name);
if (!a_bit.wire) {
c->setPort("\\Y", module->addWire(NEW_ID));
c->setPort(ID::Y, module->addWire(NEW_ID));
RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
log_assert(wire);
module->connect(RTLIL::SigBit(wire, y_bit.offset), RTLIL::S1);
module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1);
}
else if (!lut_costs.empty() || !lut_file.empty()) {
RTLIL::Cell* driver_lut = nullptr;
@ -618,8 +616,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
RTLIL::Const::from_string("01"));
bit2sinks[cell->getPort("\\A")].push_back(cell);
cell_stats["$lut"]++;
bit2sinks[cell->getPort(ID::A)].push_back(cell);
cell_stats[ID($lut)]++;
}
else
not2drivers[c] = driver_lut;
@ -627,18 +625,18 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
}
else
log_abort();
if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
continue;
}
cell_stats[RTLIL::unescape_id(c->type)]++;
cell_stats[c->type]++;
RTLIL::Cell *existing_cell = nullptr;
if (c->type == "$lut") {
if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT") == RTLIL::Const::from_string("01")) {
SigSpec my_a = module->wires_.at(remap_name(c->getPort("\\A").as_wire()->name));
SigSpec my_y = module->wires_.at(remap_name(c->getPort("\\Y").as_wire()->name));
if (c->type == ID($lut)) {
if (GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) {
SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID::A).as_wire()->name));
SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID::Y).as_wire()->name));
module->connect(my_y, my_a);
if (markgroups) c->attributes["\\abcgroup"] = map_autoidx;
if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx;
log_abort();
continue;
}
@ -646,11 +644,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
}
else {
existing_cell = module->cell(c->name);
log_assert(existing_cell);
cell = module->addCell(remap_name(c->name), c->type);
module->swap_names(cell, existing_cell);
}
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
if (existing_cell) {
cell->parameters = existing_cell->parameters;
cell->attributes = existing_cell->attributes;
@ -740,20 +739,20 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
for (auto driver_cell : bit_drivers.at(it.first))
for (auto user_cell : it.second)
toposort.edge(driver_cell, user_cell);
bool no_loops = toposort.sort();
bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
log_assert(no_loops);
for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) {
RTLIL::Cell *not_cell = mapped_mod->cell(*ii);
log_assert(not_cell);
if (not_cell->type != "$_NOT_")
if (not_cell->type != ID($_NOT_))
continue;
auto it = not2drivers.find(not_cell);
if (it == not2drivers.end())
continue;
RTLIL::Cell *driver_lut = it->second;
RTLIL::SigBit a_bit = not_cell->getPort("\\A");
RTLIL::SigBit y_bit = not_cell->getPort("\\Y");
RTLIL::SigBit a_bit = not_cell->getPort(ID::A);
RTLIL::SigBit y_bit = not_cell->getPort(ID::Y);
RTLIL::Const driver_mask;
a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name));
@ -764,13 +763,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
goto clone_lut;
for (auto sink_cell : jt->second)
if (sink_cell->type != "$lut")
if (sink_cell->type != ID($lut))
goto clone_lut;
// Push downstream LUTs past inverter
for (auto sink_cell : jt->second) {
SigSpec A = sink_cell->getPort("\\A");
RTLIL::Const mask = sink_cell->getParam("\\LUT");
SigSpec A = sink_cell->getPort(ID::A);
RTLIL::Const mask = sink_cell->getParam(ID(LUT));
int index = 0;
for (; index < GetSize(A); index++)
if (A[index] == a_bit)
@ -783,8 +782,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
i += 1 << (index+1);
}
A[index] = y_bit;
sink_cell->setPort("\\A", A);
sink_cell->setParam("\\LUT", mask);
sink_cell->setPort(ID::A, A);
sink_cell->setParam(ID(LUT), mask);
}
// Since we have rewritten all sinks (which we know
@ -793,16 +792,16 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
// that the original driving LUT will become dangling
// and get cleaned away
clone_lut:
driver_mask = driver_lut->getParam("\\LUT");
driver_mask = driver_lut->getParam(ID(LUT));
for (auto &b : driver_mask.bits) {
if (b == RTLIL::State::S0) b = RTLIL::State::S1;
else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
}
auto cell = module->addLut(NEW_ID,
driver_lut->getPort("\\A"),
driver_lut->getPort(ID::A),
y_bit,
driver_mask);
for (auto &bit : cell->connections_.at("\\A")) {
for (auto &bit : cell->connections_.at(ID::A)) {
bit.wire = module->wires_.at(remap_name(bit.wire->name));
bit2sinks[bit].push_back(cell);
}
@ -1081,9 +1080,24 @@ struct Abc9Pass : public Pass {
}
extra_args(args, argidx, design);
dict<int,IdString> box_lookup;
for (auto m : design->modules()) {
auto it = m->attributes.find(ID(abc_box_id));
if (it == m->attributes.end())
continue;
if (m->name.begins_with("$paramod"))
continue;
auto id = it->second.as_int();
auto r = box_lookup.insert(std::make_pair(id, m->name));
if (!r.second)
log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n",
log_id(m), id, log_id(r.first->second));
log_assert(r.second);
}
for (auto mod : design->selected_modules())
{
if (mod->attributes.count("\\abc_box_id"))
if (mod->attributes.count(ID(abc_box_id)))
continue;
if (mod->processes.size() > 0) {
@ -1096,7 +1110,7 @@ struct Abc9Pass : public Pass {
if (!dff_mode || !clk_str.empty()) {
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay);
box_file, lut_file, wire_delay, box_lookup);
continue;
}
@ -1137,16 +1151,16 @@ struct Abc9Pass : public Pass {
}
}
if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
{
key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec());
key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec());
}
else
if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_")
if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
{
bool this_clk_pol = cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_";
bool this_en_pol = cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_";
key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E")));
bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E))));
}
else
continue;
@ -1242,15 +1256,16 @@ struct Abc9Pass : public Pass {
en_sig = assign_map(std::get<3>(it.first));
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay);
box_file, lut_file, wire_delay, box_lookup);
assign_map.set(mod);
}
}
Pass::call(design, "clean");
assign_map.clear();
// The "clean" pass also contains a design->check() call
Pass::call(design, "clean");
log_pop();
}
} Abc9Pass;

View File

@ -66,10 +66,10 @@ struct AigmapPass : public Pass {
{
Aig aig(cell);
if (cell->type == "$_AND_" || cell->type == "$_NOT_")
if (cell->type.in(ID($_AND_), ID($_NOT_)))
aig.name.clear();
if (nand_mode && cell->type == "$_NAND_")
if (nand_mode && cell->type == ID($_NAND_))
aig.name.clear();
if (aig.name.empty()) {

View File

@ -61,7 +61,7 @@ struct AlumaccWorker
RTLIL::SigSpec get_eq() {
if (GetSize(cached_eq) == 0)
cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort("\\X"), false, alu_cell->get_src_attribute());
cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort(ID(X)), false, alu_cell->get_src_attribute());
return cached_eq;
}
@ -73,7 +73,7 @@ struct AlumaccWorker
RTLIL::SigSpec get_cf() {
if (GetSize(cached_cf) == 0) {
cached_cf = alu_cell->getPort("\\CO");
cached_cf = alu_cell->getPort(ID(CO));
log_assert(GetSize(cached_cf) >= 1);
cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[GetSize(cached_cf)-1], false, alu_cell->get_src_attribute());
}
@ -82,7 +82,7 @@ struct AlumaccWorker
RTLIL::SigSpec get_of() {
if (GetSize(cached_of) == 0) {
cached_of = {alu_cell->getPort("\\CO"), alu_cell->getPort("\\CI")};
cached_of = {alu_cell->getPort(ID(CO)), alu_cell->getPort(ID(CI))};
log_assert(GetSize(cached_of) >= 2);
cached_of = alu_cell->module->Xor(NEW_ID, cached_of[GetSize(cached_of)-1], cached_of[GetSize(cached_of)-2]);
}
@ -91,7 +91,7 @@ struct AlumaccWorker
RTLIL::SigSpec get_sf() {
if (GetSize(cached_sf) == 0) {
cached_sf = alu_cell->getPort("\\Y");
cached_sf = alu_cell->getPort(ID::Y);
cached_sf = cached_sf[GetSize(cached_sf)-1];
}
return cached_sf;
@ -125,7 +125,7 @@ struct AlumaccWorker
{
for (auto cell : module->selected_cells())
{
if (!cell->type.in("$pos", "$neg", "$add", "$sub", "$mul"))
if (!cell->type.in(ID($pos), ID($neg), ID($add), ID($sub), ID($mul)))
continue;
log(" creating $macc model for %s (%s).\n", log_id(cell), log_id(cell->type));
@ -134,38 +134,38 @@ struct AlumaccWorker
Macc::port_t new_port;
n->cell = cell;
n->y = sigmap(cell->getPort("\\Y"));
n->y = sigmap(cell->getPort(ID::Y));
n->users = 0;
for (auto bit : n->y)
n->users = max(n->users, bit_users.at(bit) - 1);
if (cell->type.in("$pos", "$neg"))
if (cell->type.in(ID($pos), ID($neg)))
{
new_port.in_a = sigmap(cell->getPort("\\A"));
new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool();
new_port.do_subtract = cell->type == "$neg";
new_port.in_a = sigmap(cell->getPort(ID::A));
new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
new_port.do_subtract = cell->type == ID($neg);
n->macc.ports.push_back(new_port);
}
if (cell->type.in("$add", "$sub"))
if (cell->type.in(ID($add), ID($sub)))
{
new_port.in_a = sigmap(cell->getPort("\\A"));
new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool();
new_port.in_a = sigmap(cell->getPort(ID::A));
new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
new_port.do_subtract = false;
n->macc.ports.push_back(new_port);
new_port.in_a = sigmap(cell->getPort("\\B"));
new_port.is_signed = cell->getParam("\\B_SIGNED").as_bool();
new_port.do_subtract = cell->type == "$sub";
new_port.in_a = sigmap(cell->getPort(ID::B));
new_port.is_signed = cell->getParam(ID(B_SIGNED)).as_bool();
new_port.do_subtract = cell->type == ID($sub);
n->macc.ports.push_back(new_port);
}
if (cell->type.in("$mul"))
if (cell->type.in(ID($mul)))
{
new_port.in_a = sigmap(cell->getPort("\\A"));
new_port.in_b = sigmap(cell->getPort("\\B"));
new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool();
new_port.in_a = sigmap(cell->getPort(ID::A));
new_port.in_b = sigmap(cell->getPort(ID::B));
new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
new_port.do_subtract = false;
n->macc.ports.push_back(new_port);
}
@ -315,7 +315,7 @@ struct AlumaccWorker
}
if (subtract_b)
C.append(RTLIL::S1);
C.append(State::S1);
if (GetSize(C) > 1)
goto next_macc;
@ -351,7 +351,7 @@ struct AlumaccWorker
for (auto &it : sig_macc)
{
auto n = it.second;
auto cell = module->addCell(NEW_ID, "$macc");
auto cell = module->addCell(NEW_ID, ID($macc));
macc_counter++;
@ -361,7 +361,7 @@ struct AlumaccWorker
n->macc.optimize(GetSize(n->y));
n->macc.to_cell(cell);
cell->setPort("\\Y", n->y);
cell->setPort(ID::Y, n->y);
cell->fixup_parameters();
module->remove(n->cell);
delete n;
@ -376,9 +376,9 @@ struct AlumaccWorker
for (auto cell : module->selected_cells())
{
if (cell->type.in("$lt", "$le", "$ge", "$gt"))
if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt)))
lge_cells.push_back(cell);
if (cell->type.in("$eq", "$eqx", "$ne", "$nex"))
if (cell->type.in(ID($eq), ID($eqx), ID($ne), ID($nex)))
eq_cells.push_back(cell);
}
@ -386,13 +386,13 @@ struct AlumaccWorker
{
log(" creating $alu model for %s (%s):", log_id(cell), log_id(cell->type));
bool cmp_less = cell->type.in("$lt", "$le");
bool cmp_equal = cell->type.in("$le", "$ge");
bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
bool cmp_less = cell->type.in(ID($lt), ID($le));
bool cmp_equal = cell->type.in(ID($le), ID($ge));
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
RTLIL::SigSpec A = sigmap(cell->getPort("\\A"));
RTLIL::SigSpec B = sigmap(cell->getPort("\\B"));
RTLIL::SigSpec Y = sigmap(cell->getPort("\\Y"));
RTLIL::SigSpec A = sigmap(cell->getPort(ID::A));
RTLIL::SigSpec B = sigmap(cell->getPort(ID::B));
RTLIL::SigSpec Y = sigmap(cell->getPort(ID::Y));
if (B < A && GetSize(B)) {
cmp_less = !cmp_less;
@ -402,7 +402,7 @@ struct AlumaccWorker
alunode_t *n = nullptr;
for (auto node : sig_alu[RTLIL::SigSig(A, B)])
if (node->is_signed == is_signed && node->invert_b && node->c == RTLIL::S1) {
if (node->is_signed == is_signed && node->invert_b && node->c == State::S1) {
n = node;
break;
}
@ -411,7 +411,7 @@ struct AlumaccWorker
n = new alunode_t;
n->a = A;
n->b = B;
n->c = RTLIL::S1;
n->c = State::S1;
n->y = module->addWire(NEW_ID, max(GetSize(A), GetSize(B)));
n->is_signed = is_signed;
n->invert_b = true;
@ -427,12 +427,12 @@ struct AlumaccWorker
for (auto cell : eq_cells)
{
bool cmp_equal = cell->type.in("$eq", "$eqx");
bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
bool cmp_equal = cell->type.in(ID($eq), ID($eqx));
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
RTLIL::SigSpec A = sigmap(cell->getPort("\\A"));
RTLIL::SigSpec B = sigmap(cell->getPort("\\B"));
RTLIL::SigSpec Y = sigmap(cell->getPort("\\Y"));
RTLIL::SigSpec A = sigmap(cell->getPort(ID::A));
RTLIL::SigSpec B = sigmap(cell->getPort(ID::B));
RTLIL::SigSpec Y = sigmap(cell->getPort(ID::Y));
if (B < A && GetSize(B))
std::swap(A, B);
@ -440,7 +440,7 @@ struct AlumaccWorker
alunode_t *n = nullptr;
for (auto node : sig_alu[RTLIL::SigSig(A, B)])
if (node->is_signed == is_signed && node->invert_b && node->c == RTLIL::S1) {
if (node->is_signed == is_signed && node->invert_b && node->c == State::S1) {
n = node;
break;
}
@ -471,7 +471,7 @@ struct AlumaccWorker
goto delete_node;
}
n->alu_cell = module->addCell(NEW_ID, "$alu");
n->alu_cell = module->addCell(NEW_ID, ID($alu));
alu_counter++;
log(" creating $alu cell for ");
@ -482,13 +482,13 @@ struct AlumaccWorker
if (n->cells.size() > 0)
n->alu_cell->set_src_attribute(n->cells[0]->get_src_attribute());
n->alu_cell->setPort("\\A", n->a);
n->alu_cell->setPort("\\B", n->b);
n->alu_cell->setPort("\\CI", GetSize(n->c) ? n->c : RTLIL::S0);
n->alu_cell->setPort("\\BI", n->invert_b ? RTLIL::S1 : RTLIL::S0);
n->alu_cell->setPort("\\Y", n->y);
n->alu_cell->setPort("\\X", module->addWire(NEW_ID, GetSize(n->y)));
n->alu_cell->setPort("\\CO", module->addWire(NEW_ID, GetSize(n->y)));
n->alu_cell->setPort(ID::A, n->a);
n->alu_cell->setPort(ID::B, n->b);
n->alu_cell->setPort(ID(CI), GetSize(n->c) ? n->c : State::S0);
n->alu_cell->setPort(ID(BI), n->invert_b ? State::S1 : State::S0);
n->alu_cell->setPort(ID::Y, n->y);
n->alu_cell->setPort(ID(X), module->addWire(NEW_ID, GetSize(n->y)));
n->alu_cell->setPort(ID(CO), module->addWire(NEW_ID, GetSize(n->y)));
n->alu_cell->fixup_parameters(n->is_signed, n->is_signed);
for (auto &it : n->cmp)

View File

@ -83,13 +83,13 @@ struct DeminoutPass : public Pass {
for (auto bit : sigmap(conn.second))
bits_used.insert(bit);
if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_", "$tribuf"))
if (conn.first == ID::Y && cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_TBUF_), ID($tribuf)))
{
bool tribuf = (cell->type == "$_TBUF_" || cell->type == "$tribuf");
bool tribuf = cell->type.in(ID($_TBUF_), ID($tribuf));
if (!tribuf) {
for (auto &c : cell->connections()) {
if (!c.first.in("\\A", "\\B"))
if (!c.first.in(ID::A, ID::B))
continue;
for (auto b : sigmap(c.second))
if (b == State::Sz)

Some files were not shown because too many files have changed in this diff Show More