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-system-dev
- libboost-python-dev - libboost-python-dev
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev
env: env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8" - 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 # Latest gcc supported on Travis Linux
- os: linux - os: linux
addons: addons:
@ -74,7 +47,7 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
packages: packages:
- g++-7 - g++-9
- gperf - gperf
- build-essential - build-essential
- bison - bison
@ -92,8 +65,9 @@ matrix:
- libboost-system-dev - libboost-system-dev
- libboost-python-dev - libboost-python-dev
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev
env: 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 # Clang which ships on Trusty Linux
- os: linux - os: linux
@ -121,6 +95,7 @@ matrix:
- libboost-system-dev - libboost-system-dev
- libboost-python-dev - libboost-python-dev
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev
env: env:
- MATRIX_EVAL="CONFIG=clang && CC=clang-3.8 && CXX=clang++-3.8" - MATRIX_EVAL="CONFIG=clang && CC=clang-3.8 && CXX=clang++-3.8"
@ -129,9 +104,9 @@ matrix:
addons: addons:
apt: apt:
sources: sources:
- llvm-toolchain-trusty-5.0 - llvm-toolchain-xenial-8
packages: packages:
- clang-5.0 - clang-8
- gperf - gperf
- build-essential - build-essential
- bison - bison
@ -149,8 +124,9 @@ matrix:
- libboost-system-dev - libboost-system-dev
- libboost-python-dev - libboost-python-dev
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev
env: 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 # # Latest clang on Mac OS X
# - os: osx # - os: osx

View File

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

View File

@ -51,7 +51,7 @@ fi
git clone git://github.com/steveicarus/iverilog.git git clone git://github.com/steveicarus/iverilog.git
cd iverilog cd iverilog
autoconf autoconf
./configure --prefix=$HOME/.local-bin CC=gcc CXX=g++ ./configure --prefix=$HOME/.local-bin
make make
make install make install
echo 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/options in synth_ecp5 (e.g. dram -> map_lutram; -nodram -> -nolutram)
- Renamed labels in synth_intel (e.g. bram -> map_bram) - Renamed labels in synth_intel (e.g. bram -> map_bram)
- Renamed labels/options in synth_xilinx (e.g. dram -> map_lutram; -nodram -> -nolutram) - 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 Yosys 0.8 .. Yosys 0.8-dev
-------------------------- --------------------------

View File

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

View File

@ -19,6 +19,7 @@ ENABLE_VERIFIC := 0
ENABLE_COVER := 1 ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0 ENABLE_LIBYOSYS := 0
ENABLE_PROTOBUF := 0 ENABLE_PROTOBUF := 0
ENABLE_ZLIB := 1
# python wrappers # python wrappers
ENABLE_PYOSYS := 0 ENABLE_PYOSYS := 0
@ -260,7 +261,8 @@ CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS)) LDLIBS := $(filter-out -lrt,$(LDLIBS))
ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w" 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 EXE = .exe
else ifeq ($(CONFIG),msys2) else ifeq ($(CONFIG),msys2)
@ -384,6 +386,12 @@ ifeq ($(ENABLE_GLOB),1)
CXXFLAGS += -DYOSYS_ENABLE_GLOB CXXFLAGS += -DYOSYS_ENABLE_GLOB
endif endif
ifeq ($(ENABLE_ZLIB),1)
CXXFLAGS += -DYOSYS_ENABLE_ZLIB
LDLIBS += -lz
endif
ifeq ($(ENABLE_TCL),1) ifeq ($(ENABLE_TCL),1)
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')") TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
ifeq ($(OS), FreeBSD) ifeq ($(OS), FreeBSD)
@ -394,7 +402,7 @@ endif
ifeq ($(CONFIG),mxe) ifeq ($(CONFIG),mxe)
CXXFLAGS += -DYOSYS_ENABLE_TCL CXXFLAGS += -DYOSYS_ENABLE_TCL
LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz -luserenv
else else
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
ifeq ($(OS), FreeBSD) ifeq ($(OS), FreeBSD)
@ -674,10 +682,12 @@ endif
test: $(TARGETS) $(EXTRA_TARGETS) test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/simple && bash run-test.sh $(SEEDOPT) +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/hana && bash run-test.sh $(SEEDOPT)
+cd tests/asicworld && bash run-test.sh $(SEEDOPT) +cd tests/asicworld && bash run-test.sh $(SEEDOPT)
# +cd tests/realmath && bash run-test.sh $(SEEDOPT) # +cd tests/realmath && bash run-test.sh $(SEEDOPT)
+cd tests/share && 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/fsm && bash run-test.sh $(SEEDOPT)
+cd tests/techmap && bash run-test.sh +cd tests/techmap && bash run-test.sh
+cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT) +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/opt && bash run-test.sh
+cd tests/aiger && bash run-test.sh $(ABCOPT) +cd tests/aiger && bash run-test.sh $(ABCOPT)
+cd tests/arch && bash run-test.sh +cd tests/arch && bash run-test.sh
+cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT)
@echo "" @echo ""
@echo " Passed \"make test\"." @echo " Passed \"make test\"."
@echo "" @echo ""
@ -773,7 +782,7 @@ clean:
rm -rf kernel/*.pyh rm -rf kernel/*.pyh
if test -d manual; then cd manual && sh clean.sh; fi 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 $(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 -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d
rm -rf tests/asicworld/*.out tests/asicworld/*.log rm -rf tests/asicworld/*.out tests/asicworld/*.log
rm -rf tests/hana/*.out tests/hana/*.log rm -rf tests/hana/*.out tests/hana/*.log
@ -862,9 +871,11 @@ config-mxe: clean
config-msys2: clean config-msys2: clean
echo 'CONFIG := msys2' > Makefile.conf echo 'CONFIG := msys2' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-msys2-64: clean config-msys2-64: clean
echo 'CONFIG := msys2-64' > Makefile.conf echo 'CONFIG := msys2-64' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-cygwin: clean config-cygwin: clean
echo 'CONFIG := cygwin' > Makefile.conf echo 'CONFIG := cygwin' > Makefile.conf

View File

@ -67,13 +67,13 @@ prerequisites for building yosys:
$ sudo apt-get install build-essential clang bison flex \ $ sudo apt-get install build-essential clang bison flex \
libreadline-dev gawk tcl-dev libffi-dev git \ libreadline-dev gawk tcl-dev libffi-dev git \
graphviz xdot pkg-config python3 libboost-system-dev \ 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: Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies:
$ brew tap Homebrew/bundle && brew bundle $ brew tap Homebrew/bundle && brew bundle
$ sudo port install bison flex readline gawk libffi \ $ 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: 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: 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 There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well
as a source distribution for Visual Studio. Visit the Yosys download page for as a source distribution for Visual Studio. Visit the Yosys download page for
@ -130,18 +130,15 @@ commands and ``help <command>`` to print details on the specified command:
yosys> help help 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: writing the design to the console in Yosys's internal format:
yosys> write_ilang yosys> write_ilang
elaborate design hierarchy:
yosys> hierarchy
convert processes (``always`` blocks) to netlist elements and perform convert processes (``always`` blocks) to netlist elements and perform
some simple optimizations: some simple optimizations:
@ -163,51 +160,26 @@ write design netlist to a new Verilog file:
yosys> write_verilog synth.v 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: or using a simple synthesis script:
$ cat synth.ys $ cat synth.ys
read_verilog tests/simple/fiedler-cooley.v read -sv tests/simple/fiedler-cooley.v
hierarchy; proc; opt; techmap; opt hierarchy -top up3down5
proc; opt; techmap; opt
write_verilog synth.v write_verilog synth.v
$ ./yosys synth.ys $ ./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 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 in the liberty file ``mycells.lib``, the following synthesis script will
synthesize for the given cell library: synthesize for the given cell library:
# read design
read -sv tests/simple/fiedler-cooley.v
hierarchy -top up3down5
# the high-level stuff # the high-level stuff
hierarchy; proc; fsm; opt; memory; opt proc; fsm; opt; memory; opt
# mapping to internal cell library # mapping to internal cell library
techmap; opt techmap; opt
@ -222,7 +194,8 @@ synthesize for the given cell library:
clean clean
If you do not have a liberty file but want to test this synthesis script, 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 Liberty file downloads for and information about free and open ASIC standard
cell libraries can be found here: cell libraries can be found here:
@ -231,20 +204,18 @@ cell libraries can be found here:
- http://www.vlsitechnology.org/synopsys/vsclib013.lib - http://www.vlsitechnology.org/synopsys/vsclib013.lib
The command ``synth`` provides a good default synthesis script (see The command ``synth`` provides a good default synthesis script (see
``help synth``). If possible a synthesis script should borrow from ``synth``. ``help synth``):
For example:
# the high-level stuff read -sv tests/simple/fiedler-cooley.v
hierarchy synth -top up3down5
synth -run coarse
# mapping to internal cells # mapping to target cells
techmap; opt -fast
dfflibmap -liberty mycells.lib dfflibmap -liberty mycells.lib
abc -liberty mycells.lib abc -liberty mycells.lib
clean 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 Unsupported Verilog-2005 Features

View File

@ -53,7 +53,7 @@ PRIVATE_NAMESPACE_BEGIN
inline int32_t to_big_endian(int32_t i32) { inline int32_t to_big_endian(int32_t i32) {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return __builtin_bswap32(i32); return bswap32(i32);
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
return i32; return i32;
#else #else
@ -312,7 +312,7 @@ struct XAigerWriter
#if 0 #if 0
toposort.analyze_loops = true; toposort.analyze_loops = true;
#endif #endif
bool no_loops = toposort.sort(); bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
#if 0 #if 0
unsigned i = 0; unsigned i = 0;
for (auto &it : toposort.loops) { for (auto &it : toposort.loops) {
@ -388,11 +388,11 @@ struct XAigerWriter
RTLIL::SigSpec rhs; RTLIL::SigSpec rhs;
if (it != cell->connections_.end()) { if (it != cell->connections_.end()) {
if (GetSize(it->second) < GetSize(w)) 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; rhs = it->second;
} }
else { else {
rhs = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); rhs = RTLIL::SigSpec(State::S0, GetSize(w));
cell->setPort(port_name, rhs); cell->setPort(port_name, rhs);
} }
@ -400,10 +400,10 @@ struct XAigerWriter
for (auto b : rhs.bits()) { for (auto b : rhs.bits()) {
SigBit I = sigmap(b); SigBit I = sigmap(b);
if (b == RTLIL::Sx) if (b == RTLIL::Sx)
b = RTLIL::S0; b = State::S0;
else if (I != b) { else if (I != b) {
if (I == RTLIL::Sx) if (I == RTLIL::Sx)
alias_map[b] = RTLIL::S0; alias_map[b] = State::S0;
else else
alias_map[b] = I; alias_map[b] = I;
} }
@ -610,19 +610,18 @@ struct XAigerWriter
std::stringstream h_buffer; std::stringstream h_buffer;
auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1);
write_h_buffer(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()); 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()); 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()); 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()); 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()); write_h_buffer(box_list.size());
RTLIL::Module *holes_module = nullptr; RTLIL::Module *holes_module = module->design->addModule("$__holes__");
holes_module = module->design->addModule("$__holes__");
log_assert(holes_module); log_assert(holes_module);
int port_id = 1; int port_id = 1;
@ -672,7 +671,7 @@ struct XAigerWriter
if (holes_cell) if (holes_cell)
port_wire.append(holes_wire); port_wire.append(holes_wire);
else else
holes_module->connect(holes_wire, RTLIL::S0); holes_module->connect(holes_wire, State::S0);
} }
if (!port_wire.empty()) if (!port_wire.empty())
holes_cell->setPort(w->name, port_wire); holes_cell->setPort(w->name, port_wire);
@ -719,27 +718,33 @@ struct XAigerWriter
Pass::call(holes_module->design, "flatten -wb"); Pass::call(holes_module->design, "flatten -wb");
// TODO: Should techmap/aigmap/check all lib_whitebox-es just once, // 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, "techmap");
Pass::call(holes_module->design, "aigmap"); Pass::call(holes_module->design, "aigmap");
for (auto cell : holes_module->cells()) for (auto cell : holes_module->cells())
if (!cell->type.in("$_NOT_", "$_AND_")) if (!cell->type.in("$_NOT_", "$_AND_"))
log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); 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; std::stringstream a_buffer;
XAigerWriter writer(holes_module, true /* holes_mode */); XAigerWriter writer(holes_module, true /* holes_mode */);
writer.write_aiger(a_buffer, false /*ascii_mode*/); writer.write_aiger(a_buffer, false /*ascii_mode*/);
holes_module->design->selection_stack.pop_back(); delete holes_design;
f << "a"; f << "a";
std::string buffer_str = a_buffer.str(); std::string buffer_str = a_buffer.str();
int32_t buffer_size_be = to_big_endian(buffer_str.size()); 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(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
f.write(buffer_str.data(), buffer_str.size()); f.write(buffer_str.data(), buffer_str.size());
holes_module->design->remove(holes_module);
log_pop(); log_pop();
} }
@ -772,7 +777,7 @@ struct XAigerWriter
if (output_bits.count(b)) { if (output_bits.count(b)) {
int o = ordered_outputs.at(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; continue;
} }

View File

@ -327,6 +327,13 @@ struct BlifDumper
goto internal_cell; 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_") { if (!config->icells_mode && cell->type == "$_FF_") {
f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr_init(cell->getPort("\\Q"))); cstr_init(cell->getPort("\\Q")));
@ -370,7 +377,7 @@ struct BlifDumper
f << stringf("\n"); f << stringf("\n");
RTLIL::SigSpec mask = cell->parameters.at("\\LUT"); RTLIL::SigSpec mask = cell->parameters.at("\\LUT");
for (int i = 0; i < (1 << width); i++) 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--) { for (int j = width-1; j >= 0; j--) {
f << ((i>>j)&1 ? '1' : '0'); f << ((i>>j)&1 ? '1' : '0');
} }

View File

@ -496,7 +496,7 @@ struct BtorWorker
goto okay; goto okay;
} }
if (cell->type.in("$mux", "$_MUX_")) if (cell->type.in("$mux", "$_MUX_", "$_NMUX_"))
{ {
SigSpec sig_a = sigmap(cell->getPort("\\A")); SigSpec sig_a = sigmap(cell->getPort("\\A"));
SigSpec sig_b = sigmap(cell->getPort("\\B")); SigSpec sig_b = sigmap(cell->getPort("\\B"));
@ -511,6 +511,12 @@ struct BtorWorker
int nid = next_nid++; int nid = next_nid++;
btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a); 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); add_nid_sig(nid, sig_y);
goto okay; goto okay;
} }
@ -610,8 +616,8 @@ struct BtorWorker
if (initstate_nid < 0) if (initstate_nid < 0)
{ {
int sid = get_bv_sid(1); int sid = get_bv_sid(1);
int one_nid = get_sig_nid(Const(1, 1)); int one_nid = get_sig_nid(State::S1);
int zero_nid = get_sig_nid(Const(0, 1)); int zero_nid = get_sig_nid(State::S0);
initstate_nid = next_nid++; initstate_nid = next_nid++;
btorf("%d state %d\n", initstate_nid, sid); btorf("%d state %d\n", initstate_nid, sid);
btorf("%d init %d %d %d\n", next_nid++, sid, initstate_nid, one_nid); 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: // Current (3/13/2019) conventions:
// generate a constant 0 for clock and a constant 1 for enable if they are undefined. // generate a constant 0 for clock and a constant 1 for enable if they are undefined.
if (!clk.is_fully_def()) if (!clk.is_fully_def())
this->clk = SigSpec(RTLIL::Const(0, 1)); this->clk = SigSpec(State::S0);
if (!ena.is_fully_def()) if (!ena.is_fully_def())
this->ena = SigSpec(RTLIL::Const(1, 1)); this->ena = SigSpec(State::S1);
} }
string gen_read(const char * indent) { string gen_read(const char * indent) {
string addr_expr = make_expr(addr); string addr_expr = make_expr(addr);
@ -297,7 +297,7 @@ struct FirrtlWorker
std::string cell_type = fid(cell->type); std::string cell_type = fid(cell->type);
std::string instanceOf; std::string instanceOf;
// If this is a parameterized module, its parent module is encoded in the cell type // 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; std::string::iterator it;
for (it = cell_type.begin(); it < cell_type.end(); it++) for (it = cell_type.begin(); it < cell_type.end(); it++)
@ -363,7 +363,7 @@ struct FirrtlWorker
} }
// Check for subfield assignment. // Check for subfield assignment.
std::string bitsString = "bits("; std::string bitsString = "bits(";
if (sinkExpr.substr(0, bitsString.length()) == bitsString ) { if (sinkExpr.compare(0, bitsString.length(), bitsString) == 0) {
if (sinkSig == nullptr) if (sinkSig == nullptr)
log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str()); log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str());
// Don't generate the assignment here. // Don't generate the assignment here.
@ -381,10 +381,10 @@ struct FirrtlWorker
// Given an expression for a shift amount, and a maximum width, // 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. // 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; 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; 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); 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 // Deal with the difference in semantics between FIRRTL and verilog
@ -422,22 +422,33 @@ struct FirrtlWorker
for (auto cell : module->cells()) 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? // Is this cell is a module instance?
if (cell->type[0] != '$') if (cell->type[0] != '$')
{ {
process_instance(cell, wire_exprs); process_instance(cell, wire_exprs);
continue; 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")) 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")); string a_expr = make_expr(cell->getPort("\\A"));
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); 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 + ")"; a_expr = "asSInt(" + a_expr + ")";
} }
@ -446,12 +457,13 @@ struct FirrtlWorker
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
} }
string primop; // Assume the FIRRTL width is a single bit.
bool always_uint = false; firrtl_width = 1;
if (cell->type == "$not") primop = "not"; if (cell->type == "$not") primop = "not";
else if (cell->type == "$neg") { else if (cell->type == "$neg") {
primop = "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") { } else if (cell->type == "$logic_not") {
primop = "eq"; primop = "eq";
a_expr = stringf("%s, UInt(0)", a_expr.c_str()); a_expr = stringf("%s, UInt(0)", a_expr.c_str());
@ -466,14 +478,12 @@ struct FirrtlWorker
else if (cell->type == "$reduce_bool") { else if (cell->type == "$reduce_bool") {
primop = "neq"; primop = "neq";
// Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand. // 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); 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()); 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()); expr = stringf("asUInt(%s)", expr.c_str());
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), 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; 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", "$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 a_expr = make_expr(cell->getPort("\\A"));
string b_expr = make_expr(cell->getPort("\\B")); 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)); 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 + ")"; a_expr = "asSInt(" + a_expr + ")";
} // Expand the "A" operand to the result width
// Shift amount is always unsigned, and needn't be padded to result width. if (a_width < y_width) {
if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) { a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
if (cell->parameters.at("\\B_SIGNED").as_bool()) { a_width = y_width;
b_expr = "asSInt(" + b_expr + ")";
} }
if (b_padded_width < y_width) { }
auto b_sig = cell->getPort("\\B"); // Shift amount is always unsigned, and needn't be padded to result width,
b_padded_width = y_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"); auto a_sig = cell->getPort("\\A");
if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) { if (cell->type == "$add") {
a_expr = "asUInt(" + a_expr + ")"; 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" ) { else if (cell->type == "$or" ) {
primop = "or"; primop = "or";
always_uint = true; always_uint = true;
} firrtl_width = max(a_width, b_width);
}
else if (cell->type == "$xor") { else if (cell->type == "$xor") {
primop = "xor"; primop = "xor";
always_uint = true; 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")) { else if ((cell->type == "$eq") | (cell->type == "$eqx")) {
primop = "eq"; primop = "eq";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if ((cell->type == "$ne") | (cell->type == "$nex")) { else if ((cell->type == "$ne") | (cell->type == "$nex")) {
primop = "neq"; primop = "neq";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if (cell->type == "$gt") { else if (cell->type == "$gt") {
primop = "gt"; primop = "gt";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if (cell->type == "$ge") { else if (cell->type == "$ge") {
primop = "geq"; primop = "geq";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if (cell->type == "$lt") { else if (cell->type == "$lt") {
primop = "lt"; primop = "lt";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if (cell->type == "$le") { else if (cell->type == "$le") {
primop = "leq"; primop = "leq";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if ((cell->type == "$shl") | (cell->type == "$sshl")) { else if ((cell->type == "$shl") | (cell->type == "$sshl")) {
// FIRRTL will widen the result (y) by the amount of the shift. // 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. // 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"); auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) { if (b_sig.is_fully_const()) {
primop = "shl"; 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 { } else {
primop = "dshl"; primop = "dshl";
// Convert from FIRRTL left shift semantics. // 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")) { else if ((cell->type == "$shr") | (cell->type == "$sshr")) {
@ -578,36 +631,86 @@ struct FirrtlWorker
auto b_sig = cell->getPort("\\B"); auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) { if (b_sig.is_fully_const()) {
primop = "shr"; 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 { } else {
primop = "dshr"; 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")) { else if ((cell->type == "$logic_and")) {
primop = "and"; primop = "and";
a_expr = "neq(" + a_expr + ", UInt(0))"; a_expr = "neq(" + a_expr + ", UInt(0))";
b_expr = "neq(" + b_expr + ", UInt(0))"; b_expr = "neq(" + b_expr + ", UInt(0))";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if ((cell->type == "$logic_or")) { else if ((cell->type == "$logic_or")) {
primop = "or"; primop = "or";
a_expr = "neq(" + a_expr + ", UInt(0))"; a_expr = "neq(" + a_expr + ", UInt(0))";
b_expr = "neq(" + b_expr + ", UInt(0))"; b_expr = "neq(" + b_expr + ", UInt(0))";
always_uint = true; 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()) { if (!cell->parameters.at("\\B_SIGNED").as_bool()) {
b_expr = "asUInt(" + b_expr + ")"; b_expr = "asUInt(" + b_expr + ")";
} }
string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str()); string expr;
// Deal with $xnor == ~^ (not xor)
// Deal with FIRRTL's "shift widens" semantics if (primop == "xnor") {
if (extract_y_bits) { expr = stringf("not(xor(%s, %s))", a_expr.c_str(), b_expr.c_str());
expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1); } 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()); expr = stringf("asUInt(%s)", expr.c_str());
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), 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")) if (cell->type.in("$mux"))
{ {
string y_id = make_id(cell->name);
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at("\\WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A")); string a_expr = make_expr(cell->getPort("\\A"));
string b_expr = make_expr(cell->getPort("\\B")); string b_expr = make_expr(cell->getPort("\\B"));
@ -762,21 +864,20 @@ struct FirrtlWorker
if (clkpol == false) if (clkpol == false)
log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell)); 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(); int width = cell->parameters.at("\\WIDTH").as_int();
string expr = make_expr(cell->getPort("\\D")); string expr = make_expr(cell->getPort("\\D"));
string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")"; 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())); cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
register_reverse_wire_map(q_id, cell->getPort("\\Q")); register_reverse_wire_map(y_id, cell->getPort("\\Q"));
continue; continue;
} }
// This may be a parameterized module - paramod. // 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); process_instance(cell, wire_exprs);
continue; continue;
@ -785,8 +886,6 @@ struct FirrtlWorker
// assign y = a[b +: y_width]; // assign y = a[b +: y_width];
// We'll extract the correct bits as part of the primop. // 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")); string a_expr = make_expr(cell->getPort("\\A"));
// Get the initial bit selector // Get the initial bit selector
string b_expr = make_expr(cell->getPort("\\B")); string b_expr = make_expr(cell->getPort("\\B"));
@ -808,18 +907,15 @@ struct FirrtlWorker
// assign y = a >> b; // assign y = a >> b;
// where b may be negative // 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 a_expr = make_expr(cell->getPort("\\A"));
string b_expr = make_expr(cell->getPort("\\B")); string b_expr = make_expr(cell->getPort("\\B"));
auto b_string = b_expr.c_str(); auto b_string = b_expr.c_str();
int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int();
string expr; string expr;
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
if (cell->getParam("\\B_SIGNED").as_bool()) { if (cell->getParam("\\B_SIGNED").as_bool()) {
// We generate a left or right shift based on the sign of b. // 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); std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string);
expr = stringf("mux(%s < 0, %s, %s)", expr = stringf("mux(%s < 0, %s, %s)",
b_string, b_string,
@ -833,7 +929,21 @@ struct FirrtlWorker
register_reverse_wire_map(y_id, cell->getPort("\\Y")); register_reverse_wire_map(y_id, cell->getPort("\\Y"));
continue; 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()) 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++) { for (int i = 0; i < width; i++) {
log_assert(offset+i < (int)data.bits.size()); log_assert(offset+i < (int)data.bits.size());
switch (data.bits[offset+i]) { switch (data.bits[offset+i]) {
case RTLIL::S0: break; case State::S0: break;
case RTLIL::S1: val |= 1 << i; break; case State::S1: val |= 1 << i; break;
default: val = -1; 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--) { for (int i = offset+width-1; i >= offset; i--) {
log_assert(i < (int)data.bits.size()); log_assert(i < (int)data.bits.size());
switch (data.bits[i]) { switch (data.bits[i]) {
case RTLIL::S0: f << stringf("0"); break; case State::S0: f << stringf("0"); break;
case RTLIL::S1: f << stringf("1"); break; case State::S1: f << stringf("1"); break;
case RTLIL::Sx: f << stringf("x"); break; case RTLIL::Sx: f << stringf("x"); break;
case RTLIL::Sz: f << stringf("z"); break; case RTLIL::Sz: f << stringf("z"); break;
case RTLIL::Sa: f << stringf("-"); break; case RTLIL::Sa: f << stringf("-"); break;

View File

@ -108,7 +108,7 @@ struct IntersynthBackend : public Backend {
if (f.fail()) if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str()); log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design; 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); libs.push_back(lib);
} }
@ -183,7 +183,7 @@ struct IntersynthBackend : public Backend {
if (param.second.bits.size() != 32) { if (param.second.bits.size() != 32) {
node_code += stringf(" %s '", RTLIL::id2cstr(param.first)); node_code += stringf(" %s '", RTLIL::id2cstr(param.first));
for (int i = param.second.bits.size()-1; i >= 0; i--) 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 } else
node_code += stringf(" %s 0x%x", RTLIL::id2cstr(param.first), param.second.as_int()); node_code += stringf(" %s 0x%x", RTLIL::id2cstr(param.first), param.second.as_int());
} }

View File

@ -83,20 +83,43 @@ struct JsonWriter
return str + " ]"; 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) void write_parameters(const dict<IdString, Const> &parameters, bool for_module=false)
{ {
bool first = true; bool first = true;
for (auto &param : parameters) { for (auto &param : parameters) {
f << stringf("%s\n", first ? "" : ","); f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str()); f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str());
if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) write_parameter_value(param.second);
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());
first = false; 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("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("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("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("connected to a constant driver are denoted as string \"0\", \"1\", \"x\", or\n");
log("a number.\n"); log("\"z\" instead of a number.\n");
log("\n"); log("\n");
log("Numeric parameter and attribute values up to 32 bits are written as decimal\n"); log("Numeric 32-bit parameter and attribute values are written as decimal values.\n");
log("values. Numbers larger than that are written as string holding the binary\n"); log("Bit verctors of different sizes, or ones containing 'x' or 'z' bits, are written\n");
log("representation of the value.\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("\n");
log("For example the following Verilog code:\n"); log("For example the following Verilog code:\n");
log("\n"); log("\n");

View File

@ -472,7 +472,7 @@ struct SimplecWorker
return; return;
} }
if (cell->type == "$_MUX_") if (cell->type.in("$_MUX_", "$_NMUX_"))
{ {
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); 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"; 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) // 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); log_assert(y.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + 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 == "$_ANDNOT_") return export_gate(cell, "(and A (not B))");
if (cell->type == "$_ORNOT_") return export_gate(cell, "(or 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 == "$_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 == "$_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 == "$_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)))"); 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_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 == "$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")); int width = GetSize(cell->getPort("\\Y"));
std::string processed_expr = get_bv(cell->getPort("\\A")); std::string processed_expr = get_bv(cell->getPort("\\A"));
@ -1475,7 +1476,7 @@ struct Smt2Backend : public Backend {
int indent = 0; int indent = 0;
while (indent < GetSize(line) && (line[indent] == ' ' || line[indent] == '\t')) while (indent < GetSize(line) && (line[indent] == ' ' || line[indent] == '\t'))
indent++; indent++;
if (line.substr(indent, 2) == "%%") if (line.compare(indent, 2, "%%") == 0)
break; break;
*f << line << std::endl; *f << line << std::endl;
} }

View File

@ -61,7 +61,7 @@ struct SmvWorker
{ {
string name = stringf("_%s", id.c_str()); string name = stringf("_%s", id.c_str());
if (name.substr(0, 2) == "_\\") if (name.compare(0, 2, "_\\") == 0)
name = "_" + name.substr(2); name = "_" + name.substr(2);
for (auto &c : name) { for (auto &c : name) {
@ -537,6 +537,13 @@ struct SmvWorker
continue; 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_") if (cell->type == "$_AOI3_")
{ {
definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), 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; int32_t val = 0;
for (int i = offset+width-1; i >= offset; i--) { for (int i = offset+width-1; i >= offset; i--) {
log_assert(i < (int)data.bits.size()); 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; goto dump_hex;
if (data.bits[i] == RTLIL::S1) if (data.bits[i] == State::S1)
val |= 1 << (i - offset); val |= 1 << (i - offset);
} }
if (decimal) 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++) { for (int i = offset; i < offset+width; i++) {
log_assert(i < (int)data.bits.size()); log_assert(i < (int)data.bits.size());
switch (data.bits[i]) { switch (data.bits[i]) {
case RTLIL::S0: bin_digits.push_back('0'); break; case State::S0: bin_digits.push_back('0'); break;
case RTLIL::S1: bin_digits.push_back('1'); break; case State::S1: bin_digits.push_back('1'); break;
case RTLIL::Sx: bin_digits.push_back('x'); break; case RTLIL::Sx: bin_digits.push_back('x'); break;
case RTLIL::Sz: bin_digits.push_back('z'); break; case RTLIL::Sz: bin_digits.push_back('z'); break;
case RTLIL::Sa: bin_digits.push_back('?'); 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--) { for (int i = offset+width-1; i >= offset; i--) {
log_assert(i < (int)data.bits.size()); log_assert(i < (int)data.bits.size());
switch (data.bits[i]) { switch (data.bits[i]) {
case RTLIL::S0: f << stringf("0"); break; case State::S0: f << stringf("0"); break;
case RTLIL::S1: f << stringf("1"); break; case State::S1: f << stringf("1"); break;
case RTLIL::Sx: f << stringf("x"); break; case RTLIL::Sx: f << stringf("x"); break;
case RTLIL::Sz: f << stringf("z"); break; case RTLIL::Sz: f << stringf("z"); break;
case RTLIL::Sa: f << stringf("?"); 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) { 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("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str());
f << stringf(" = "); 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 "); 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 "); f << stringf(" 1 ");
else else
dump_const(f, it->second, -1, 0, false, as_comment); 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; 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_")) { if (cell->type.in("$_AOI3_", "$_OAI3_")) {
f << stringf("%s" "assign ", indent.c_str()); f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, cell->getPort("\\Y")); 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; return true;
} }
if (cell->type.substr(0, 6) == "$_DFF_") if (cell->type.begins_with("$_DFF_"))
{ {
std::string reg_name = cellname(cell); std::string reg_name = cellname(cell);
bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); 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; 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]; 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; 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; RTLIL::SigSpec sig_clk, sig_arst, sig_en, val_arst;
bool pol_clk, pol_arst = false, pol_en = false; 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> #include <libkern/OSByteOrder.h>
#define __builtin_bswap32 OSSwapInt32 #define __builtin_bswap32 OSSwapInt32
#endif #endif
#define __STDC_FORMAT_MACROS
#include <inttypes.h> #include <inttypes.h>
#include "kernel/yosys.h" #include "kernel/yosys.h"
@ -66,7 +67,7 @@ struct ConstEvalAig
continue; continue;
for (auto &it2 : it.second->connections()) for (auto &it2 : it.second->connections())
if (yosys_celltypes.cell_output(it.second->type, it2.first)) { 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); log_assert(r.second);
} }
} }
@ -151,12 +152,12 @@ struct ConstEvalAig
RTLIL::State eval_ret = RTLIL::Sx; RTLIL::State eval_ret = RTLIL::Sx;
if (cell->type == "$_NOT_") { if (cell->type == "$_NOT_") {
if (sig_a == RTLIL::S0) eval_ret = RTLIL::S1; if (sig_a == State::S0) eval_ret = State::S1;
else if (sig_a == RTLIL::S1) eval_ret = RTLIL::S0; else if (sig_a == State::S1) eval_ret = State::S0;
} }
else if (cell->type == "$_AND_") { else if (cell->type == "$_AND_") {
if (sig_a == RTLIL::S0) { if (sig_a == State::S0) {
eval_ret = RTLIL::S0; eval_ret = State::S0;
goto eval_end; goto eval_end;
} }
@ -164,15 +165,15 @@ struct ConstEvalAig
RTLIL::SigBit sig_b = cell->getPort("\\B"); RTLIL::SigBit sig_b = cell->getPort("\\B");
if (!eval(sig_b)) if (!eval(sig_b))
return false; return false;
if (sig_b == RTLIL::S0) { if (sig_b == State::S0) {
eval_ret = RTLIL::S0; eval_ret = State::S0;
goto eval_end; goto eval_end;
} }
if (sig_a != RTLIL::S1 || sig_b != RTLIL::S1) if (sig_a != State::S1 || sig_b != State::S1)
goto eval_end; goto eval_end;
eval_ret = RTLIL::S1; eval_ret = State::S1;
} }
} }
else log_abort(); else log_abort();
@ -256,7 +257,7 @@ end_of_header:
RTLIL::Wire* n0 = module->wire("\\__0__"); RTLIL::Wire* n0 = module->wire("\\__0__");
if (n0) if (n0)
module->connect(n0, RTLIL::S0); module->connect(n0, State::S0);
// Parse footer (symbol table, comments, etc.) // Parse footer (symbol table, comments, etc.)
unsigned l1; unsigned l1;
@ -301,7 +302,11 @@ static uint32_t parse_xaiger_literal(std::istream &f)
uint32_t l; uint32_t l;
f.read(reinterpret_cast<char*>(&l), sizeof(l)); f.read(reinterpret_cast<char*>(&l), sizeof(l));
if (f.gcount() != 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())); log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast<int64_t>(f.tellg()));
#endif
return from_big_endian(l); return from_big_endian(l);
} }
@ -333,7 +338,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera
return wire; return wire;
} }
void AigerReader::parse_xaiger() void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
{ {
std::string header; std::string header;
f >> header; f >> header;
@ -367,22 +372,7 @@ void AigerReader::parse_xaiger()
RTLIL::Wire* n0 = module->wire("\\__0__"); RTLIL::Wire* n0 = module->wire("\\__0__");
if (n0) if (n0)
module->connect(n0, RTLIL::S0); module->connect(n0, State::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);
}
// Parse footer (symbol table, comments, etc.) // Parse footer (symbol table, comments, etc.)
std::string s; std::string s;
@ -399,9 +389,9 @@ void AigerReader::parse_xaiger()
f.ignore(1); f.ignore(1);
// XAIGER extensions // XAIGER extensions
if (c == 'm') { 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 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); log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize);
ConstEvalAig ce(module); ConstEvalAig ce(module);
for (unsigned i = 0; i < lutNum; ++i) { for (unsigned i = 0; i < lutNum; ++i) {
@ -426,7 +416,7 @@ void AigerReader::parse_xaiger()
int gray = j ^ (j >> 1); int gray = j ^ (j >> 1);
ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast<int>(cutLeavesM)}); ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast<int>(cutLeavesM)});
RTLIL::SigBit o(output_sig); RTLIL::SigBit o(output_sig);
bool success = ce.eval(o); bool success YS_ATTRIBUTE(unused) = ce.eval(o);
log_assert(success); log_assert(success);
log_assert(o.wire == nullptr); log_assert(o.wire == nullptr);
lut_mask[gray] = o.data; lut_mask[gray] = o.data;
@ -438,7 +428,7 @@ void AigerReader::parse_xaiger()
} }
} }
else if (c == 'r') { 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); flopNum = parse_xaiger_literal(f);
log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
f.ignore(flopNum * sizeof(uint32_t)); f.ignore(flopNum * sizeof(uint32_t));
@ -450,18 +440,18 @@ void AigerReader::parse_xaiger()
} }
else if (c == 'h') { else if (c == 'h') {
f.ignore(sizeof(uint32_t)); 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); 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); 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); log_debug("coNum = %u\n", coNum);
piNum = parse_xaiger_literal(f); piNum = parse_xaiger_literal(f);
log_debug("piNum = %u\n", piNum); 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); log_debug("poNum = %u\n", poNum);
uint32_t boxNum = parse_xaiger_literal(f); 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++) { for (unsigned i = 0; i < boxNum; i++) {
f.ignore(2*sizeof(uint32_t)); f.ignore(2*sizeof(uint32_t));
uint32_t boxUniqueId = parse_xaiger_literal(f); 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); log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0) if (l3 == 0)
q_wire->attributes["\\init"] = RTLIL::S0; q_wire->attributes["\\init"] = State::S0;
else if (l3 == 1) else if (l3 == 1)
q_wire->attributes["\\init"] = RTLIL::S1; q_wire->attributes["\\init"] = State::S1;
else if (l3 == l1) { else if (l3 == l1) {
//q_wire->attributes["\\init"] = RTLIL::Sx; //q_wire->attributes["\\init"] = RTLIL::Sx;
} }
@ -542,7 +532,7 @@ void AigerReader::parse_aiger_ascii()
} }
else { else {
// AIGER latches are assumed to be initialized to zero // 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); 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); log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0) if (l3 == 0)
q_wire->attributes["\\init"] = RTLIL::S0; q_wire->attributes["\\init"] = State::S0;
else if (l3 == 1) else if (l3 == 1)
q_wire->attributes["\\init"] = RTLIL::S1; q_wire->attributes["\\init"] = State::S1;
else if (l3 == l1) { else if (l3 == l1) {
//q_wire->attributes["\\init"] = RTLIL::Sx; //q_wire->attributes["\\init"] = RTLIL::Sx;
} }
@ -667,7 +657,7 @@ void AigerReader::parse_aiger_binary()
} }
else { else {
// AIGER latches are assumed to be initialized to zero // 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); latches.push_back(q_wire);
} }
@ -911,9 +901,6 @@ void AigerReader::post_process()
RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable));
if (cell) { // ABC could have optimised this box away if (cell) { // ABC could have optimised this box away
module->rename(cell, escaped_s); module->rename(cell, escaped_s);
RTLIL::Module* box_module = design->module(cell->type);
log_assert(box_module);
for (const auto &i : cell->connections()) { for (const auto &i : cell->connections()) {
RTLIL::IdString port_name = i.first; RTLIL::IdString port_name = i.first;
RTLIL::SigSpec rhs = i.second; RTLIL::SigSpec rhs = i.second;
@ -982,16 +969,17 @@ void AigerReader::post_process()
} }
module->fixup_ports(); 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->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()) { for (auto cell : module->cells().to_vector()) {
if (cell->type != "$lut") continue; if (cell->type != "$lut") continue;
auto y_port = cell->getPort("\\Y").as_bit(); 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); 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_aiger();
void parse_xaiger(); void parse_xaiger(const dict<int,IdString> &box_lookup);
void parse_aiger_ascii(); void parse_aiger_ascii();
void parse_aiger_binary(); void parse_aiger_binary();
void post_process(); void post_process();

View File

@ -283,8 +283,8 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
if (!bits.empty()) { if (!bits.empty()) {
fprintf(f, " bits='"); fprintf(f, " bits='");
for (size_t i = bits.size(); i > 0; i--) for (size_t i = bits.size(); i > 0; i--)
fprintf(f, "%c", bits[i-1] == RTLIL::S0 ? '0' : fprintf(f, "%c", bits[i-1] == State::S0 ? '0' :
bits[i-1] == RTLIL::S1 ? '1' : bits[i-1] == State::S1 ? '1' :
bits[i-1] == RTLIL::Sx ? 'x' : bits[i-1] == RTLIL::Sx ? 'x' :
bits[i-1] == RTLIL::Sz ? 'z' : '?'); bits[i-1] == RTLIL::Sz ? 'z' : '?');
fprintf(f, "'(%d)", GetSize(bits)); 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->integer = v;
node->is_signed = is_signed; node->is_signed = is_signed;
for (int i = 0; i < width; i++) { 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; v = v >> 1;
} }
node->range_valid = true; node->range_valid = true;
@ -733,9 +733,9 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
node->bits = v; node->bits = v;
for (size_t i = 0; i < 32; i++) { for (size_t i = 0; i < 32; i++) {
if (i < node->bits.size()) 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()) 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_valid = true;
node->range_left = node->bits.size()-1; 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++) { for (size_t i = 0; i < str.size(); i++) {
unsigned char ch = str[str.size() - i - 1]; unsigned char ch = str[str.size() - i - 1];
for (int j = 0; j < 8; j++) { 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; ch = ch >> 1;
} }
} }
@ -780,7 +780,7 @@ AstNode *AstNode::mkconst_str(const std::string &str)
bool AstNode::bits_only_01() const bool AstNode::bits_only_01() const
{ {
for (auto bit : bits) for (auto bit : bits)
if (bit != RTLIL::S0 && bit != RTLIL::S1) if (bit != State::S0 && bit != State::S1)
return false; return false;
return true; 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); (*it)->str = (*it)->str.substr(1);
if (defer) if (defer)
@ -1172,7 +1172,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
if (design->has((*it)->str)) { if (design->has((*it)->str)) {
RTLIL::Module *existing_mod = design->module((*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()); log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str());
} else if (nooverwrite) { } else if (nooverwrite) {
log("Ignoring re-definition of module `%s' at %s:%d.\n", 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(); 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); 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()); 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->nomeminit = nomeminit;
new_mod->nomem2reg = nomem2reg; new_mod->nomem2reg = nomem2reg;
new_mod->mem2reg = mem2reg; new_mod->mem2reg = mem2reg;
new_mod->noblackbox = noblackbox;
new_mod->lib = lib; new_mod->lib = lib;
new_mod->nowb = nowb;
new_mod->noopt = noopt; new_mod->noopt = noopt;
new_mod->icells = icells; new_mod->icells = icells;
new_mod->pwires = pwires; new_mod->pwires = pwires;

View File

@ -1516,7 +1516,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
AstNode *child = *it; AstNode *child = *it;
if (child->type == AST_CELLTYPE) { if (child->type == AST_CELLTYPE) {
cell->type = child->str; 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); cell->type = cell->type.substr(1);
continue; continue;
} }

View File

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

View File

@ -78,7 +78,7 @@ failed:
return std::pair<RTLIL::IdString, int>("\\" + name, 0); 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::Module *module = nullptr;
RTLIL::Const *lutptr = NULL; RTLIL::Const *lutptr = NULL;

View File

@ -24,7 +24,7 @@
YOSYS_NAMESPACE_BEGIN 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); bool run_clean = false, bool sop_mode = false, bool wideports = false);
YOSYS_NAMESPACE_END YOSYS_NAMESPACE_END

View File

@ -25,7 +25,7 @@ struct JsonNode
{ {
char type; // S=String, N=Number, A=Array, D=Dict char type; // S=String, N=Number, A=Array, D=Dict
string data_string; string data_string;
int data_number; int64_t data_number;
vector<JsonNode*> data_array; vector<JsonNode*> data_array;
dict<string, JsonNode*> data_dict; dict<string, JsonNode*> data_dict;
vector<string> data_dict_keys; 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) void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
{ {
if (node->type != 'D') 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) for (auto it : node->data_dict)
{ {
IdString key = RTLIL::escape_id(it.first.c_str()); IdString key = RTLIL::escape_id(it.first.c_str());
JsonNode *value_node = it.second; Const value = json_parse_attr_param_value(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();
}
results[key] = value; results[key] = value;
} }
} }

View File

@ -19,6 +19,7 @@
#include "kernel/yosys.h" #include "kernel/yosys.h"
#include "kernel/sigtools.h" #include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h" #include "kernel/log.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.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_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); 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()); new_net = new Net(name.c_str());
nl->Add(new_net); 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); 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()) { while (!nl_todo.empty()) {
Netlist *nl = *nl_todo.begin(); Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0) { 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); importer.import_netlist(design, nl, nl_todo);
} }
nl_todo.erase(nl); nl_todo.erase(nl);
@ -1952,6 +1998,9 @@ struct VerificPass : public Pass {
log(" -autocover\n"); log(" -autocover\n");
log(" Generate automatic cover statements for all asserts\n"); log(" Generate automatic cover statements for all asserts\n");
log("\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(" -chparam name value \n");
log(" Elaborate the specified top modules (all modules when -all given) using\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"); 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("VERIFIC");
veri_file::DefineMacro(args[argidx] == "-formal" ? "FORMAL" : "SYNTHESIS"); 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); std::string name = args[argidx].substr(2);
if (args[argidx] == "-D") { if (args[argidx] == "-D") {
if (++argidx >= GetSize(args)) if (++argidx >= GetSize(args))
@ -2213,7 +2262,7 @@ struct VerificPass : public Pass {
std::set<Netlist*> nl_todo, nl_done; std::set<Netlist*> nl_todo, nl_done;
bool mode_all = false, mode_gates = false, mode_keep = false; bool mode_all = false, mode_gates = false, mode_keep = false;
bool mode_nosva = false, mode_names = false, mode_verific = 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; bool flatten = false, extnets = false;
string dumpfile; string dumpfile;
Map parameters(STRING_HASH); Map parameters(STRING_HASH);
@ -2255,6 +2304,10 @@ struct VerificPass : public Pass {
mode_autocover = true; mode_autocover = true;
continue; continue;
} }
if (args[argidx] == "-fullinit") {
mode_fullinit = true;
continue;
}
if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) { if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) {
const std::string &key = args[++argidx]; const std::string &key = args[++argidx];
const std::string &value = args[++argidx]; const std::string &value = args[++argidx];
@ -2283,7 +2336,7 @@ struct VerificPass : public Pass {
break; 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"); cmd_error(args, argidx, "unknown option");
if (mode_all) if (mode_all)
@ -2378,7 +2431,7 @@ struct VerificPass : public Pass {
Netlist *nl = *nl_todo.begin(); Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0) { if (nl_done.count(nl) == 0) {
VerificImporter importer(mode_gates, mode_keep, mode_nosva, 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); importer.import_netlist(design, nl, nl_todo);
} }
nl_todo.erase(nl); nl_todo.erase(nl);
@ -2484,7 +2537,7 @@ struct ReadPass : public Pass {
args[0] = "verific"; args[0] = "verific";
} else { } else {
args[0] = "read_verilog"; args[0] = "read_verilog";
args.erase(args.begin()+1, args.begin()+2); args[1] = "-defer";
} }
Pass::call(design, args); Pass::call(design, args);
return; return;
@ -2498,6 +2551,7 @@ struct ReadPass : public Pass {
if (args[1] == "-formal") if (args[1] == "-formal")
args.insert(args.begin()+1, std::string()); args.insert(args.begin()+1, std::string());
args[1] = "-sv"; args[1] = "-sv";
args.insert(args.begin()+1, "-defer");
} }
Pass::call(design, args); Pass::call(design, args);
return; return;

View File

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

View File

@ -357,7 +357,7 @@ struct SvaFsm
for (int i = 0; i < GetSize(nodes); i++) for (int i = 0; i < GetSize(nodes); i++)
{ {
if (next_state_sig[i] != State::S0) { 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 { } else {
module->connect(state_wire[i], State::S0); 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) { if (base == 10) {
while (!digits.empty()) 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 { } else {
int bits_per_digit = my_ilog2(base-1); int bits_per_digit = my_ilog2(base-1);
for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) { 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) else if (*it == 0xf2)
data.push_back(RTLIL::Sa); data.push_back(RTLIL::Sa);
else else
data.push_back((*it & bitmask) ? RTLIL::S1 : RTLIL::S0); data.push_back((*it & bitmask) ? State::S1 : State::S0);
} }
} }
} }
int len = GetSize(data); 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_in_bits < 0) {
if (len < 32) 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; 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); 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--) for (len = len - 1; len >= 0; len--)
if (data[len] == RTLIL::S1) if (data[len] == State::S1)
break; break;
if (msb == RTLIL::S0 || msb == RTLIL::S1) { if (msb == State::S0 || msb == State::S1) {
len += 1; len += 1;
data.resize(len_in_bits, RTLIL::S0); data.resize(len_in_bits, State::S0);
} else { } else {
len += 2; len += 2;
data.resize(len_in_bits, msb); 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++) { for (int i = 0; i < len; i++) {
unsigned char ch = str[len - i]; unsigned char ch = str[len - i];
for (int j = 0; j < 8; j++) { 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; ch = ch >> 1;
} }
} }
@ -190,8 +190,8 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
if (*endptr == 0) { if (*endptr == 0) {
std::vector<RTLIL::State> data; std::vector<RTLIL::State> data;
my_strtobin(data, str, -1, 10, case_type, false); my_strtobin(data, str, -1, 10, case_type, false);
if (data.back() == RTLIL::S1) if (data.back() == State::S1)
data.push_back(RTLIL::S0); data.push_back(State::S0);
return AstNode::mkconst_bits(data, true); 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 (len_in_bits < 0) {
if (is_signed && data.back() == RTLIL::S1) if (is_signed && data.back() == State::S1)
data.push_back(RTLIL::S0); data.push_back(State::S0);
} }
return AstNode::mkconst_bits(data, is_signed, is_unsized); 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) \ #define YY_INPUT(buf,result,max_size) \
result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size) result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
#undef YY_BUF_SIZE
#define YY_BUF_SIZE 65536
%} %}
%option yylineno %option yylineno

View File

@ -274,7 +274,7 @@ hierarchical_id:
$$ = $1; $$ = $1;
} | } |
hierarchical_id TOK_PACKAGESEP TOK_ID { hierarchical_id TOK_PACKAGESEP TOK_ID {
if ($3->substr(0, 1) == "\\") if ($3->compare(0, 1, "\\") == 0)
*$1 += "::" + $3->substr(1); *$1 += "::" + $3->substr(1);
else else
*$1 += "::" + *$3; *$1 += "::" + *$3;
@ -282,7 +282,7 @@ hierarchical_id:
$$ = $1; $$ = $1;
} | } |
hierarchical_id '.' TOK_ID { hierarchical_id '.' TOK_ID {
if ($3->substr(0, 1) == "\\") if ($3->compare(0, 1, "\\") == 0)
*$1 += "." + $3->substr(1); *$1 += "." + $3->substr(1);
else else
*$1 += "." + *$3; *$1 += "." + *$3;
@ -2184,7 +2184,7 @@ basic_expr:
$$ = $1; $$ = $1;
} | } |
'(' expr ')' TOK_CONSTVAL { '(' 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()); 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 *bits = $2;
AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
@ -2194,7 +2194,7 @@ basic_expr:
delete $4; delete $4;
} | } |
hierarchical_id TOK_CONSTVAL { 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()); 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); AstNode *bits = new AstNode(AST_IDENTIFIER);
bits->str = *$1; bits->str = *$1;

View File

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

View File

@ -24,9 +24,9 @@ PRIVATE_NAMESPACE_BEGIN
void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) 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 a_width = GetSize(cell->getPort(A));
int y_width = GetSize(cell->getPort(Y)); 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) 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 a_width = GetSize(cell->getPort(A));
int b_width = GetSize(cell->getPort(B)); int b_width = GetSize(cell->getPort(B));
int y_width = GetSize(cell->getPort(Y)); 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) if (a_width > b_width)
a_width = b_width; a_width = b_width;
else else
@ -71,9 +71,9 @@ void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
void arith_neg_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 a_width = GetSize(cell->getPort(A));
int y_width = GetSize(cell->getPort(Y)); 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) 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 a_width = GetSize(cell->getPort(A));
int b_width = GetSize(cell->getPort(B)); int b_width = GetSize(cell->getPort(B));
int y_width = GetSize(cell->getPort(Y)); 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); int ab_width = std::max(a_width, b_width);
y_width = std::min(y_width, ab_width+1); 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) 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)); 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) 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 a_width = GetSize(cell->getPort(A));
int b_width = GetSize(cell->getPort(B)); 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) 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 a_width = GetSize(cell->getPort(A));
int b_width = GetSize(cell->getPort(B)); 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) 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); bitwise_unary_op(this, cell);
return true; 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); bitwise_binary_op(this, cell);
return true; return true;
} }
if (cell->type == "$neg") { if (cell->type == ID($neg)) {
arith_neg_op(this, cell); arith_neg_op(this, cell);
return true; return true;
} }
if (cell->type.in("$add", "$sub")) { if (cell->type.in(ID($add), ID($sub))) {
arith_binary_op(this, cell); arith_binary_op(this, cell);
return true; 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); reduce_op(this, cell);
return true; return true;
} }
// FIXME: // 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); // shift_op(this, cell);
// return true; // 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); compare_op(this, cell);
return true; return true;
} }
if (cell->type.in("$mux", "$pmux")) { if (cell->type.in(ID($mux), ID($pmux))) {
mux_op(this, cell); mux_op(this, cell);
return true; return true;
} }

View File

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

View File

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

View File

@ -24,62 +24,92 @@
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr); struct CellCosts
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)
{ {
static dict<RTLIL::IdString, int> gate_cost = { static const dict<RTLIL::IdString, int>& default_gate_cost() {
{ "$_BUF_", 1 }, static const dict<RTLIL::IdString, int> db = {
{ "$_NOT_", 2 }, { ID($_BUF_), 1 },
{ "$_AND_", 4 }, { ID($_NOT_), 2 },
{ "$_NAND_", 4 }, { ID($_AND_), 4 },
{ "$_OR_", 4 }, { ID($_NAND_), 4 },
{ "$_NOR_", 4 }, { ID($_OR_), 4 },
{ "$_ANDNOT_", 4 }, { ID($_NOR_), 4 },
{ "$_ORNOT_", 4 }, { ID($_ANDNOT_), 4 },
{ "$_XOR_", 8 }, { ID($_ORNOT_), 4 },
{ "$_XNOR_", 8 }, { ID($_XOR_), 5 },
{ "$_AOI3_", 6 }, { ID($_XNOR_), 5 },
{ "$_OAI3_", 6 }, { ID($_AOI3_), 6 },
{ "$_AOI4_", 8 }, { ID($_OAI3_), 6 },
{ "$_OAI4_", 8 }, { ID($_AOI4_), 7 },
{ "$_MUX_", 4 } { ID($_OAI4_), 7 },
}; { ID($_MUX_), 4 },
{ ID($_NMUX_), 4 }
if (gate_cost.count(type)) };
return gate_cost.at(type); return db;
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;
} }
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters)); static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
return 1; 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) dict<RTLIL::IdString, int> mod_cost_cache;
{ const dict<RTLIL::IdString, int> *gate_cost = nullptr;
return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache); 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 YOSYS_NAMESPACE_END

View File

@ -522,6 +522,12 @@ int main(int argc, char **argv)
if (!backend_command.empty()) if (!backend_command.empty())
run_backend(output_filename, backend_command); 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()) if (!depsfile.empty())
{ {
FILE *f = fopen(depsfile.c_str(), "wt"); 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; } 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) # define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0)
#else #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) # define log_debug(_fmt, ...) do { } while (0)
#endif #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]) 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); port.in_b.remove(GetSize(port.in_b)-1);
} else { } 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); 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); port.in_b.remove(GetSize(port.in_b)-1);
} }
@ -80,9 +80,9 @@ struct Macc
} }
for (auto &bit : bit_ports) for (auto &bit : bit_ports)
if (bit == RTLIL::S1) if (bit == State::S1)
off = const_add(off, RTLIL::Const(1, width), false, false, width); 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); new_bit_ports.append(bit);
if (off.as_bool()) { if (off.as_bool()) {
@ -99,24 +99,24 @@ struct Macc
void from_cell(RTLIL::Cell *cell) void from_cell(RTLIL::Cell *cell)
{ {
RTLIL::SigSpec port_a = cell->getPort("\\A"); RTLIL::SigSpec port_a = cell->getPort(ID::A);
ports.clear(); 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; int config_cursor = 0;
#ifndef NDEBUG #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); log_assert(GetSize(config_bits) >= config_width);
#endif #endif
int num_bits = 0; int num_bits = 0;
if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 1; if (config_bits[config_cursor++] == State::S1) num_bits |= 1;
if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 2; if (config_bits[config_cursor++] == State::S1) num_bits |= 2;
if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 4; if (config_bits[config_cursor++] == State::S1) num_bits |= 4;
if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 8; if (config_bits[config_cursor++] == State::S1) num_bits |= 8;
int port_a_cursor = 0; int port_a_cursor = 0;
while (port_a_cursor < GetSize(port_a)) while (port_a_cursor < GetSize(port_a))
@ -124,12 +124,12 @@ struct Macc
log_assert(config_cursor + 2 + 2*num_bits <= config_width); log_assert(config_cursor + 2 + 2*num_bits <= config_width);
port_t this_port; port_t this_port;
this_port.is_signed = config_bits[config_cursor++] == RTLIL::S1; this_port.is_signed = config_bits[config_cursor++] == State::S1;
this_port.do_subtract = config_bits[config_cursor++] == RTLIL::S1; this_port.do_subtract = config_bits[config_cursor++] == State::S1;
int size_a = 0; int size_a = 0;
for (int i = 0; i < num_bits; i++) 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; size_a |= 1 << i;
this_port.in_a = port_a.extract(port_a_cursor, size_a); this_port.in_a = port_a.extract(port_a_cursor, size_a);
@ -137,7 +137,7 @@ struct Macc
int size_b = 0; int size_b = 0;
for (int i = 0; i < num_bits; i++) 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; size_b |= 1 << i;
this_port.in_b = port_a.extract(port_a_cursor, size_b); this_port.in_b = port_a.extract(port_a_cursor, size_b);
@ -166,43 +166,43 @@ struct Macc
num_bits++, max_size /= 2; num_bits++, max_size /= 2;
log_assert(num_bits < 16); log_assert(num_bits < 16);
config_bits.push_back(num_bits & 1 ? RTLIL::S1 : RTLIL::S0); config_bits.push_back(num_bits & 1 ? State::S1 : State::S0);
config_bits.push_back(num_bits & 2 ? RTLIL::S1 : RTLIL::S0); config_bits.push_back(num_bits & 2 ? State::S1 : State::S0);
config_bits.push_back(num_bits & 4 ? RTLIL::S1 : RTLIL::S0); config_bits.push_back(num_bits & 4 ? State::S1 : State::S0);
config_bits.push_back(num_bits & 8 ? RTLIL::S1 : RTLIL::S0); config_bits.push_back(num_bits & 8 ? State::S1 : State::S0);
for (auto &port : ports) for (auto &port : ports)
{ {
if (GetSize(port.in_a) == 0) if (GetSize(port.in_a) == 0)
continue; continue;
config_bits.push_back(port.is_signed ? RTLIL::S1 : RTLIL::S0); config_bits.push_back(port.is_signed ? State::S1 : State::S0);
config_bits.push_back(port.do_subtract ? RTLIL::S1 : RTLIL::S0); config_bits.push_back(port.do_subtract ? State::S1 : State::S0);
int size_a = GetSize(port.in_a); int size_a = GetSize(port.in_a);
for (int i = 0; i < num_bits; i++) 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); int size_b = GetSize(port.in_b);
for (int i = 0; i < num_bits; i++) 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_a);
port_a.append(port.in_b); port_a.append(port.in_b);
} }
cell->setPort("\\A", port_a); cell->setPort(ID::A, port_a);
cell->setPort("\\B", bit_ports); cell->setPort(ID::B, bit_ports);
cell->setParam("\\CONFIG", config_bits); cell->setParam(ID(CONFIG), config_bits);
cell->setParam("\\CONFIG_WIDTH", GetSize(config_bits)); cell->setParam(ID(CONFIG_WIDTH), GetSize(config_bits));
cell->setParam("\\A_WIDTH", GetSize(port_a)); cell->setParam(ID(A_WIDTH), GetSize(port_a));
cell->setParam("\\B_WIDTH", GetSize(bit_ports)); cell->setParam(ID(B_WIDTH), GetSize(bit_ports));
} }
bool eval(RTLIL::Const &result) const bool eval(RTLIL::Const &result) const
{ {
for (auto &bit : result.bits) for (auto &bit : result.bits)
bit = RTLIL::S0; bit = State::S0;
for (auto &port : ports) for (auto &port : ports)
{ {

View File

@ -25,6 +25,65 @@
#include <stdio.h> #include <stdio.h>
#include <errno.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 YOSYS_NAMESPACE_BEGIN
#define MAX_REG_COUNT 1000 #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]; 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."); cmd_error(args, argidx, "Unknown option or option in arguments.");
if (!select) if (!select)
@ -236,8 +295,6 @@ void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
pass_register[args[0]]->post_execute(state); pass_register[args[0]]->post_execute(state);
while (design->selection_stack.size() > orig_sel_stack_pos) while (design->selection_stack.size() > orig_sel_stack_pos)
design->selection_stack.pop_back(); design->selection_stack.pop_back();
design->check();
} }
void Pass::call_on_selection(RTLIL::Design *design, const RTLIL::Selection &selection, std::string command) 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()); log(" %s\n", command.c_str());
else else
log(" %s %s\n", command.c_str(), info.c_str()); log(" %s %s\n", command.c_str(), info.c_str());
} else } else {
Pass::call(active_design, command); Pass::call(active_design, command);
active_design->check();
}
} }
void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to) 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]; 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."); cmd_error(args, argidx, "Unknown option or option in arguments.");
if (f != NULL) if (f != NULL)
cmd_error(args, argidx, "Extra filename argument in direct file mode."); 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; filename = arg;
if (filename == "<<" && argidx+1 < args.size()) if (filename == "<<" && argidx+1 < args.size())
filename += args[++argidx]; filename += args[++argidx];
if (filename.substr(0, 2) == "<<") { if (filename.compare(0, 2, "<<") == 0) {
if (Frontend::current_script_file == NULL) if (Frontend::current_script_file == NULL)
log_error("Unexpected here document '%s' outside of script!\n", filename.c_str()); log_error("Unexpected here document '%s' outside of script!\n", filename.c_str());
if (filename.size() <= 2) if (filename.size() <= 2)
@ -416,7 +475,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
break; break;
} }
size_t indent = buffer.find_first_not_of(" \t\r\n"); 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; break;
last_here_document += buffer; last_here_document += buffer;
} }
@ -436,12 +495,34 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
delete ff; delete ff;
else else
f = ff; 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) if (f == NULL)
log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno)); 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++) 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."); cmd_error(args, i, "Found option, expected arguments.");
if (argidx+1 < args.size()) { 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); args.push_back(filename);
frontend_register[args[0]]->execute(args, design); frontend_register[args[0]]->execute(args, design);
} }
design->check();
} }
Backend::Backend(std::string name, std::string short_help) : 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]; 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."); cmd_error(args, argidx, "Unknown option or option in arguments.");
if (f != NULL) if (f != NULL)
cmd_error(args, argidx, "Extra filename argument in direct file mode."); 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; filename = arg;
rewrite_filename(filename); rewrite_filename(filename);
std::ofstream *ff = new std::ofstream; if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".gz") == 0) {
ff->open(filename.c_str(), std::ofstream::trunc); #ifdef YOSYS_ENABLE_ZLIB
yosys_output_files.insert(filename); gzip_ostream *gf = new gzip_ostream;
if (ff->fail()) { if (!gf->open(filename)) {
delete ff; delete gf;
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno)); 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) 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) while (design->selection_stack.size() > orig_sel_stack_pos)
design->selection_stack.pop_back(); design->selection_stack.pop_back();
design->check();
} }
static struct CellHelpMessages { 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_XTRACE_GET_PUT
#undef YOSYS_SORT_ID_FREE_LIST #undef YOSYS_SORT_ID_FREE_LIST
#undef YOSYS_USE_STICKY_IDS
#undef YOSYS_NO_IDS_REFCNT
// the global id string cache // the global id string cache
@ -87,13 +89,17 @@ namespace RTLIL
~destruct_guard_t() { ok = false; } ~destruct_guard_t() { ok = false; }
} destruct_guard; } destruct_guard;
static std::vector<int> global_refcount_storage_;
static std::vector<char*> global_id_storage_; static std::vector<char*> global_id_storage_;
static dict<char*, int, hash_cstr_ops> global_id_index_; 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_; 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_ptr_;
static int last_created_idx_[8]; static int last_created_idx_[8];
#endif
static inline void xtrace_db_dump() static inline void xtrace_db_dump()
{ {
@ -110,12 +116,14 @@ namespace RTLIL
static inline void checkpoint() static inline void checkpoint()
{ {
#ifdef YOSYS_USE_STICKY_IDS
last_created_idx_ptr_ = 0; last_created_idx_ptr_ = 0;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (last_created_idx_[i]) if (last_created_idx_[i])
put_reference(last_created_idx_[i]); put_reference(last_created_idx_[i]);
last_created_idx_[i] = 0; last_created_idx_[i] = 0;
} }
#endif
#ifdef YOSYS_SORT_ID_FREE_LIST #ifdef YOSYS_SORT_ID_FREE_LIST
std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>()); std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>());
#endif #endif
@ -123,36 +131,47 @@ namespace RTLIL
static inline int get_reference(int idx) static inline int get_reference(int idx)
{ {
global_refcount_storage_.at(idx)++; if (idx) {
#ifdef YOSYS_XTRACE_GET_PUT #ifndef YOSYS_NO_IDS_REFCNT
if (yosys_xtrace) { global_refcount_storage_[idx]++;
log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
}
#endif #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; return idx;
} }
static inline int get_reference(const char *p) static int get_reference(const char *p)
{ {
log_assert(destruct_guard.ok); log_assert(destruct_guard.ok);
if (p[0]) { if (!p[0])
log_assert(p[1] != 0); return 0;
log_assert(p[0] == '$' || p[0] == '\\');
} log_assert(p[0] == '$' || p[0] == '\\');
log_assert(p[1] != 0);
auto it = global_id_index_.find((char*)p); auto it = global_id_index_.find((char*)p);
if (it != global_id_index_.end()) { if (it != global_id_index_.end()) {
#ifndef YOSYS_NO_IDS_REFCNT
global_refcount_storage_.at(it->second)++; global_refcount_storage_.at(it->second)++;
#endif
#ifdef YOSYS_XTRACE_GET_PUT #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)); 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 #endif
return it->second; return it->second;
} }
#ifndef YOSYS_NO_IDS_REFCNT
if (global_free_idx_list_.empty()) { 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); log_assert(global_id_storage_.size() < 0x40000000);
global_free_idx_list_.push_back(global_id_storage_.size()); global_free_idx_list_.push_back(global_id_storage_.size());
global_id_storage_.push_back(nullptr); global_id_storage_.push_back(nullptr);
@ -164,13 +183,15 @@ namespace RTLIL
global_id_storage_.at(idx) = strdup(p); global_id_storage_.at(idx) = strdup(p);
global_id_index_[global_id_storage_.at(idx)] = idx; global_id_index_[global_id_storage_.at(idx)] = idx;
global_refcount_storage_.at(idx)++; global_refcount_storage_.at(idx)++;
#else
// Avoid Create->Delete->Create pattern if (global_id_storage_.empty()) {
if (last_created_idx_[last_created_idx_ptr_]) global_id_storage_.push_back((char*)"");
put_reference(last_created_idx_[last_created_idx_ptr_]); global_id_index_[global_id_storage_.back()] = 0;
last_created_idx_[last_created_idx_ptr_] = idx; }
get_reference(last_created_idx_[last_created_idx_ptr_]); int idx = global_id_storage_.size();
last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7; global_id_storage_.push_back(strdup(p));
global_id_index_[global_id_storage_.back()] = idx;
#endif
if (yosys_xtrace) { if (yosys_xtrace) {
log("#X# New IdString '%s' with index %d.\n", p, idx); log("#X# New IdString '%s' with index %d.\n", p, idx);
@ -178,18 +199,28 @@ namespace RTLIL
} }
#ifdef YOSYS_XTRACE_GET_PUT #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)); log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
}
#endif #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; return idx;
} }
#ifndef YOSYS_NO_IDS_REFCNT
static inline void put_reference(int idx) static inline void put_reference(int idx)
{ {
// put_reference() may be called from destructors after the destructor of // put_reference() may be called from destructors after the destructor of
// global_refcount_storage_ has been run. in this case we simply do nothing. // global_refcount_storage_ has been run. in this case we simply do nothing.
if (!destruct_guard.ok) if (!destruct_guard.ok || !idx)
return; return;
#ifdef YOSYS_XTRACE_GET_PUT #ifdef YOSYS_XTRACE_GET_PUT
@ -198,11 +229,13 @@ namespace RTLIL
} }
#endif #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; return;
log_assert(refcount == 0);
if (yosys_xtrace) { if (yosys_xtrace) {
log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx); log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx);
log_backtrace("-X- ", yosys_xtrace-1); log_backtrace("-X- ", yosys_xtrace-1);
@ -213,46 +246,50 @@ namespace RTLIL
global_id_storage_.at(idx) = nullptr; global_id_storage_.at(idx) = nullptr;
global_free_idx_list_.push_back(idx); 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 // the actual IdString object is just is a single int
int index_; int index_;
IdString() : index_(get_reference("")) { } inline IdString() : index_(0) { }
IdString(const char *str) : index_(get_reference(str)) { } inline IdString(const char *str) : index_(get_reference(str)) { }
IdString(const IdString &str) : index_(get_reference(str.index_)) { } inline IdString(const IdString &str) : index_(get_reference(str.index_)) { }
IdString(const std::string &str) : index_(get_reference(str.c_str())) { } inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
~IdString() { put_reference(index_); } 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_); put_reference(index_);
index_ = get_reference(rhs.index_); index_ = get_reference(rhs.index_);
} }
void operator=(const char *rhs) { inline void operator=(const char *rhs) {
IdString id(rhs); IdString id(rhs);
*this = id; *this = id;
} }
void operator=(const std::string &rhs) { inline void operator=(const std::string &rhs) {
IdString id(rhs); IdString id(rhs);
*this = id; *this = id;
} }
const char *c_str() const { inline const char *c_str() const {
return global_id_storage_.at(index_); return global_id_storage_.at(index_);
} }
std::string str() const { inline std::string str() const {
return std::string(global_id_storage_.at(index_)); 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_; 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_; }
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. // 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); 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 { bool begins_with(const char* prefix) const {
size_t len = strlen(prefix); size_t len = strlen(prefix);
if (size() < len) return false; if (size() < len) return false;
return substr(0, len) == prefix; return compare(0, len, prefix) == 0;
} }
bool ends_with(const char* suffix) const { bool ends_with(const char* suffix) const {
size_t len = strlen(suffix); size_t len = strlen(suffix);
if (size() < len) return false; if (size() < len) return false;
return substr(size()-len) == suffix; return compare(size()-len, len, suffix) == 0;
} }
size_t size() const { size_t size() const {
return str().size(); return strlen(c_str());
} }
bool empty() const { bool empty() const {
@ -328,6 +369,14 @@ namespace RTLIL
bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; } 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) { static inline std::string escape_id(std::string str) {
if (str.size() > 0 && str[0] != '\\' && str[0] != '$') if (str.size() > 0 && str[0] != '\\' && str[0] != '$')
return "\\" + str; 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. // It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
template<typename T> 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; typename dict<RTLIL::IdString, T>::iterator it;
dict<RTLIL::IdString, T> *list_p; dict<RTLIL::IdString, T> *list_p;
int *refcount_p; int *refcount_p;
@ -474,13 +527,25 @@ namespace RTLIL
return it != other.it; 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); log_assert(list_p != nullptr);
if (++it == list_p->end()) { if (++it == list_p->end()) {
(*refcount_p)--; (*refcount_p)--;
list_p = nullptr; list_p = nullptr;
refcount_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_bool_attribute(RTLIL::IdString id) const;
bool get_blackbox_attribute(bool ignore_wb=false) 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); 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 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(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
RTLIL::SigSpec extract(int offset, int length = 1) 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(const RTLIL::SigSpec &signal);
void append_bit(const RTLIL::SigBit &bit); void append_bit(const RTLIL::SigBit &bit);
@ -818,6 +884,7 @@ public:
operator std::vector<RTLIL::SigChunk>() const { return chunks(); } operator std::vector<RTLIL::SigChunk>() const { return chunks(); }
operator std::vector<RTLIL::SigBit>() const { return bits(); } 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_; }; 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* 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* 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* 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* 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* 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 = ""); 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 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 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 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 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 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 = ""); 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); void fixup_parameters(bool set_a_signed = false, bool set_b_signed = false);
bool has_keep_attr() const { bool has_keep_attr() const {
return get_bool_attribute("\\keep") || (module && module->design && module->design->module(type) && return get_bool_attribute(ID::keep) || (module && module->design && module->design->module(type) &&
module->design->module(type)->get_bool_attribute("\\keep")); module->design->module(type)->get_bool_attribute(ID::keep));
} }
template<typename T> void rewrite_sigspecs(T &functor); 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() : wire(NULL), data(RTLIL::State::S0) { }
inline RTLIL::SigBit::SigBit(RTLIL::State bit) : wire(NULL), data(bit) { } 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) : 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(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]; } 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) if(already_setup)
return; return;
already_setup = true; already_setup = true;
// if there are already IdString objects then we have a global initialization order bug
IdString empty_id; RTLIL::ID::A = "\\A";
log_assert(empty_id.index_ == 0); RTLIL::ID::B = "\\B";
IdString::get_reference(empty_id.index_); RTLIL::ID::Y = "\\Y";
RTLIL::ID::keep = "\\keep";
RTLIL::ID::whitebox = "\\whitebox";
RTLIL::ID::blackbox = "\\blackbox";
#ifdef WITH_PYTHON #ifdef WITH_PYTHON
PyImport_AppendInittab((char*)"libyosys", INIT_MODULE); PyImport_AppendInittab((char*)"libyosys", INIT_MODULE);
@ -575,9 +578,6 @@ void yosys_shutdown()
#ifdef WITH_PYTHON #ifdef WITH_PYTHON
Py_Finalize(); Py_Finalize();
#endif #endif
IdString empty_id;
IdString::put_reference(empty_id.index_);
} }
RTLIL::IdString new_id(std::string file, int line, std::string func) 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) 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); 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); filename = proc_share_dirname() + filename.substr(2);
#ifndef _WIN32 #ifndef _WIN32
if (filename.substr(0, 2) == "~/") if (filename.compare(0, 2, "~/") == 0)
filename = filename.replace(0, 1, getenv("HOME")); filename = filename.replace(0, 1, getenv("HOME"));
#endif #endif
} }
@ -894,23 +894,26 @@ void run_frontend(std::string filename, std::string command, std::string *backen
design = yosys_design; design = yosys_design;
if (command == "auto") { 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"; 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"; 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"; 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"; 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"; 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"; 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"; 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"; 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"; command = "tcl";
else if (filename == "-") else if (filename == "-")
command = "script"; command = "script";
@ -961,14 +964,18 @@ void run_frontend(std::string filename, std::string command, std::string *backen
command += next_line; command += next_line;
} }
handle_label(command, from_to_active, run_from, run_to); handle_label(command, from_to_active, run_from, run_to);
if (from_to_active) if (from_to_active) {
Pass::call(design, command); Pass::call(design, command);
design->check();
}
} }
if (!command.empty()) { if (!command.empty()) {
handle_label(command, from_to_active, run_from, run_to); handle_label(command, from_to_active, run_from, run_to);
if (from_to_active) if (from_to_active) {
Pass::call(design, command); Pass::call(design, command);
design->check();
}
} }
} }
catch (...) { catch (...) {
@ -997,6 +1004,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen
Pass::call(design, vector<string>({command, filename})); Pass::call(design, vector<string>({command, filename}));
else else
Frontend::frontend_call(design, NULL, filename, command); Frontend::frontend_call(design, NULL, filename, command);
design->check();
} }
void run_frontend(std::string filename, std::string command, RTLIL::Design *design) 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; design = yosys_design;
if (command == "auto") { 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"; 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"; 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"; 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"; 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"; 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"; command = "json";
else if (filename == "-") else if (filename == "-")
command = "ilang"; command = "ilang";
@ -1064,7 +1072,7 @@ static char *readline_cmd_generator(const char *text, int state)
} }
for (; it != pass_register.end(); it++) { 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 strdup((it++)->first.c_str());
} }
return NULL; return NULL;
@ -1086,7 +1094,7 @@ static char *readline_obj_generator(const char *text, int state)
if (design->selected_active_module.empty()) if (design->selected_active_module.empty())
{ {
for (auto &it : design->modules_) 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))); obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
} }
else 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); RTLIL::Module *module = design->modules_.at(design->selected_active_module);
for (auto &it : module->wires_) 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))); obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
for (auto &it : module->memories) 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))); obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
for (auto &it : module->cells_) 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))); obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
for (auto &it : module->processes) 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))); obj_names.push_back(strdup(RTLIL::id2cstr(it.first)));
} }
@ -1180,6 +1188,7 @@ void shell(RTLIL::Design *design)
design->selection_stack.pop_back(); design->selection_stack.pop_back();
log_reset_stack(); log_reset_stack();
} }
design->check();
} }
if (command == NULL) if (command == NULL)
printf("exit\n"); printf("exit\n");

View File

@ -52,6 +52,7 @@
#include <stdexcept> #include <stdexcept>
#include <memory> #include <memory>
#include <cmath> #include <cmath>
#include <cstddef>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
@ -87,6 +88,10 @@ extern int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName);
extern void Tcl_Finalize(void); extern void Tcl_Finalize(void);
extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr); extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr);
extern const char *Tcl_GetStringResult(Tcl_Interp *interp); 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
#endif #endif
@ -300,8 +305,17 @@ RTLIL::IdString new_id(std::string file, int line, std::string func);
#define NEW_ID \ #define NEW_ID \
YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__) YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__)
#define ID(_str) \ // Create a statically allocated IdString object, using for example ID(A) or ID($add).
([]() { static YOSYS_NAMESPACE_PREFIX RTLIL::IdString _id(_str); return _id; })() //
// 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(); RTLIL::Design *yosys_get_design();
std::string proc_self_dirname(); std::string proc_self_dirname();

View File

@ -494,6 +494,6 @@ Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLA
\end{fixme} \end{fixme}
\begin{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} \end{fixme}

View File

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

View File

@ -121,7 +121,7 @@ struct CoverPass : public Pass {
} }
break; 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++]); patterns.push_back(args[argidx++]);
extra_args(args, argidx, design); extra_args(args, argidx, design);

View File

@ -107,7 +107,7 @@ struct DeletePass : public Pass {
for (auto &it : module->cells_) { for (auto &it : module->cells_) {
if (design->selected(module, it.second)) if (design->selected(module, it.second))
delete_cells.insert(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_mems.count(it.second->parameters.at("\\MEMID").decode_string()) != 0)
delete_cells.insert(it.second); delete_cells.insert(it.second);
} }

View File

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

View File

@ -527,11 +527,11 @@ struct ShowWorker
{ {
currentColor = xorshift32(currentColor); currentColor = xorshift32(currentColor);
if (wires_on_demand.count(it.first) > 0) { 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()); it.second.out.erase(*it.second.in.begin());
if (it.second.in.size() == 1 && it.second.out.size() == 1) { if (it.second.in.size() == 1 && it.second.out.size() == 1) {
std::string from = *it.second.in.begin(), to = *it.second.out.begin(); 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()); 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; continue;
} }
@ -808,7 +808,7 @@ struct ShowPass : public Pass {
if (f.fail()) if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str()); log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design; 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); libs.push_back(lib);
} }

View File

@ -17,11 +17,10 @@
* *
*/ */
#include "kernel/register.h" #include "kernel/yosys.h"
#include "kernel/celltypes.h" #include "kernel/celltypes.h"
#include "passes/techmap/libparse.h" #include "passes/techmap/libparse.h"
#include "kernel/cost.h"
#include "kernel/log.h"
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN PRIVATE_NAMESPACE_BEGIN
@ -223,6 +222,28 @@ struct statdata_t
log("\n"); log("\n");
log(" Estimated number of LCs: %10d\n", lc_cnt); 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("\n");
log(" -tech <technology>\n"); log(" -tech <technology>\n");
log(" print area estemate for the specified technology. Currently supported\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("\n");
log(" -width\n"); log(" -width\n");
log(" annotate internal cell types with their word 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); 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()); log_cmd_error("Unsupported technology: '%s'\n", techname.c_str());
for (auto mod : design->selected_modules()) for (auto mod : design->selected_modules())

View File

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

View File

@ -215,9 +215,9 @@ struct EquivStructWorker
if (c != nullptr) { if (c != nullptr) {
string n = cell_name.str(); string n = cell_name.str();
cells_type = c->type; 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); 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); gate_cells.push_back(c);
else else
other_cells.push_back(c); other_cells.push_back(c);

View File

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

View File

@ -168,7 +168,7 @@ undef_bit_in_next_state:
ctrl_in_bit_indices[ctrl_in[i]] = i; ctrl_in_bit_indices[ctrl_in[i]] = i;
for (auto &it : ctrl_in_bit_indices) 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)) for (auto &dc_bit : exclusive_ctrls.at(it.first))
if (ctrl_in_bit_indices.count(dc_bit)) if (ctrl_in_bit_indices.count(dc_bit))
tr.ctrl_in.bits.at(ctrl_in_bit_indices.at(dc_bit)) = RTLIL::State::Sa; 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(); ce.push();
dont_care.append(undef); dont_care.append(undef);
ce.set(undef, constval.as_const()); 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)) { for (auto &bit : exclusive_ctrls.at(undef)) {
RTLIL::SigSpec bitval = bit; RTLIL::SigSpec bitval = bit;
if (ce.eval(bitval) && bitval != RTLIL::S0) if (ce.eval(bitval) && bitval != State::S0)
goto found_contradiction_1; goto found_contradiction_1;
else 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); find_transitions(ce, ce_nostop, fsm_data, states, state_in, ctrl_in, ctrl_out, dff_in, dont_care);
found_contradiction_1: found_contradiction_1:
@ -231,21 +231,21 @@ undef_bit_in_next_state:
else else
{ {
ce.push(), ce_nostop.push(); ce.push(), ce_nostop.push();
ce.set(undef, RTLIL::S0); ce.set(undef, State::S0);
ce_nostop.set(undef, RTLIL::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); find_transitions(ce, ce_nostop, fsm_data, states, state_in, ctrl_in, ctrl_out, dff_in, dont_care);
ce.pop(), ce_nostop.pop(); ce.pop(), ce_nostop.pop();
ce.push(), ce_nostop.push(); ce.push(), ce_nostop.push();
ce.set(undef, RTLIL::S1); ce.set(undef, State::S1);
ce_nostop.set(undef, RTLIL::S1); ce_nostop.set(undef, State::S1);
if (exclusive_ctrls.count(undef)) if (exclusive_ctrls.count(undef))
for (auto &bit : exclusive_ctrls.at(undef)) { for (auto &bit : exclusive_ctrls.at(undef)) {
RTLIL::SigSpec bitval = bit; 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; goto found_contradiction_2;
else 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); find_transitions(ce, ce_nostop, fsm_data, states, state_in, ctrl_in, ctrl_out, dff_in, dont_care);
found_contradiction_2: found_contradiction_2:
@ -263,8 +263,8 @@ static void extract_fsm(RTLIL::Wire *wire)
RTLIL::SigSpec dff_in(RTLIL::State::Sm, wire->width); RTLIL::SigSpec dff_in(RTLIL::State::Sm, wire->width);
RTLIL::Const reset_state(RTLIL::State::Sx, wire->width); RTLIL::Const reset_state(RTLIL::State::Sx, wire->width);
RTLIL::SigSpec clk = RTLIL::S0; RTLIL::SigSpec clk = State::S0;
RTLIL::SigSpec arst = RTLIL::S0; RTLIL::SigSpec arst = State::S0;
bool clk_polarity = true; bool clk_polarity = true;
bool arst_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"); RTLIL::Cell *fsm_cell = module->addCell(stringf("$fsm$%s$%d", wire->name.c_str(), autoidx++), "$fsm");
fsm_cell->setPort("\\CLK", clk); fsm_cell->setPort("\\CLK", clk);
fsm_cell->setPort("\\ARST", arst); fsm_cell->setPort("\\ARST", arst);
fsm_cell->parameters["\\CLK_POLARITY"] = clk_polarity ? RTLIL::S1 : RTLIL::S0; fsm_cell->parameters["\\CLK_POLARITY"] = clk_polarity ? State::S1 : State::S0;
fsm_cell->parameters["\\ARST_POLARITY"] = arst_polarity ? RTLIL::S1 : RTLIL::S0; fsm_cell->parameters["\\ARST_POLARITY"] = arst_polarity ? State::S1 : State::S0;
fsm_cell->setPort("\\CTRL_IN", ctrl_in); fsm_cell->setPort("\\CTRL_IN", ctrl_in);
fsm_cell->setPort("\\CTRL_OUT", ctrl_out); fsm_cell->setPort("\\CTRL_OUT", ctrl_out);
fsm_cell->parameters["\\NAME"] = RTLIL::Const(wire->name.str()); 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); cases_vector.append(and_sig);
break; break;
case 0: case 0:
cases_vector.append(RTLIL::SigSpec(1, 1)); cases_vector.append(State::S1);
break; break;
default: default:
log_abort(); log_abort();
@ -150,7 +150,7 @@ static void implement_pattern_cache(RTLIL::Module *module, std::map<RTLIL::Const
} else if (cases_vector.size() == 1) { } else if (cases_vector.size() == 1) {
module->connect(RTLIL::SigSig(output, cases_vector)); module->connect(RTLIL::SigSig(output, cases_vector));
} else { } 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; RTLIL::Cell *cell = i2.second;
if (design->has(cell->type)) if (design->has(cell->type))
continue; continue;
if (cell->type.substr(0, 1) == "$" && cell->type.substr(0, 3) != "$__") if (cell->type.begins_with("$__"))
continue; continue;
for (auto &pattern : celltypes) for (auto &pattern : celltypes)
if (patmatch(pattern.c_str(), RTLIL::unescape_id(cell->type).c_str())) 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. // Return the "basic" type for an array item.
std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) { std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) {
std::string basicType = celltype; 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_idx = celltype.find_first_of(':');
int pos_num = celltype.find_first_of(':', pos_idx + 1); int pos_num = celltype.find_first_of(':', pos_idx + 1);
int pos_type = celltype.find_first_of(':', pos_num + 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::IdString> connections_to_add_name;
std::vector<RTLIL::SigSpec> connections_to_add_signal; std::vector<RTLIL::SigSpec> connections_to_add_signal;
if (cell->type.substr(0, 7) == "$array:") { if (cell->type.begins_with("$array:")) {
int pos[3]; int pos[3];
basic_cell_type(cell->type.str(), pos); basic_cell_type(cell->type.str(), pos);
int pos_idx = pos[0]; int pos_idx = pos[0];
int pos_num = pos[1]; int pos_num = pos[1];
int pos_type = pos[2]; int pos_type = pos[2];
int idx = atoi(cell->type.str().substr(pos_idx + 1, pos_num).c_str()); int idx = atoi(cell->type.substr(pos_idx + 1, pos_num).c_str());
int num = atoi(cell->type.str().substr(pos_num + 1, pos_type).c_str()); int num = atoi(cell->type.substr(pos_num + 1, pos_type).c_str());
array_cells[cell] = std::pair<int, int>(idx, num); 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::Module*> interfaces_to_add_to_submodule;
dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_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_) { for (auto &conn : cell->connections_) {
int conn_size = conn.second.size(); int conn_size = conn.second.size();
RTLIL::IdString portname = conn.first; RTLIL::IdString portname = conn.first;
if (portname.substr(0, 1) == "$") { if (portname.begins_with("$")) {
int port_id = atoi(portname.substr(1).c_str()); int port_id = atoi(portname.substr(1).c_str());
for (auto &wire_it : mod->wires_) for (auto &wire_it : mod->wires_)
if (wire_it.second->port_id == port_id) { 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()) { for (auto cell : mod->cells()) {
std::string celltype = cell->type.str(); 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); celltype = basic_cell_type(celltype);
}
if (design->module(celltype)) if (design->module(celltype))
hierarchy_worker(design, used, design->module(celltype), indent+4); 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()) { for (auto cell : module->cells()) {
std::string celltype = cell->type.str(); std::string celltype = cell->type.str();
// Is this an array instance // Is this an array instance
if (celltype.substr(0, 7) == "$array:") { if (celltype.compare(0, strlen("$array:"), "$array:") == 0)
celltype = basic_cell_type(celltype); celltype = basic_cell_type(celltype);
}
// Is this cell a module instance? // Is this cell a module instance?
auto instModule = design->module(celltype); auto instModule = design->module(celltype);
// If there is no instance for this, issue a warning. // 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); log_assert(sig_wr_en.size() == wr_ports * memory->width);
mem->parameters["\\WR_PORTS"] = Const(wr_ports); 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_ENABLE"] = wr_ports ? sig_wr_clk_enable.as_const() : State::S0;
mem->parameters["\\WR_CLK_POLARITY"] = wr_ports ? sig_wr_clk_polarity.as_const() : Const(0, 1); 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_CLK", sig_wr_clk);
mem->setPort("\\WR_ADDR", sig_wr_addr); 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); log_assert(sig_rd_data.size() == rd_ports * memory->width);
mem->parameters["\\RD_PORTS"] = Const(rd_ports); 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_ENABLE"] = rd_ports ? sig_rd_clk_enable.as_const() : State::S0;
mem->parameters["\\RD_CLK_POLARITY"] = rd_ports ? sig_rd_clk_polarity.as_const() : Const(0, 1); 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() : Const(0, 1); mem->parameters["\\RD_TRANSPARENT"] = rd_ports ? sig_rd_transparent.as_const() : State::S0;
mem->setPort("\\RD_CLK", sig_rd_clk); mem->setPort("\\RD_CLK", sig_rd_clk);
mem->setPort("\\RD_ADDR", sig_rd_addr); 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_a[sigmap(cell->getPort("\\A"))] = cell;
mux_cells_b[sigmap(cell->getPort("\\B"))] = 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_a = cell->getPort("\\A");
SigSpec sig_y = cell->getPort("\\Y"); SigSpec sig_y = cell->getPort("\\Y");
if (cell->type == "$not") if (cell->type == "$not")

View File

@ -301,7 +301,7 @@ struct MemoryMapWorker
RTLIL::Wire *w = w_seladdr; 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"); RTLIL::Cell *c = module->addCell(genid(cell->name, "$wren", i, "", j, "", wr_offset), "$and");
c->parameters["\\A_SIGNED"] = RTLIL::Const(0); c->parameters["\\A_SIGNED"] = RTLIL::Const(0);

View File

@ -155,7 +155,7 @@ struct MemoryShareWorker
{ {
bool ignore_data_port = false; 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_a = sigmap(cell->getPort("\\A"));
std::vector<RTLIL::SigBit> sig_b = sigmap(cell->getPort("\\B")); std::vector<RTLIL::SigBit> sig_b = sigmap(cell->getPort("\\B"));
@ -173,7 +173,7 @@ struct MemoryShareWorker
continue; continue;
} }
if ((cell->type == "$memwr" || cell->type == "$memrd") && if (cell->type.in("$memwr", "$memrd") &&
cell->parameters.at("\\MEMID").decode_string() == memid) cell->parameters.at("\\MEMID").decode_string() == memid)
ignore_data_port = true; ignore_data_port = true;
@ -690,7 +690,7 @@ struct MemoryShareWorker
sigmap_xmux.add(cell->getPort("\\Y"), sig_a); 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")); std::vector<RTLIL::SigBit> sig_y = sigmap(cell->getPort("\\Y"));
for (int i = 0; i < int(sig_y.size()); i++) 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_muxtree.o
OBJS += passes/opt/opt_reduce.o OBJS += passes/opt/opt_reduce.o
OBJS += passes/opt/opt_rmdff.o OBJS += passes/opt/opt_rmdff.o
OBJS += passes/opt/opt_share.o
OBJS += passes/opt/opt_clean.o OBJS += passes/opt/opt_clean.o
OBJS += passes/opt/opt_expr.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/pmux2shiftx.o
OBJS += passes/opt/muxpack.o OBJS += passes/opt/muxpack.o
endif endif

View File

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

View File

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

View File

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

View File

@ -35,10 +35,10 @@ void demorgan_worker(
//TODO: Add support for reduce_xor //TODO: Add support for reduce_xor
//DeMorgan of XOR is either XOR (if even number of inputs) or XNOR (if odd number) //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; 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)); log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig));
int num_inverted = 0; int num_inverted = 0;
for(int i=0; i<GetSize(insig); i++) for(int i=0; i<GetSize(insig); i++)
@ -51,7 +51,7 @@ void demorgan_worker(
bool inverted = false; bool inverted = false;
for(auto x : ports) for(auto x : ports)
{ {
if(x.port == "\\Y" && x.cell->type == "$_NOT_") if(x.port == ID::Y && x.cell->type == ID($_NOT_))
{ {
inverted = true; inverted = true;
break; break;
@ -85,7 +85,7 @@ void demorgan_worker(
RTLIL::Cell* srcinv = NULL; RTLIL::Cell* srcinv = NULL;
for(auto x : ports) 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; srcinv = x.cell;
break; break;
@ -103,7 +103,7 @@ void demorgan_worker(
//We ARE inverted - bypass it //We ARE inverted - bypass it
//Don't automatically delete the inverter since other stuff might still use it //Don't automatically delete the inverter since other stuff might still use it
else 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 //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) //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 //Change the cell type
if(cell->type == "$reduce_and") if(cell->type == ID($reduce_and))
cell->type = "$reduce_or"; cell->type = ID($reduce_or);
else if(cell->type == "$reduce_or") else if(cell->type == ID($reduce_or))
cell->type = "$reduce_and"; cell->type = ID($reduce_and);
//don't change XOR //don't change XOR
//Add an inverter to the output //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); auto uninverted_output = m->addWire(NEW_ID);
m->addNot(NEW_ID, RTLIL::SigSpec(uninverted_output), inverted_output); 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 { 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) bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs)
{ {
SigSpec lut_input = sigmap(lut->getPort("\\A")); SigSpec lut_input = sigmap(lut->getPort(ID::A));
int lut_width = lut->getParam("\\WIDTH").as_int(); int lut_width = lut->getParam(ID(WIDTH)).as_int();
Const lut_table = lut->getParam("\\LUT"); Const lut_table = lut->getParam(ID(LUT));
int lut_index = 0; int lut_index = 0;
for (int i = 0; i < lut_width; i++) 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++) for (int arity = 1; arity <= max_arity; arity++)
{ {
if (arity_counts[arity]) if (arity_counts[arity])
@ -99,10 +99,16 @@ struct OptLutWorker
log("Discovering LUTs.\n"); log("Discovering LUTs.\n");
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type == "$lut") if (cell->type == ID($lut))
{ {
int lut_width = cell->getParam("\\WIDTH").as_int(); if (cell->has_keep_attr())
SigSpec lut_input = cell->getPort("\\A"); 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; int lut_arity = 0;
log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); 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(); 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]; pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut];
vector<SigBit> lut_inputs; vector<SigBit> lut_inputs;
@ -261,7 +267,7 @@ struct OptLutWorker
log_debug(" Not eliminating cell (connected to dedicated logic).\n"); log_debug(" Not eliminating cell (connected to dedicated logic).\n");
else else
{ {
SigSpec lut_output = lut->getPort("\\Y"); SigSpec lut_output = lut->getPort(ID::Y);
for (auto &port : index.query_ports(lut_output)) for (auto &port : index.query_ports(lut_output))
{ {
if (port.cell != lut && luts.count(port.cell)) if (port.cell != lut && luts.count(port.cell))
@ -297,13 +303,13 @@ struct OptLutWorker
} }
auto lutA = worklist.pop(); auto lutA = worklist.pop();
SigSpec lutA_input = sigmap(lutA->getPort("\\A")); SigSpec lutA_input = sigmap(lutA->getPort(ID::A));
SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); SigSpec lutA_output = sigmap(lutA->getPort(ID::Y)[0]);
int lutA_width = lutA->getParam("\\WIDTH").as_int(); int lutA_width = lutA->getParam(ID(WIDTH)).as_int();
int lutA_arity = luts_arity[lutA]; int lutA_arity = luts_arity[lutA];
pool<int> &lutA_dlogic_inputs = luts_dlogic_inputs[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) if (lutA_output_ports.size() != 2)
continue; continue;
@ -315,15 +321,15 @@ struct OptLutWorker
if (luts.count(port.cell)) if (luts.count(port.cell))
{ {
auto lutB = port.cell; auto lutB = port.cell;
SigSpec lutB_input = sigmap(lutB->getPort("\\A")); SigSpec lutB_input = sigmap(lutB->getPort(ID::A));
SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]); SigSpec lutB_output = sigmap(lutB->getPort(ID::Y)[0]);
int lutB_width = lutB->getParam("\\WIDTH").as_int(); int lutB_width = lutB->getParam(ID(WIDTH)).as_int();
int lutB_arity = luts_arity[lutB]; int lutB_arity = luts_arity[lutB];
pool<int> &lutB_dlogic_inputs = luts_dlogic_inputs[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)); 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"); log_debug(" Not combining LUTs (cascade connection feeds module output).\n");
continue; continue;
@ -351,14 +357,14 @@ struct OptLutWorker
int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size();
if (lutA_dlogic_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 else
log_debug(" Cell A is a %d-LUT. ", lutA_arity); log_debug(" Cell A is a %d-LUT. ", lutA_arity);
if (lutB_dlogic_inputs.size()) 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 else
log_debug("Cell B is a %d-LUT.\n", lutB_arity); 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; const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B;
int combine_mask = 0; 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"); log_debug(" Not combining LUTs into cell A (combined LUT wider than cell A).\n");
else if (lutB_dlogic_inputs.size() > 0) else if (lutB_dlogic_inputs.size() > 0)
log_debug(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); 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"); log_debug(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
else else
combine_mask |= COMBINE_A; 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"); log_debug(" Not combining LUTs into cell B (combined LUT wider than cell B).\n");
else if (lutA_dlogic_inputs.size() > 0) else if (lutA_dlogic_inputs.size() > 0)
log_debug(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); 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"); log_debug(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
else else
combine_mask |= COMBINE_B; combine_mask |= COMBINE_B;
@ -434,8 +440,8 @@ struct OptLutWorker
lutR_unique.insert(bit); lutR_unique.insert(bit);
} }
int lutM_width = lutM->getParam("\\WIDTH").as_int(); int lutM_width = lutM->getParam(ID(WIDTH)).as_int();
SigSpec lutM_input = sigmap(lutM->getPort("\\A")); SigSpec lutM_input = sigmap(lutM->getPort(ID::A));
std::vector<SigBit> lutM_new_inputs; std::vector<SigBit> lutM_new_inputs;
for (int i = 0; i < lutM_width; i++) 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); 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 A truth table: %s.\n", lutA->getParam(ID(LUT)).as_string().c_str());
log_debug(" Cell B truth table: %s.\n", lutB->getParam("\\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()); log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
lutM->setParam("\\LUT", lutM_new_table); lutM->setParam(ID(LUT), lutM_new_table);
lutM->setPort("\\A", lutM_new_inputs); lutM->setPort(ID::A, lutM_new_inputs);
lutM->setPort("\\Y", lutB_output); lutM->setPort(ID::Y, lutB_output);
luts_arity[lutM] = lutM_arity; luts_arity[lutM] = lutM_arity;
luts.erase(lutR); luts.erase(lutR);

View File

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

View File

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

View File

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

View File

@ -41,7 +41,7 @@ void remove_init_attr(SigSpec sig)
for (auto bit : assign_map(sig)) for (auto bit : assign_map(sig))
if (init_attributes.count(bit)) if (init_attributes.count(bit))
for (auto wbit : init_attributes.at(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) 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; SigSpec sig_set, sig_clr;
State pol_set, pol_clr; State pol_set, pol_clr;
if (cell->hasPort("\\S")) if (cell->hasPort(ID(S)))
sig_set = cell->getPort("\\S"); sig_set = cell->getPort(ID(S));
if (cell->hasPort("\\R")) if (cell->hasPort(ID(R)))
sig_clr = cell->getPort("\\R"); sig_clr = cell->getPort(ID(R));
if (cell->hasPort("\\SET")) if (cell->hasPort(ID(SET)))
sig_set = cell->getPort("\\SET"); sig_set = cell->getPort(ID(SET));
if (cell->hasPort("\\CLR")) if (cell->hasPort(ID(CLR)))
sig_clr = cell->getPort("\\CLR"); sig_clr = cell->getPort(ID(CLR));
log_assert(GetSize(sig_set) == GetSize(sig_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_set = cell->type[9] == 'P' ? State::S1 : State::S0;
pol_clr = cell->type[10] == 'P' ? State::S1 : State::S0; pol_clr = cell->type[10] == 'P' ? State::S1 : State::S0;
} else } 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_set = cell->type[12] == 'P' ? State::S1 : State::S0;
pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0; pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0;
} else } else
if (cell->type == "$dffsr" || cell->type == "$dlatchsr") { if (cell->type.in(ID($dffsr), ID($dlatchsr))) {
pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0; pol_set = cell->parameters[ID(SET_POLARITY)].as_bool() ? State::S1 : State::S0;
pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0; pol_clr = cell->parameters[ID(CLR_POLARITY)].as_bool() ? State::S1 : State::S0;
} else } else
log_abort(); log_abort();
State npol_set = pol_set == State::S0 ? State::S1 : State::S0; State npol_set = pol_set == State::S0 ? State::S1 : State::S0;
State npol_clr = pol_clr == 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_d = cell->getPort(ID(D));
SigSpec sig_q = cell->getPort("\\Q"); SigSpec sig_q = cell->getPort(ID(Q));
bool did_something = false; bool did_something = false;
bool proper_sr = false; bool proper_sr = false;
@ -137,20 +137,20 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
return true; return true;
} }
if (cell->type == "$dffsr" || cell->type == "$dlatchsr") if (cell->type.in(ID($dffsr), ID($dlatchsr)))
{ {
cell->setParam("\\WIDTH", GetSize(sig_d)); cell->setParam(ID(WIDTH), GetSize(sig_d));
cell->setPort("\\SET", sig_set); cell->setPort(ID(SET), sig_set);
cell->setPort("\\CLR", sig_clr); cell->setPort(ID(CLR), sig_clr);
cell->setPort("\\D", sig_d); cell->setPort(ID(D), sig_d);
cell->setPort("\\Q", sig_q); cell->setPort(ID(Q), sig_q);
} }
else else
{ {
cell->setPort("\\S", sig_set); cell->setPort(ID(S), sig_set);
cell->setPort("\\R", sig_clr); cell->setPort(ID(R), sig_clr);
cell->setPort("\\D", sig_d); cell->setPort(ID(D), sig_d);
cell->setPort("\\Q", sig_q); cell->setPort(ID(Q), sig_q);
} }
if (proper_sr) 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) if (used_pol_set && used_pol_clr && pol_set != pol_clr)
return did_something; return did_something;
if (cell->type == "$dlatchsr") if (cell->type == ID($dlatchsr))
return did_something; return did_something;
State unified_pol = used_pol_set ? pol_set : pol_clr; State unified_pol = used_pol_set ? pol_set : pol_clr;
if (cell->type == "$dffsr") if (cell->type == ID($dffsr))
{ {
if (hasreset) if (hasreset)
{ {
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod)); 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->type = ID($adff);
cell->setParam("\\ARST_POLARITY", unified_pol); cell->setParam(ID(ARST_POLARITY), unified_pol);
cell->setParam("\\ARST_VALUE", reset_val); cell->setParam(ID(ARST_VALUE), reset_val);
cell->setPort("\\ARST", sig_reset); cell->setPort(ID(ARST), sig_reset);
cell->unsetParam("\\SET_POLARITY"); cell->unsetParam(ID(SET_POLARITY));
cell->unsetParam("\\CLR_POLARITY"); cell->unsetParam(ID(CLR_POLARITY));
cell->unsetPort("\\SET"); cell->unsetPort(ID(SET));
cell->unsetPort("\\CLR"); cell->unsetPort(ID(CLR));
} }
else else
{ {
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod)); 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->type = ID($dff);
cell->unsetParam("\\SET_POLARITY"); cell->unsetParam(ID(SET_POLARITY));
cell->unsetParam("\\CLR_POLARITY"); cell->unsetParam(ID(CLR_POLARITY));
cell->unsetPort("\\SET"); cell->unsetPort(ID(SET));
cell->unsetPort("\\CLR"); cell->unsetPort(ID(CLR));
} }
return true; return true;
@ -198,9 +198,9 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
{ {
IdString new_type; IdString new_type;
if (cell->type.substr(0,8) == "$_DFFSR_") if (cell->type.begins_with("$_DFFSR_"))
new_type = stringf("$_DFF_%c_", cell->type[8]); 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]); new_type = stringf("$_DLATCH_%c_", cell->type[11]);
else else
log_abort(); 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)); 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->type = new_type;
cell->unsetPort("\\S"); cell->unsetPort(ID(S));
cell->unsetPort("\\R"); cell->unsetPort(ID(R));
return true; return true;
} }
@ -222,18 +222,18 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
SigSpec sig_e; SigSpec sig_e;
State on_state, off_state; State on_state, off_state;
if (dlatch->type == "$dlatch") { if (dlatch->type == ID($dlatch)) {
sig_e = assign_map(dlatch->getPort("\\EN")); sig_e = assign_map(dlatch->getPort(ID(EN)));
on_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S1 : State::S0; on_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S1 : State::S0;
off_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S0 : State::S1; off_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S0 : State::S1;
} else } else
if (dlatch->type == "$_DLATCH_P_") { if (dlatch->type == ID($_DLATCH_P_)) {
sig_e = assign_map(dlatch->getPort("\\E")); sig_e = assign_map(dlatch->getPort(ID(E)));
on_state = State::S1; on_state = State::S1;
off_state = State::S0; off_state = State::S0;
} else } else
if (dlatch->type == "$_DLATCH_N_") { if (dlatch->type == ID($_DLATCH_N_)) {
sig_e = assign_map(dlatch->getPort("\\E")); sig_e = assign_map(dlatch->getPort(ID(E)));
on_state = State::S0; on_state = State::S0;
off_state = State::S1; off_state = State::S1;
} else } else
@ -242,15 +242,15 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
if (sig_e == off_state) if (sig_e == off_state)
{ {
RTLIL::Const val_init; 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); 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; goto delete_dlatch;
} }
if (sig_e == on_state) 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; goto delete_dlatch;
} }
@ -258,7 +258,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
delete_dlatch: delete_dlatch:
log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod)); 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); mod->remove(dlatch);
return true; 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::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e;
RTLIL::Const val_cp, val_rp, val_rv, val_ep; RTLIL::Const val_cp, val_rp, val_rv, val_ep;
if (dff->type == "$_FF_") { if (dff->type == ID($_FF_)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
} }
else if (dff->type == "$_DFF_N_" || dff->type == "$_DFF_P_") { else if (dff->type == ID($_DFF_N_) || dff->type == ID($_DFF_P_)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\C"); sig_c = dff->getPort(ID(C));
val_cp = RTLIL::Const(dff->type == "$_DFF_P_", 1); 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[6] == 'N' || dff->type[6] == 'P') &&
(dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[7] == 'N' || dff->type[7] == 'P') &&
(dff->type[8] == '0' || dff->type[8] == '1')) { (dff->type[8] == '0' || dff->type[8] == '1')) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\C"); sig_c = dff->getPort(ID(C));
sig_r = dff->getPort("\\R"); sig_r = dff->getPort(ID(R));
val_cp = RTLIL::Const(dff->type[6] == 'P', 1); val_cp = RTLIL::Const(dff->type[6] == 'P', 1);
val_rp = RTLIL::Const(dff->type[7] == 'P', 1); val_rp = RTLIL::Const(dff->type[7] == 'P', 1);
val_rv = RTLIL::Const(dff->type[8] == '1', 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[7] == 'N' || dff->type[7] == 'P') &&
(dff->type[8] == 'N' || dff->type[8] == 'P')) { (dff->type[8] == 'N' || dff->type[8] == 'P')) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\C"); sig_c = dff->getPort(ID(C));
sig_e = dff->getPort("\\E"); sig_e = dff->getPort(ID(E));
val_cp = RTLIL::Const(dff->type[7] == 'P', 1); val_cp = RTLIL::Const(dff->type[7] == 'P', 1);
val_ep = RTLIL::Const(dff->type[8] == 'P', 1); val_ep = RTLIL::Const(dff->type[8] == 'P', 1);
} }
else if (dff->type == "$ff") { else if (dff->type == ID($ff)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
} }
else if (dff->type == "$dff") { else if (dff->type == ID($dff)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\CLK"); sig_c = dff->getPort(ID(CLK));
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
} }
else if (dff->type == "$dffe") { else if (dff->type == ID($dffe)) {
sig_e = dff->getPort("\\EN"); sig_e = dff->getPort(ID(EN));
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\CLK"); sig_c = dff->getPort(ID(CLK));
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1); val_ep = RTLIL::Const(dff->parameters[ID(EN_POLARITY)].as_bool(), 1);
} }
else if (dff->type == "$adff") { else if (dff->type == ID($adff)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\CLK"); sig_c = dff->getPort(ID(CLK));
sig_r = dff->getPort("\\ARST"); sig_r = dff->getPort(ID(ARST));
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
val_rp = RTLIL::Const(dff->parameters["\\ARST_POLARITY"].as_bool(), 1); val_rp = RTLIL::Const(dff->parameters[ID(ARST_POLARITY)].as_bool(), 1);
val_rv = dff->parameters["\\ARST_VALUE"]; val_rv = dff->parameters[ID(ARST_VALUE)];
} }
else else
log_abort(); 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); 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; std::set<RTLIL::Cell*> muxes;
mux_drivers.find(sig_d, muxes); mux_drivers.find(sig_d, muxes);
for (auto mux : muxes) { for (auto mux : muxes) {
RTLIL::SigSpec sig_a = assign_map(mux->getPort("\\A")); RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID::A));
RTLIL::SigSpec sig_b = assign_map(mux->getPort("\\B")); 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())) { if (sig_a == sig_q && sig_b.is_fully_const() && (!has_init || val_init == sig_b.as_const())) {
mod->connect(sig_q, sig_b); mod->connect(sig_q, sig_b);
goto delete_dff; 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)); 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") { if (dff->type == ID($adff)) {
dff->type = "$dff"; dff->type = ID($dff);
dff->unsetPort("\\ARST"); dff->unsetPort(ID(ARST));
dff->unsetParam("\\ARST_POLARITY"); dff->unsetParam(ID(ARST_POLARITY));
dff->unsetParam("\\ARST_VALUE"); dff->unsetParam(ID(ARST_VALUE));
return true; 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->type = stringf("$_DFF_%c_", + dff->type[6]);
dff->unsetPort("\\R"); dff->unsetPort(ID(R));
} }
// If enable signal is present, and is fully constant // 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)); 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") { if (dff->type == ID($dffe)) {
dff->type = "$dff"; dff->type = ID($dff);
dff->unsetPort("\\EN"); dff->unsetPort(ID(EN));
dff->unsetParam("\\EN_POLARITY"); dff->unsetParam(ID(EN_POLARITY));
return true; 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->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)) 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, 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)); 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; tmp[position] = sigbit_init_val;
dff->setPort("\\D", tmp); dff->setPort(ID(D), tmp);
removed_sigbits = true; removed_sigbits = true;
} }
@ -528,7 +528,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
delete_dff: delete_dff:
log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); 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); mod->remove(dff);
for (auto &entry : bit2driver) for (auto &entry : bit2driver)
@ -588,8 +588,8 @@ struct OptRmdffPass : public Pass {
for (auto wire : module->wires()) for (auto wire : module->wires())
{ {
if (wire->attributes.count("\\init") != 0) { if (wire->attributes.count(ID(init)) != 0) {
Const initval = wire->attributes.at("\\init"); Const initval = wire->attributes.at(ID(init));
for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++)
if (initval[i] == State::S0 || initval[i] == State::S1) if (initval[i] == State::S0 || initval[i] == State::S1)
dff_init_map.add(SigBit(wire, i), initval[i]); 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->type.in(ID($mux), ID($pmux))) {
if (cell->getPort("\\A").size() == cell->getPort("\\B").size()) if (cell->getPort(ID::A).size() == cell->getPort(ID::B).size())
mux_drivers.insert(assign_map(cell->getPort("\\Y")), cell); mux_drivers.insert(assign_map(cell->getPort(ID::Y)), cell);
continue; continue;
} }
if (!design->selected(module, cell)) if (!design->selected(module, cell))
continue; continue;
if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_", if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_", "$dffsr", ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), ID($dffsr),
"$_DLATCHSR_NNN_", "$_DLATCHSR_NNP_", "$_DLATCHSR_NPN_", "$_DLATCHSR_NPP_", ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
"$_DLATCHSR_PNN_", "$_DLATCHSR_PNP_", "$_DLATCHSR_PPN_", "$_DLATCHSR_PPP_", "$dlatchsr")) ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), ID($dlatchsr)))
dffsr_list.push_back(cell->name); dffsr_list.push_back(cell->name);
if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_", if (cell->type.in(ID($_FF_), ID($_DFF_N_), ID($_DFF_P_),
"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_", ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
"$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_", ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
"$ff", "$dff", "$dffe", "$adff")) ID($ff), ID($dff), ID($dffe), ID($adff)))
dff_list.push_back(cell->name); 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); 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()) for (auto wire : module->wires())
{ {
auto it = wire->attributes.find("\\init"); auto it = wire->attributes.find(ID(init));
if (it == wire->attributes.end()) if (it == wire->attributes.end())
continue; continue;
@ -63,19 +63,19 @@ struct OnehotDatabase
vector<SigSpec> inputs; vector<SigSpec> inputs;
SigSpec output; 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"); output = cell->getPort(ID(Q));
if (cell->type == "$adff") if (cell->type == ID($adff))
inputs.push_back(cell->getParam("\\ARST_VALUE")); inputs.push_back(cell->getParam(ID(ARST_VALUE)));
inputs.push_back(cell->getPort("\\D")); 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"); output = cell->getPort(ID::Y);
inputs.push_back(cell->getPort("\\A")); inputs.push_back(cell->getPort(ID::A));
SigSpec B = cell->getPort("\\B"); SigSpec B = cell->getPort(ID::B);
for (int i = 0; i < GetSize(B); i += GetSize(output)) for (int i = 0; i < GetSize(B); i += GetSize(output))
inputs.push_back(B.extract(i, GetSize(output))); inputs.push_back(B.extract(i, GetSize(output)));
} }
@ -292,23 +292,23 @@ struct Pmux2ShiftxPass : public Pass {
for (auto cell : module->cells()) for (auto cell : module->cells())
{ {
if (cell->type == "$eq") if (cell->type == ID($eq))
{ {
dict<SigBit, State> bits; dict<SigBit, State> bits;
SigSpec A = sigmap(cell->getPort("\\A")); SigSpec A = sigmap(cell->getPort(ID::A));
SigSpec B = sigmap(cell->getPort("\\B")); SigSpec B = sigmap(cell->getPort(ID::B));
int a_width = cell->getParam("\\A_WIDTH").as_int(); int a_width = cell->getParam(ID(A_WIDTH)).as_int();
int b_width = cell->getParam("\\B_WIDTH").as_int(); int b_width = cell->getParam(ID(B_WIDTH)).as_int();
if (a_width < b_width) { 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); A.extend_u0(b_width, a_signed);
} }
if (b_width < a_width) { 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); B.extend_u0(a_width, b_signed);
} }
@ -335,15 +335,15 @@ struct Pmux2ShiftxPass : public Pass {
entry.second.bits.push_back(it.second); 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; goto next_cell;
} }
if (cell->type == "$logic_not") if (cell->type == ID($logic_not))
{ {
dict<SigBit, State> bits; 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++) for (int i = 0; i < GetSize(A); i++)
bits[A[i]] = State::S0; bits[A[i]] = State::S0;
@ -356,7 +356,7 @@ struct Pmux2ShiftxPass : public Pass {
entry.second.bits.push_back(it.second); 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; goto next_cell;
} }
next_cell:; next_cell:;
@ -364,11 +364,11 @@ struct Pmux2ShiftxPass : public Pass {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type != "$pmux") if (cell->type != ID($pmux))
continue; continue;
string src = cell->get_src_attribute(); 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 width_bits = ceil_log2(width);
int extwidth = width; int extwidth = width;
@ -377,9 +377,9 @@ struct Pmux2ShiftxPass : public Pass {
dict<SigSpec, pool<int>> seldb; dict<SigSpec, pool<int>> seldb;
SigSpec A = cell->getPort("\\A"); SigSpec A = cell->getPort(ID::A);
SigSpec B = cell->getPort("\\B"); SigSpec B = cell->getPort(ID::B);
SigSpec S = sigmap(cell->getPort("\\S")); SigSpec S = sigmap(cell->getPort(ID(S)));
for (int i = 0; i < GetSize(S); i++) for (int i = 0; i < GetSize(S); i++)
{ {
if (!eqdb.count(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); log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits);
} }
SigSpec updated_S = cell->getPort("\\S"); SigSpec updated_S = cell->getPort(ID(S));
SigSpec updated_B = cell->getPort("\\B"); SigSpec updated_B = cell->getPort(ID::B);
while (!seldb.empty()) while (!seldb.empty())
{ {
@ -727,9 +727,9 @@ struct Pmux2ShiftxPass : public Pass {
} }
// update $pmux cell // update $pmux cell
cell->setPort("\\S", updated_S); cell->setPort(ID(S), updated_S);
cell->setPort("\\B", updated_B); cell->setPort(ID::B, updated_B);
cell->setParam("\\S_WIDTH", GetSize(updated_S)); cell->setParam(ID(S_WIDTH), GetSize(updated_S));
} }
} }
} }
@ -779,22 +779,22 @@ struct OnehotPass : public Pass {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type != "$eq") if (cell->type != ID($eq))
continue; continue;
SigSpec A = sigmap(cell->getPort("\\A")); SigSpec A = sigmap(cell->getPort(ID::A));
SigSpec B = sigmap(cell->getPort("\\B")); SigSpec B = sigmap(cell->getPort(ID::B));
int a_width = cell->getParam("\\A_WIDTH").as_int(); int a_width = cell->getParam(ID(A_WIDTH)).as_int();
int b_width = cell->getParam("\\B_WIDTH").as_int(); int b_width = cell->getParam(ID(B_WIDTH)).as_int();
if (a_width < b_width) { 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); A.extend_u0(b_width, a_signed);
} }
if (b_width < a_width) { 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); B.extend_u0(a_width, b_signed);
} }
@ -830,7 +830,7 @@ struct OnehotPass : public Pass {
continue; continue;
} }
SigSpec Y = cell->getPort("\\Y"); SigSpec Y = cell->getPort(ID::Y);
if (not_onehot) if (not_onehot)
{ {

View File

@ -171,7 +171,7 @@ struct RmportsPassPass : public Pass {
wire->port_output = false; wire->port_output = false;
wire->port_id = 0; 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 // Re-number all of the wires that DO have ports still on them
for(size_t i=0; i<module->ports.size(); i++) for(size_t i=0; i<module->ports.size(); i++)

View File

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

View File

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

View File

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

View File

@ -1,4 +1,5 @@
OBJS += passes/pmgen/ice40_dsp.o OBJS += passes/pmgen/ice40_dsp.o
OBJS += passes/pmgen/ice40_wrapcarry.o
OBJS += passes/pmgen/peepopt.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 passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
EXTRA_OBJS += passes/pmgen/peepopt_pm.h EXTRA_OBJS += passes/pmgen/peepopt_pm.h
.SECONDARY: 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); 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").is_fully_const()) {
if (!cell->getPort("\\A").as_bool()) if (!cell->getPort("\\A").as_bool())
polarity = !polarity; 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").is_fully_const()) {
if (cell->getPort("\\A").as_bool()) if (cell->getPort("\\A").as_bool())
polarity = !polarity; polarity = !polarity;

View File

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

View File

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

View File

@ -143,7 +143,7 @@ void create_dff_dq_map(std::map<RTLIL::IdString, dff_map_info_t> &map, RTLIL::De
continue; 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.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit();
info.clk_polarity = info.cell->type == "$_DFF_P_"; info.clk_polarity = info.cell->type == "$_DFF_P_";
info.bit_d = sigmap(info.cell->getPort("\\D")).as_bit(); 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; 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_clk = sigmap(info.cell->getPort("\\C")).as_bit();
info.bit_arst = sigmap(info.cell->getPort("\\R")).as_bit(); info.bit_arst = sigmap(info.cell->getPort("\\R")).as_bit();
info.clk_polarity = info.cell->type[6] == 'P'; 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; 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"); that->cmd_error(args, argidx, "command argument error");
RTLIL::IdString gold_name = RTLIL::escape_id(args[argidx++]); 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) { if (flag_make_assert) {
RTLIL::Cell *assert_cell = miter_module->addCell(NEW_ID, "$assert"); RTLIL::Cell *assert_cell = miter_module->addCell(NEW_ID, "$assert");
assert_cell->setPort("\\A", all_conditions); 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"); 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; 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"); that->cmd_error(args, argidx, "command argument error");
IdString module_name = RTLIL::escape_id(args[argidx++]); IdString module_name = RTLIL::escape_id(args[argidx++]);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -83,13 +83,13 @@ struct DeminoutPass : public Pass {
for (auto bit : sigmap(conn.second)) for (auto bit : sigmap(conn.second))
bits_used.insert(bit); 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) { if (!tribuf) {
for (auto &c : cell->connections()) { for (auto &c : cell->connections()) {
if (!c.first.in("\\A", "\\B")) if (!c.first.in(ID::A, ID::B))
continue; continue;
for (auto b : sigmap(c.second)) for (auto b : sigmap(c.second))
if (b == State::Sz) if (b == State::Sz)

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