mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'origin/master' into eddie/synth_xilinx
This commit is contained in:
commit
d9fe4cccbf
42
.travis.yml
42
.travis.yml
|
@ -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
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
68
Dockerfile
68
Dockerfile
|
@ -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"]
|
||||||
|
|
19
Makefile
19
Makefile
|
@ -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
|
||||||
|
|
73
README.md
73
README.md
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -726,20 +725,26 @@ struct XAigerWriter
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,80 +491,120 @@ 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
|
||||||
|
if (a_width < y_width) {
|
||||||
|
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
|
||||||
|
a_width = y_width;
|
||||||
}
|
}
|
||||||
// Shift amount is always unsigned, and needn't be padded to result width.
|
}
|
||||||
if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) {
|
// Shift amount is always unsigned, and needn't be padded to result width,
|
||||||
if (cell->parameters.at("\\B_SIGNED").as_bool()) {
|
// 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 + ")";
|
b_expr = "asSInt(" + b_expr + ")";
|
||||||
}
|
// Expand the "B" operand to the result width
|
||||||
if (b_padded_width < y_width) {
|
if (b_width < y_width) {
|
||||||
auto b_sig = cell->getPort("\\B");
|
b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
|
||||||
b_padded_width = 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);
|
||||||
string primop;
|
} else if (cell->type == "$sub") {
|
||||||
bool always_uint = false;
|
primop = "sub";
|
||||||
if (cell->type == "$add") primop = "add";
|
firrtl_is_signed = true;
|
||||||
else if (cell->type == "$sub") primop = "sub";
|
int a_widthInc = (!a_signed && b_signed) ? 2 : (a_signed && !b_signed) ? 1 : 0;
|
||||||
else if (cell->type == "$mul") primop = "mul";
|
int b_widthInc = (a_signed && !b_signed) ? 2 : (!a_signed && b_signed) ? 1 : 0;
|
||||||
else if (cell->type == "$div") primop = "div";
|
firrtl_width = max(a_width + a_widthInc, b_width + b_widthInc);
|
||||||
else if (cell->type == "$mod") primop = "rem";
|
} else if (cell->type == "$mul") {
|
||||||
else if (cell->type == "$and") {
|
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";
|
primop = "and";
|
||||||
always_uint = true;
|
always_uint = true;
|
||||||
|
firrtl_width = max(a_width, b_width);
|
||||||
}
|
}
|
||||||
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.
|
||||||
|
@ -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,9 +631,19 @@ 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")) {
|
||||||
|
@ -588,26 +651,66 @@ struct FirrtlWorker
|
||||||
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())
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> ¶meters, bool for_module=false)
|
void write_parameters(const dict<IdString, Const> ¶meters, bool for_module=false)
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto ¶m : parameters) {
|
for (auto ¶m : 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");
|
||||||
|
|
|
@ -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) +
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")),
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
@ -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 ;
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,7 +3630,6 @@ 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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_))
|
||||||
}
|
|
||||||
goto optimize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool"))
|
|
||||||
{
|
|
||||||
int Y = mk.inport("\\A", 0);
|
|
||||||
for (int i = 1; i < GetSize(cell->getPort("\\A")); i++) {
|
|
||||||
int A = mk.inport("\\A", i);
|
|
||||||
if (cell->type == "$reduce_and") Y = mk.and_gate(A, Y);
|
|
||||||
if (cell->type == "$reduce_or") Y = mk.or_gate(A, Y);
|
|
||||||
if (cell->type == "$reduce_bool") Y = mk.or_gate(A, Y);
|
|
||||||
if (cell->type == "$reduce_xor") Y = mk.xor_gate(A, Y);
|
|
||||||
if (cell->type == "$reduce_xnor") Y = mk.xor_gate(A, Y);
|
|
||||||
}
|
|
||||||
if (cell->type == "$reduce_xnor")
|
|
||||||
Y = mk.not_gate(Y);
|
Y = mk.not_gate(Y);
|
||||||
mk.outport(Y, "\\Y", 0);
|
mk.outport(Y, ID::Y, i);
|
||||||
for (int i = 1; i < GetSize(cell->getPort("\\Y")); i++)
|
}
|
||||||
mk.outport(mk.bool_node(false), "\\Y", i);
|
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in("$logic_not", "$logic_and", "$logic_or"))
|
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool)))
|
||||||
{
|
{
|
||||||
int A = mk.inport("\\A", 0), Y = -1;
|
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++) {
|
||||||
A = mk.or_gate(mk.inport("\\A", i), A);
|
int A = mk.inport(ID::A, i);
|
||||||
if (cell->type.in("$logic_and", "$logic_or")) {
|
if (cell->type == ID($reduce_and)) Y = mk.and_gate(A, Y);
|
||||||
int B = mk.inport("\\B", 0);
|
if (cell->type == ID($reduce_or)) Y = mk.or_gate(A, Y);
|
||||||
for (int i = 1; i < GetSize(cell->getPort("\\B")); i++)
|
if (cell->type == ID($reduce_bool)) Y = mk.or_gate(A, Y);
|
||||||
B = mk.or_gate(mk.inport("\\B", i), B);
|
if (cell->type == ID($reduce_xor)) Y = mk.xor_gate(A, Y);
|
||||||
if (cell->type == "$logic_and") Y = mk.and_gate(A, B);
|
if (cell->type == ID($reduce_xnor)) Y = mk.xor_gate(A, Y);
|
||||||
if (cell->type == "$logic_or") Y = mk.or_gate(A, B);
|
}
|
||||||
|
if (cell->type == ID($reduce_xnor))
|
||||||
|
Y = mk.not_gate(Y);
|
||||||
|
mk.outport(Y, ID::Y, 0);
|
||||||
|
for (int i = 1; i < GetSize(cell->getPort(ID::Y)); i++)
|
||||||
|
mk.outport(mk.bool_node(false), ID::Y, i);
|
||||||
|
goto optimize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or)))
|
||||||
|
{
|
||||||
|
int A = mk.inport(ID::A, 0), Y = -1;
|
||||||
|
for (int i = 1; i < GetSize(cell->getPort(ID::A)); i++)
|
||||||
|
A = mk.or_gate(mk.inport(ID::A, i), A);
|
||||||
|
if (cell->type.in(ID($logic_and), ID($logic_or))) {
|
||||||
|
int B = mk.inport(ID::B, 0);
|
||||||
|
for (int i = 1; i < GetSize(cell->getPort(ID::B)); i++)
|
||||||
|
B = mk.or_gate(mk.inport(ID::B, i), B);
|
||||||
|
if (cell->type == ID($logic_and)) Y = mk.and_gate(A, B);
|
||||||
|
if (cell->type == ID($logic_or)) Y = mk.or_gate(A, B);
|
||||||
} else {
|
} 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,6 +175,9 @@ 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;
|
||||||
|
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());
|
y_values.push_back(yc.as_const());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
|
124
kernel/cost.h
124
kernel/cost.h
|
@ -24,63 +24,93 @@
|
||||||
|
|
||||||
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> ¶meters = 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 }
|
||||||
};
|
};
|
||||||
|
return db;
|
||||||
if (gate_cost.count(type))
|
|
||||||
return gate_cost.at(type);
|
|
||||||
|
|
||||||
if (parameters.empty() && design && design->module(type))
|
|
||||||
{
|
|
||||||
RTLIL::Module *mod = design->module(type);
|
|
||||||
|
|
||||||
if (mod->attributes.count("\\cost"))
|
|
||||||
return mod->attributes.at("\\cost").as_int();
|
|
||||||
|
|
||||||
dict<RTLIL::IdString, int> local_mod_cost_cache;
|
|
||||||
if (mod_cost_cache == nullptr)
|
|
||||||
mod_cost_cache = &local_mod_cost_cache;
|
|
||||||
|
|
||||||
if (mod_cost_cache->count(mod->name))
|
|
||||||
return mod_cost_cache->at(mod->name);
|
|
||||||
|
|
||||||
int module_cost = 1;
|
|
||||||
for (auto c : mod->cells())
|
|
||||||
module_cost += get_cell_cost(c, mod_cost_cache);
|
|
||||||
|
|
||||||
(*mod_cost_cache)[mod->name] = module_cost;
|
|
||||||
return module_cost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
dict<RTLIL::IdString, int> mod_cost_cache;
|
||||||
|
const dict<RTLIL::IdString, int> *gate_cost = nullptr;
|
||||||
|
Design *design = nullptr;
|
||||||
|
|
||||||
|
int get(RTLIL::IdString type) const
|
||||||
|
{
|
||||||
|
if (gate_cost && gate_cost->count(type))
|
||||||
|
return gate_cost->at(type);
|
||||||
|
|
||||||
|
log_warning("Can't determine cost of %s cell.\n", log_id(type));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache)
|
int get(RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache);
|
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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,6 +625,19 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
|
||||||
|
|
||||||
filename = arg;
|
filename = arg;
|
||||||
rewrite_filename(filename);
|
rewrite_filename(filename);
|
||||||
|
if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".gz") == 0) {
|
||||||
|
#ifdef YOSYS_ENABLE_ZLIB
|
||||||
|
gzip_ostream *gf = new gzip_ostream;
|
||||||
|
if (!gf->open(filename)) {
|
||||||
|
delete gf;
|
||||||
|
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
|
||||||
|
}
|
||||||
|
yosys_output_files.insert(filename);
|
||||||
|
f = gf;
|
||||||
|
#else
|
||||||
|
log_cmd_error("Yosys is compiled without zlib support, unable to write gzip output.\n");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
std::ofstream *ff = new std::ofstream;
|
std::ofstream *ff = new std::ofstream;
|
||||||
ff->open(filename.c_str(), std::ofstream::trunc);
|
ff->open(filename.c_str(), std::ofstream::trunc);
|
||||||
yosys_output_files.insert(filename);
|
yosys_output_files.insert(filename);
|
||||||
|
@ -555,6 +647,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
|
||||||
}
|
}
|
||||||
f = ff;
|
f = ff;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (called_with_fp)
|
if (called_with_fp)
|
||||||
args.push_back(filename);
|
args.push_back(filename);
|
||||||
|
@ -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 {
|
||||||
|
|
1169
kernel/rtlil.cc
1169
kernel/rtlil.cc
File diff suppressed because it is too large
Load Diff
163
kernel/rtlil.h
163
kernel/rtlil.h
|
@ -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]; }
|
||||||
|
|
522
kernel/satgen.h
522
kernel/satgen.h
File diff suppressed because it is too large
Load Diff
|
@ -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");
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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}
|
||||||
|
|
||||||
|
|
|
@ -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! */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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 += " ";
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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++)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 ®s, 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())
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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++)
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
/ice40_dsp_pm.h
|
/*_pm.h
|
||||||
/peepopt_pm.h
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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++]);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,7 +1407,9 @@ 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");
|
||||||
|
@ -1409,12 +1417,17 @@ struct AbcPass : public Pass {
|
||||||
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(" cmos: NAND NOR AOI3 OAI3 AOI4 OAI4 NMUX MUX XOR XNOR\n");
|
||||||
log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
|
log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
|
||||||
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n");
|
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" The alias 'all' represent the full set of all gate types.\n");
|
||||||
|
log("\n");
|
||||||
log(" Prefix a gate type with a '-' to remove it from the list. For example\n");
|
log(" 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;
|
||||||
|
|
|
@ -71,11 +71,9 @@ 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)
|
||||||
|
@ -89,7 +87,7 @@ void handle_loops(RTLIL::Design *design)
|
||||||
// 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;
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue