mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into eddie/synth_xilinx
This commit is contained in:
		
						commit
						d9fe4cccbf
					
				
					 191 changed files with 6974 additions and 4473 deletions
				
			
		
							
								
								
									
										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; | ||||||
|  |  | ||||||
							
								
								
									
										8
									
								
								examples/mimas2/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								examples/mimas2/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | A simple example design, based on the Numato Labs Mimas V2 board | ||||||
|  | ================================================================ | ||||||
|  | 
 | ||||||
|  | This example uses Yosys for synthesis and Xilinx ISE | ||||||
|  | for place&route and bit-stream creation. | ||||||
|  | 
 | ||||||
|  | To synthesize: | ||||||
|  |   bash run.sh | ||||||
							
								
								
									
										13
									
								
								examples/mimas2/example.ucf
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								examples/mimas2/example.ucf
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | CONFIG VCCAUX = "3.3" ; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | NET "CLK"                   LOC = D9      | IOSTANDARD = LVCMOS33 | PERIOD = 12MHz ; | ||||||
|  | 
 | ||||||
|  | NET "LED[7]"                     LOC = P15     | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | ||||||
|  | NET "LED[6]"                     LOC = P16     | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | ||||||
|  | NET "LED[5]"                     LOC = N15     | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | ||||||
|  | NET "LED[4]"                     LOC = N16     | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | ||||||
|  | NET "LED[3]"                     LOC = U17     | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | ||||||
|  | NET "LED[2]"                     LOC = U18     | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | ||||||
|  | NET "LED[1]"                     LOC = T17     | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | ||||||
|  | NET "LED[0]"                     LOC = T18     | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | ||||||
							
								
								
									
										14
									
								
								examples/mimas2/example.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								examples/mimas2/example.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | module example( | ||||||
|  | 	input wire CLK, | ||||||
|  | 	output wire [7:0] LED | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | reg [27:0] ctr; | ||||||
|  | initial ctr = 0; | ||||||
|  | 
 | ||||||
|  | always @(posedge CLK) | ||||||
|  | 	ctr <= ctr + 1; | ||||||
|  | 
 | ||||||
|  | assign LED = ctr[27:20]; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
							
								
								
									
										8
									
								
								examples/mimas2/run.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								examples/mimas2/run.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | #!/bin/sh | ||||||
|  | set -e | ||||||
|  | yosys run_yosys.ys | ||||||
|  | edif2ngd example.edif | ||||||
|  | ngdbuild example -uc example.ucf -p xc6slx9csg324-3 | ||||||
|  | map -w example | ||||||
|  | par -w example.ncd example_par.ncd | ||||||
|  | bitgen -w example_par.ncd -g StartupClk:JTAGClk | ||||||
							
								
								
									
										4
									
								
								examples/mimas2/run_yosys.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								examples/mimas2/run_yosys.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | read_verilog example.v | ||||||
|  | synth_xilinx -top example -family xc6s | ||||||
|  | iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I | ||||||
|  | write_edif -pvector bra example.edif | ||||||
|  | @ -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); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										649
									
								
								passes/opt/opt_share.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										649
									
								
								passes/opt/opt_share.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,649 @@ | ||||||
|  | /*
 | ||||||
|  |  *  yosys -- Yosys Open SYnthesis Suite | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||||
|  |  *                2019  Bogdan Vukobratovic <bogdan.vukobratovic@gmail.com> | ||||||
|  |  * | ||||||
|  |  *  Permission to use, copy, modify, and/or distribute this software for any | ||||||
|  |  *  purpose with or without fee is hereby granted, provided that the above | ||||||
|  |  *  copyright notice and this permission notice appear in all copies. | ||||||
|  |  * | ||||||
|  |  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  |  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  |  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  |  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  |  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  |  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  |  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "kernel/log.h" | ||||||
|  | #include "kernel/register.h" | ||||||
|  | #include "kernel/rtlil.h" | ||||||
|  | #include "kernel/sigtools.h" | ||||||
|  | #include <algorithm> | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | 
 | ||||||
|  | USING_YOSYS_NAMESPACE | ||||||
|  | PRIVATE_NAMESPACE_BEGIN | ||||||
|  | 
 | ||||||
|  | SigMap assign_map; | ||||||
|  | 
 | ||||||
|  | struct OpMuxConn { | ||||||
|  | 	RTLIL::SigSpec sig; | ||||||
|  | 	RTLIL::Cell *mux; | ||||||
|  | 	RTLIL::Cell *op; | ||||||
|  | 	int mux_port_id; | ||||||
|  | 	int mux_port_offset; | ||||||
|  | 	int op_outsig_offset; | ||||||
|  | 
 | ||||||
|  | 	bool operator<(const OpMuxConn &other) const | ||||||
|  | 	{ | ||||||
|  | 		if (mux != other.mux) | ||||||
|  | 			return mux < other.mux; | ||||||
|  | 
 | ||||||
|  | 		if (mux_port_id != other.mux_port_id) | ||||||
|  | 			return mux_port_id < other.mux_port_id; | ||||||
|  | 
 | ||||||
|  | 		return mux_port_offset < other.mux_port_offset; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // Helper class to track additiona information about a SigSpec, like whether it is signed and the semantics of the port it is connected to
 | ||||||
|  | struct ExtSigSpec { | ||||||
|  | 	RTLIL::SigSpec sig; | ||||||
|  | 	RTLIL::SigSpec sign; | ||||||
|  | 	bool is_signed; | ||||||
|  | 	RTLIL::IdString semantics; | ||||||
|  | 
 | ||||||
|  | 	ExtSigSpec() {} | ||||||
|  | 
 | ||||||
|  | 	ExtSigSpec(RTLIL::SigSpec s, RTLIL::SigSpec sign = RTLIL::Const(0, 1), bool is_signed = false, RTLIL::IdString semantics = RTLIL::IdString()) : sig(s), sign(sign), is_signed(is_signed), semantics(semantics) {} | ||||||
|  | 
 | ||||||
|  | 	bool empty() const { return sig.empty(); } | ||||||
|  | 
 | ||||||
|  | 	bool operator<(const ExtSigSpec &other) const | ||||||
|  | 	{ | ||||||
|  | 		if (sig != other.sig) | ||||||
|  | 			return sig < other.sig; | ||||||
|  | 
 | ||||||
|  | 		if (sign != other.sign) | ||||||
|  | 			return sign < other.sign; | ||||||
|  | 
 | ||||||
|  | 		if (is_signed != other.is_signed) | ||||||
|  | 			return is_signed < other.is_signed; | ||||||
|  | 
 | ||||||
|  | 		return semantics < other.semantics; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool operator==(const RTLIL::SigSpec &other) const { return (sign != RTLIL::Const(0, 1)) ? false : sig == other; } | ||||||
|  | 	bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig && semantics == other.semantics; } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($and), ID($or), ID($xor), ID($xnor) | ||||||
|  | 
 | ||||||
|  | #define REDUCTION_OPS ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($reduce_nand) | ||||||
|  | 
 | ||||||
|  | #define LOGICAL_OPS ID($logic_and), ID($logic_or) | ||||||
|  | 
 | ||||||
|  | #define SHIFT_OPS ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx) | ||||||
|  | 
 | ||||||
|  | #define RELATIONAL_OPS ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt) | ||||||
|  | 
 | ||||||
|  | bool cell_supported(RTLIL::Cell *cell) | ||||||
|  | { | ||||||
|  | 	if (cell->type.in(ID($alu))) { | ||||||
|  | 		RTLIL::SigSpec sig_bi = cell->getPort(ID(BI)); | ||||||
|  | 		RTLIL::SigSpec sig_ci = cell->getPort(ID(CI)); | ||||||
|  | 
 | ||||||
|  | 		if (sig_bi.is_fully_const() && sig_ci.is_fully_const() && sig_bi == sig_ci) | ||||||
|  | 			return true; | ||||||
|  | 	} else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($concat))) { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::map<IdString, IdString> mergeable_type_map{ | ||||||
|  |   {ID($sub), ID($add)}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b) | ||||||
|  | { | ||||||
|  | 	auto a_type = a->type; | ||||||
|  | 	if (mergeable_type_map.count(a_type)) | ||||||
|  | 		a_type = mergeable_type_map.at(a_type); | ||||||
|  | 
 | ||||||
|  | 	auto b_type = b->type; | ||||||
|  | 	if (mergeable_type_map.count(b_type)) | ||||||
|  | 		b_type = mergeable_type_map.at(b_type); | ||||||
|  | 
 | ||||||
|  | 	return a_type == b_type; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_name) | ||||||
|  | { | ||||||
|  | 	if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt), ID($div), ID($mod), ID($concat), SHIFT_OPS) && port_name == ID::B) | ||||||
|  | 		return port_name; | ||||||
|  | 
 | ||||||
|  | 	return ""; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | RTLIL::SigSpec decode_port_sign(RTLIL::Cell *cell, RTLIL::IdString port_name) { | ||||||
|  | 
 | ||||||
|  | 	if (cell->type == ID($alu) && port_name == ID::B) | ||||||
|  | 		return cell->getPort(ID(BI)); | ||||||
|  | 	else if (cell->type == ID($sub) && port_name == ID::B) | ||||||
|  | 		return RTLIL::Const(1, 1); | ||||||
|  | 
 | ||||||
|  | 	return RTLIL::Const(0, 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool decode_port_signed(RTLIL::Cell *cell, RTLIL::IdString port_name) | ||||||
|  | { | ||||||
|  | 	if (cell->type.in(BITWISE_OPS, LOGICAL_OPS)) | ||||||
|  | 		return false; | ||||||
|  | 
 | ||||||
|  | 	if (cell->hasParam(port_name.str() + "_SIGNED")) | ||||||
|  | 		return cell->getParam(port_name.str() + "_SIGNED").as_bool(); | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ExtSigSpec decode_port(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sigmap) | ||||||
|  | { | ||||||
|  | 	auto sig = (*sigmap)(cell->getPort(port_name)); | ||||||
|  | 
 | ||||||
|  | 	RTLIL::SigSpec sign = decode_port_sign(cell, port_name); | ||||||
|  | 	RTLIL::IdString semantics = decode_port_semantics(cell, port_name); | ||||||
|  | 
 | ||||||
|  | 	bool is_signed = decode_port_signed(cell, port_name); | ||||||
|  | 
 | ||||||
|  | 	return ExtSigSpec(sig, sign, is_signed, semantics); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<OpMuxConn> &ports, const ExtSigSpec &operand) | ||||||
|  | { | ||||||
|  | 	std::vector<ExtSigSpec> muxed_operands; | ||||||
|  | 	int max_width = 0; | ||||||
|  | 	for (const auto& p : ports) { | ||||||
|  | 		auto op = p.op; | ||||||
|  | 
 | ||||||
|  | 		RTLIL::IdString muxed_port_name = ID::A; | ||||||
|  | 		if (decode_port(op, ID::A, &assign_map) == operand) | ||||||
|  | 			muxed_port_name = ID::B; | ||||||
|  | 
 | ||||||
|  | 		auto operand = decode_port(op, muxed_port_name, &assign_map); | ||||||
|  | 		if (operand.sig.size() > max_width) | ||||||
|  | 			max_width = operand.sig.size(); | ||||||
|  | 
 | ||||||
|  | 		muxed_operands.push_back(operand); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	auto shared_op = ports[0].op; | ||||||
|  | 
 | ||||||
|  | 	if (std::any_of(muxed_operands.begin(), muxed_operands.end(), [&](ExtSigSpec &op) { return op.sign != muxed_operands[0].sign; })) | ||||||
|  |         max_width = std::max(max_width, shared_op->getParam(ID(Y_WIDTH)).as_int()); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	for (auto &operand : muxed_operands) | ||||||
|  | 		operand.sig.extend_u0(max_width, operand.is_signed); | ||||||
|  | 
 | ||||||
|  | 	for (const auto& p : ports) { | ||||||
|  | 		auto op = p.op; | ||||||
|  | 		if (op == shared_op) | ||||||
|  | 			continue; | ||||||
|  | 		module->remove(op); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (auto &muxed_op : muxed_operands) | ||||||
|  | 		if (muxed_op.sign != muxed_operands[0].sign) | ||||||
|  | 			muxed_op = ExtSigSpec(module->Neg(NEW_ID, muxed_op.sig, muxed_op.is_signed)); | ||||||
|  | 
 | ||||||
|  | 	RTLIL::SigSpec mux_y = mux->getPort(ID::Y); | ||||||
|  | 	RTLIL::SigSpec mux_a = mux->getPort(ID::A); | ||||||
|  | 	RTLIL::SigSpec mux_b = mux->getPort(ID::B); | ||||||
|  | 	RTLIL::SigSpec mux_s = mux->getPort(ID(S)); | ||||||
|  | 
 | ||||||
|  | 	RTLIL::SigSpec shared_pmux_a = RTLIL::Const(RTLIL::State::Sx, max_width); | ||||||
|  | 	RTLIL::SigSpec shared_pmux_b; | ||||||
|  | 	RTLIL::SigSpec shared_pmux_s; | ||||||
|  | 
 | ||||||
|  | 	int conn_width = ports[0].sig.size(); | ||||||
|  | 	int conn_offset = ports[0].mux_port_offset; | ||||||
|  | 
 | ||||||
|  | 	shared_op->setPort(ID::Y, shared_op->getPort(ID::Y).extract(0, conn_width)); | ||||||
|  | 
 | ||||||
|  | 	if (mux->type == ID($pmux)) { | ||||||
|  | 		shared_pmux_s = RTLIL::SigSpec(); | ||||||
|  | 
 | ||||||
|  | 		for (const auto &p : ports) { | ||||||
|  | 			shared_pmux_s.append(mux_s[p.mux_port_id]); | ||||||
|  | 			mux_b.replace(p.mux_port_id * mux_a.size() + conn_offset, shared_op->getPort(ID::Y)); | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		shared_pmux_s = RTLIL::SigSpec{mux_s, module->Not(NEW_ID, mux_s)}; | ||||||
|  | 		mux_a.replace(conn_offset, shared_op->getPort(ID::Y)); | ||||||
|  | 		mux_b.replace(conn_offset, shared_op->getPort(ID::Y)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	mux->setPort(ID::A, mux_a); | ||||||
|  | 	mux->setPort(ID::B, mux_b); | ||||||
|  | 	mux->setPort(ID::Y, mux_y); | ||||||
|  | 	mux->setPort(ID(S), mux_s); | ||||||
|  | 
 | ||||||
|  | 	for (const auto &op : muxed_operands) | ||||||
|  | 		shared_pmux_b.append(op.sig); | ||||||
|  | 
 | ||||||
|  | 	auto mux_to_oper = module->Pmux(NEW_ID, shared_pmux_a, shared_pmux_b, shared_pmux_s); | ||||||
|  | 
 | ||||||
|  | 	if (shared_op->type.in(ID($alu))) { | ||||||
|  | 		RTLIL::SigSpec alu_x = shared_op->getPort(ID(X)); | ||||||
|  | 		RTLIL::SigSpec alu_co = shared_op->getPort(ID(CO)); | ||||||
|  | 
 | ||||||
|  | 		shared_op->setPort(ID(X), alu_x.extract(0, conn_width)); | ||||||
|  | 		shared_op->setPort(ID(CO), alu_co.extract(0, conn_width)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	shared_op->setParam(ID(Y_WIDTH), conn_width); | ||||||
|  | 
 | ||||||
|  | 	if (decode_port(shared_op, ID::A, &assign_map) == operand) { | ||||||
|  | 		shared_op->setPort(ID::B, mux_to_oper); | ||||||
|  | 		shared_op->setParam(ID(B_WIDTH), max_width); | ||||||
|  | 	} else { | ||||||
|  | 		shared_op->setPort(ID::A, mux_to_oper); | ||||||
|  | 		shared_op->setParam(ID(A_WIDTH), max_width); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	RTLIL::Cell *mux; | ||||||
|  | 	std::vector<OpMuxConn> ports; | ||||||
|  | 	ExtSigSpec shared_operand; | ||||||
|  | } merged_op_t; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | template <typename T> void remove_val(std::vector<T> &v, const std::vector<T> &vals) | ||||||
|  | { | ||||||
|  | 	auto val_iter = vals.rbegin(); | ||||||
|  | 	for (auto i = v.rbegin(); i != v.rend(); ++i) | ||||||
|  | 		if ((val_iter != vals.rend()) && (*i == *val_iter)) { | ||||||
|  | 			v.erase(i.base() - 1); | ||||||
|  | 			++val_iter; | ||||||
|  | 		} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void check_muxed_operands(std::vector<const OpMuxConn *> &ports, const ExtSigSpec &shared_operand) | ||||||
|  | { | ||||||
|  | 	auto it = ports.begin(); | ||||||
|  | 	ExtSigSpec seed; | ||||||
|  | 
 | ||||||
|  | 	while (it != ports.end()) { | ||||||
|  | 		auto p = *it; | ||||||
|  | 		auto op = p->op; | ||||||
|  | 
 | ||||||
|  | 		RTLIL::IdString muxed_port_name = ID::A; | ||||||
|  | 		if (decode_port(op, ID::A, &assign_map) == shared_operand) { | ||||||
|  | 			muxed_port_name = ID::B; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		auto operand = decode_port(op, muxed_port_name, &assign_map); | ||||||
|  | 
 | ||||||
|  | 		if (seed.empty()) | ||||||
|  | 			seed = operand; | ||||||
|  | 
 | ||||||
|  | 		if (operand.is_signed != seed.is_signed) { | ||||||
|  | 			ports.erase(it); | ||||||
|  | 		} else { | ||||||
|  | 			++it; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vector<const OpMuxConn *> &ports, const std::map<ExtSigSpec, std::set<RTLIL::Cell *>> &operand_to_users) | ||||||
|  | { | ||||||
|  | 	std::set<RTLIL::Cell *> ops_using_operand; | ||||||
|  | 	std::set<RTLIL::Cell *> ops_set; | ||||||
|  | 	for(const auto& p: ports) | ||||||
|  | 		ops_set.insert(p->op); | ||||||
|  | 
 | ||||||
|  | 	ExtSigSpec oper; | ||||||
|  | 
 | ||||||
|  | 	auto op_a = seed->op; | ||||||
|  | 
 | ||||||
|  | 	for (RTLIL::IdString port_name : {ID::A, ID::B}) { | ||||||
|  | 		oper = decode_port(op_a, port_name, &assign_map); | ||||||
|  | 		auto operand_users = operand_to_users.at(oper); | ||||||
|  | 
 | ||||||
|  | 		if (operand_users.size() == 1) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		ops_using_operand.clear(); | ||||||
|  | 		for (auto mux_ops: ops_set) | ||||||
|  | 			if (operand_users.count(mux_ops)) | ||||||
|  | 				ops_using_operand.insert(mux_ops); | ||||||
|  | 
 | ||||||
|  | 		if (ops_using_operand.size() > 1) { | ||||||
|  | 			ports.erase(std::remove_if(ports.begin(), ports.end(), [&](const OpMuxConn *p) { return !ops_using_operand.count(p->op); }), | ||||||
|  | 						ports.end()); | ||||||
|  | 			return oper; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ExtSigSpec(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | dict<RTLIL::SigSpec, OpMuxConn> find_valid_op_mux_conns(RTLIL::Module *module, dict<RTLIL::SigBit, RTLIL::SigSpec> &op_outbit_to_outsig, | ||||||
|  | 							dict<RTLIL::SigSpec, RTLIL::Cell *> outsig_to_operator, | ||||||
|  | 							dict<RTLIL::SigBit, RTLIL::SigSpec> &op_aux_to_outsig) | ||||||
|  | { | ||||||
|  | 	dict<RTLIL::SigSpec, int> op_outsig_user_track; | ||||||
|  | 	dict<RTLIL::SigSpec, OpMuxConn> op_mux_conn_map; | ||||||
|  | 
 | ||||||
|  | 	std::function<void(RTLIL::SigSpec)> remove_outsig = [&](RTLIL::SigSpec outsig) { | ||||||
|  | 		for (auto op_outbit : outsig) | ||||||
|  | 			op_outbit_to_outsig.erase(op_outbit); | ||||||
|  | 
 | ||||||
|  | 		if (op_mux_conn_map.count(outsig)) | ||||||
|  | 			op_mux_conn_map.erase(outsig); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	std::function<void(RTLIL::SigBit)> remove_outsig_from_aux_bit = [&](RTLIL::SigBit auxbit) { | ||||||
|  | 		auto aux_outsig = op_aux_to_outsig.at(auxbit); | ||||||
|  | 		auto op = outsig_to_operator.at(aux_outsig); | ||||||
|  | 		auto op_outsig = assign_map(op->getPort(ID::Y)); | ||||||
|  | 		remove_outsig(op_outsig); | ||||||
|  | 
 | ||||||
|  | 		for (auto aux_outbit : aux_outsig) | ||||||
|  | 			op_aux_to_outsig.erase(aux_outbit); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	std::function<void(RTLIL::Cell *)> find_op_mux_conns = [&](RTLIL::Cell *mux) { | ||||||
|  | 		RTLIL::SigSpec sig; | ||||||
|  | 		int mux_port_size; | ||||||
|  | 
 | ||||||
|  | 		if (mux->type.in(ID($mux), ID($_MUX_))) { | ||||||
|  | 			mux_port_size = mux->getPort(ID::A).size(); | ||||||
|  | 			sig = RTLIL::SigSpec{mux->getPort(ID::B), mux->getPort(ID::A)}; | ||||||
|  | 		} else { | ||||||
|  | 			mux_port_size = mux->getPort(ID::A).size(); | ||||||
|  | 			sig = mux->getPort(ID::B); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		auto mux_insig = assign_map(sig); | ||||||
|  | 
 | ||||||
|  | 		for (int i = 0; i < mux_insig.size(); ++i) { | ||||||
|  | 			if (op_aux_to_outsig.count(mux_insig[i])) { | ||||||
|  | 				remove_outsig_from_aux_bit(mux_insig[i]); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (!op_outbit_to_outsig.count(mux_insig[i])) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			auto op_outsig = op_outbit_to_outsig.at(mux_insig[i]); | ||||||
|  | 
 | ||||||
|  | 			if (op_mux_conn_map.count(op_outsig)) { | ||||||
|  | 				remove_outsig(op_outsig); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			int mux_port_id = i / mux_port_size; | ||||||
|  | 			int mux_port_offset = i % mux_port_size; | ||||||
|  | 
 | ||||||
|  | 			int op_outsig_offset; | ||||||
|  | 			for (op_outsig_offset = 0; op_outsig[op_outsig_offset] != mux_insig[i]; ++op_outsig_offset) | ||||||
|  | 				; | ||||||
|  | 
 | ||||||
|  | 			int j = op_outsig_offset; | ||||||
|  | 			do { | ||||||
|  | 				if (!op_outbit_to_outsig.count(mux_insig[i])) | ||||||
|  | 					break; | ||||||
|  | 
 | ||||||
|  | 				if (op_outbit_to_outsig.at(mux_insig[i]) != op_outsig) | ||||||
|  | 					break; | ||||||
|  | 
 | ||||||
|  | 				++i; | ||||||
|  | 				++j; | ||||||
|  | 			} while ((i / mux_port_size == mux_port_id) && (j < op_outsig.size())); | ||||||
|  | 
 | ||||||
|  | 			int op_conn_width = j - op_outsig_offset; | ||||||
|  | 			OpMuxConn inp = { | ||||||
|  | 				op_outsig.extract(op_outsig_offset, op_conn_width), | ||||||
|  | 				mux, | ||||||
|  | 				outsig_to_operator.at(op_outsig), | ||||||
|  | 				mux_port_id, | ||||||
|  | 				mux_port_offset, | ||||||
|  | 				op_outsig_offset, | ||||||
|  | 			}; | ||||||
|  | 
 | ||||||
|  | 			op_mux_conn_map[op_outsig] = inp; | ||||||
|  | 
 | ||||||
|  | 			--i; | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	std::function<void(RTLIL::SigSpec)> remove_connected_ops = [&](RTLIL::SigSpec sig) { | ||||||
|  | 		auto mux_insig = assign_map(sig); | ||||||
|  | 		for (auto outbit : mux_insig) { | ||||||
|  | 			if (op_aux_to_outsig.count(outbit)) { | ||||||
|  | 				remove_outsig_from_aux_bit(outbit); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (!op_outbit_to_outsig.count(outbit)) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			remove_outsig(op_outbit_to_outsig.at(outbit)); | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	for (auto cell : module->cells()) { | ||||||
|  | 		if (cell->type.in(ID($mux), ID($_MUX_), ID($pmux))) { | ||||||
|  | 			remove_connected_ops(cell->getPort(ID(S))); | ||||||
|  | 			find_op_mux_conns(cell); | ||||||
|  | 		} else { | ||||||
|  | 			for (auto &conn : cell->connections()) | ||||||
|  | 				if (cell->input(conn.first)) | ||||||
|  | 					remove_connected_ops(conn.second); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (auto w : module->wires()) { | ||||||
|  | 		if (!w->port_output) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		remove_connected_ops(w); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return op_mux_conn_map; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct OptSharePass : public Pass { | ||||||
|  | 	OptSharePass() : Pass("opt_share", "merge mutually exclusive cells of the same type that share an input signal") {} | ||||||
|  | 	void help() YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    opt_share [selection]\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 
 | ||||||
|  | 		log("This pass identifies mutually exclusive cells of the same type that:\n"); | ||||||
|  | 		log("    (a) share an input signal,\n"); | ||||||
|  | 		log("    (b) drive the same $mux, $_MUX_, or $pmux multiplexing cell,\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("allowing the cell to be merged and the multiplexer to be moved from\n"); | ||||||
|  | 		log("multiplexing its output to multiplexing the non-shared input signals.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 	} | ||||||
|  | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 
 | ||||||
|  | 		log_header(design, "Executing OPT_SHARE pass.\n"); | ||||||
|  | 
 | ||||||
|  | 		extra_args(args, 1, design); | ||||||
|  | 		for (auto module : design->selected_modules()) { | ||||||
|  | 			assign_map.clear(); | ||||||
|  | 			assign_map.set(module); | ||||||
|  | 
 | ||||||
|  | 			std::map<ExtSigSpec, std::set<RTLIL::Cell *>> operand_to_users; | ||||||
|  | 			dict<RTLIL::SigSpec, RTLIL::Cell *> outsig_to_operator; | ||||||
|  | 			dict<RTLIL::SigBit, RTLIL::SigSpec> op_outbit_to_outsig; | ||||||
|  | 			dict<RTLIL::SigBit, RTLIL::SigSpec> op_aux_to_outsig; | ||||||
|  | 			bool any_shared_operands = false; | ||||||
|  | 			std::vector<ExtSigSpec> op_insigs; | ||||||
|  | 
 | ||||||
|  | 			for (auto cell : module->cells()) { | ||||||
|  | 				if (!cell_supported(cell)) | ||||||
|  | 					continue; | ||||||
|  | 
 | ||||||
|  | 				if (cell->type == ID($alu)) { | ||||||
|  | 					for (RTLIL::IdString port_name : {ID(X), ID(CO)}) { | ||||||
|  | 						auto mux_insig = assign_map(cell->getPort(port_name)); | ||||||
|  | 						outsig_to_operator[mux_insig] = cell; | ||||||
|  | 						for (auto outbit : mux_insig) | ||||||
|  | 							op_aux_to_outsig[outbit] = mux_insig; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				auto mux_insig = assign_map(cell->getPort(ID::Y)); | ||||||
|  | 				outsig_to_operator[mux_insig] = cell; | ||||||
|  | 				for (auto outbit : mux_insig) | ||||||
|  | 					op_outbit_to_outsig[outbit] = mux_insig; | ||||||
|  | 
 | ||||||
|  | 				for (RTLIL::IdString port_name : {ID::A, ID::B}) { | ||||||
|  | 					auto op_insig = decode_port(cell, port_name, &assign_map); | ||||||
|  | 					op_insigs.push_back(op_insig); | ||||||
|  | 					operand_to_users[op_insig].insert(cell); | ||||||
|  | 					if (operand_to_users[op_insig].size() > 1) | ||||||
|  | 						any_shared_operands = true; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (!any_shared_operands) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			// Operator outputs need to be exclusively connected to the $mux inputs in order to be mergeable. Hence we count to
 | ||||||
|  | 			// how many points are operator output bits connected.
 | ||||||
|  | 			dict<RTLIL::SigSpec, OpMuxConn> op_mux_conn_map = | ||||||
|  | 			  find_valid_op_mux_conns(module, op_outbit_to_outsig, outsig_to_operator, op_aux_to_outsig); | ||||||
|  | 
 | ||||||
|  | 			// Group op connections connected to same ports of the same $mux. Sort them in ascending order of their port offset
 | ||||||
|  | 			dict<RTLIL::Cell*, std::vector<std::set<OpMuxConn>>> mux_port_op_conns; | ||||||
|  | 			for (auto& val: op_mux_conn_map) { | ||||||
|  | 				OpMuxConn p = val.second; | ||||||
|  | 				auto& mux_port_conns = mux_port_op_conns[p.mux]; | ||||||
|  | 
 | ||||||
|  | 				if (mux_port_conns.size() == 0) { | ||||||
|  | 					int mux_port_num; | ||||||
|  | 
 | ||||||
|  | 					if (p.mux->type.in(ID($mux), ID($_MUX_))) | ||||||
|  | 						mux_port_num = 2; | ||||||
|  | 					else | ||||||
|  | 						mux_port_num = p.mux->getPort(ID(S)).size(); | ||||||
|  | 
 | ||||||
|  | 					mux_port_conns.resize(mux_port_num); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				mux_port_conns[p.mux_port_id].insert(p); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			std::vector<merged_op_t> merged_ops; | ||||||
|  | 			for (auto& val: mux_port_op_conns) { | ||||||
|  | 
 | ||||||
|  | 				RTLIL::Cell* cell = val.first; | ||||||
|  | 				auto &mux_port_conns = val.second; | ||||||
|  | 
 | ||||||
|  | 				const OpMuxConn *seed = NULL; | ||||||
|  | 
 | ||||||
|  | 				// Look through the bits of the $mux inputs and see which of them are connected to the operator
 | ||||||
|  | 				// results. Operator results can be concatenated with other signals before led to the $mux.
 | ||||||
|  | 				while (true) { | ||||||
|  | 
 | ||||||
|  | 					// Remove either the merged ports from the last iteration or the seed that failed to yield a merger
 | ||||||
|  | 					if (seed != NULL) { | ||||||
|  | 						mux_port_conns[seed->mux_port_id].erase(*seed); | ||||||
|  | 						seed = NULL; | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					// For a new merger, find the seed op connection that starts at lowest port offset among port connections
 | ||||||
|  | 					for (auto &port_conns : mux_port_conns) { | ||||||
|  | 						if (!port_conns.size()) | ||||||
|  | 							continue; | ||||||
|  | 
 | ||||||
|  | 						const OpMuxConn *next_p = &(*port_conns.begin()); | ||||||
|  | 
 | ||||||
|  | 						if ((seed == NULL) || (seed->mux_port_offset > next_p->mux_port_offset)) | ||||||
|  | 							seed = next_p; | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					// Cannot find the seed -> nothing to do for this $mux anymore
 | ||||||
|  | 					if (seed == NULL) | ||||||
|  | 						break; | ||||||
|  | 
 | ||||||
|  | 					// Find all other op connections that start from the same port offset, and whose ops can be merged with the seed op
 | ||||||
|  | 					std::vector<const OpMuxConn *> mergeable_conns; | ||||||
|  | 					for (auto &port_conns : mux_port_conns) { | ||||||
|  | 						if (!port_conns.size()) | ||||||
|  | 							continue; | ||||||
|  | 
 | ||||||
|  | 						const OpMuxConn *next_p = &(*port_conns.begin()); | ||||||
|  | 
 | ||||||
|  | 						if ((next_p->op_outsig_offset == seed->op_outsig_offset) && | ||||||
|  | 						    (next_p->mux_port_offset == seed->mux_port_offset) && mergeable(next_p->op, seed->op) && | ||||||
|  | 						    next_p->sig.size() == seed->sig.size()) | ||||||
|  | 							mergeable_conns.push_back(next_p); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					// We need at least two mergeable connections for the merger
 | ||||||
|  | 					if (mergeable_conns.size() < 2) | ||||||
|  | 						continue; | ||||||
|  | 
 | ||||||
|  | 					// Filter mergeable connections whose ops share an operand with seed connection's op
 | ||||||
|  | 					auto shared_operand = find_shared_operand(seed, mergeable_conns, operand_to_users); | ||||||
|  | 
 | ||||||
|  | 					if (shared_operand.empty()) | ||||||
|  | 						continue; | ||||||
|  | 
 | ||||||
|  | 					check_muxed_operands(mergeable_conns, shared_operand); | ||||||
|  | 
 | ||||||
|  | 					if (mergeable_conns.size() < 2) | ||||||
|  | 						continue; | ||||||
|  | 
 | ||||||
|  | 					// Remember the combination for the merger
 | ||||||
|  | 					std::vector<OpMuxConn> merged_ports; | ||||||
|  | 					for (auto p : mergeable_conns) { | ||||||
|  | 						merged_ports.push_back(*p); | ||||||
|  | 						mux_port_conns[p->mux_port_id].erase(*p); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					seed = NULL; | ||||||
|  | 
 | ||||||
|  | 					merged_ops.push_back(merged_op_t{cell, merged_ports, shared_operand}); | ||||||
|  | 
 | ||||||
|  | 					design->scratchpad_set_bool("opt.did_something", true); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			for (auto &shared : merged_ops) { | ||||||
|  | 				log("    Found cells that share an operand and can be merged by moving the %s %s in front " | ||||||
|  | 				    "of " | ||||||
|  | 				    "them:\n", | ||||||
|  | 				    log_id(shared.mux->type), log_id(shared.mux)); | ||||||
|  | 				for (const auto& op : shared.ports) | ||||||
|  | 					log("        %s\n", log_id(op.op)); | ||||||
|  | 				log("\n"); | ||||||
|  | 
 | ||||||
|  | 				merge_operators(module, shared.mux, shared.ports, shared.shared_operand); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } OptSharePass; | ||||||
|  | 
 | ||||||
|  | PRIVATE_NAMESPACE_END | ||||||
|  | @ -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)); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								passes/pmgen/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								passes/pmgen/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										90
									
								
								passes/pmgen/ice40_wrapcarry.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								passes/pmgen/ice40_wrapcarry.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,90 @@ | ||||||
|  | /*
 | ||||||
|  |  *  yosys -- Yosys Open SYnthesis Suite | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||||
|  |  * | ||||||
|  |  *  Permission to use, copy, modify, and/or distribute this software for any | ||||||
|  |  *  purpose with or without fee is hereby granted, provided that the above | ||||||
|  |  *  copyright notice and this permission notice appear in all copies. | ||||||
|  |  * | ||||||
|  |  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  |  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  |  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  |  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  |  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  |  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  |  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "kernel/yosys.h" | ||||||
|  | #include "kernel/sigtools.h" | ||||||
|  | 
 | ||||||
|  | USING_YOSYS_NAMESPACE | ||||||
|  | PRIVATE_NAMESPACE_BEGIN | ||||||
|  | 
 | ||||||
|  | #include "passes/pmgen/ice40_wrapcarry_pm.h" | ||||||
|  | 
 | ||||||
|  | void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) | ||||||
|  | { | ||||||
|  | 	auto &st = pm.st_ice40_wrapcarry; | ||||||
|  | 
 | ||||||
|  | #if 0 | ||||||
|  | 	log("\n"); | ||||||
|  | 	log("carry: %s\n", log_id(st.carry, "--")); | ||||||
|  | 	log("lut:   %s\n", log_id(st.lut, "--")); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	log("  replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n"); | ||||||
|  | 
 | ||||||
|  | 	Cell *cell = pm.module->addCell(NEW_ID, "$__ICE40_CARRY_WRAPPER"); | ||||||
|  | 	pm.module->swap_names(cell, st.carry); | ||||||
|  | 
 | ||||||
|  | 	cell->setPort("\\A", st.carry->getPort("\\I0")); | ||||||
|  | 	cell->setPort("\\B", st.carry->getPort("\\I1")); | ||||||
|  | 	cell->setPort("\\CI", st.carry->getPort("\\CI")); | ||||||
|  | 	cell->setPort("\\CO", st.carry->getPort("\\CO")); | ||||||
|  | 
 | ||||||
|  | 	cell->setPort("\\I0", st.lut->getPort("\\I0")); | ||||||
|  | 	cell->setPort("\\I3", st.lut->getPort("\\I3")); | ||||||
|  | 	cell->setPort("\\O", st.lut->getPort("\\O")); | ||||||
|  | 	cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT")); | ||||||
|  | 
 | ||||||
|  | 	pm.autoremove(st.carry); | ||||||
|  | 	pm.autoremove(st.lut); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct Ice40WrapCarryPass : public Pass { | ||||||
|  | 	Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { } | ||||||
|  | 	void help() YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    ice40_wrapcarry [selection]\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUTs,\n"); | ||||||
|  | 		log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n"); | ||||||
|  | 		log("mapping."); | ||||||
|  | 		log("\n"); | ||||||
|  | 	} | ||||||
|  | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n"); | ||||||
|  | 
 | ||||||
|  | 		size_t argidx; | ||||||
|  | 		for (argidx = 1; argidx < args.size(); argidx++) | ||||||
|  | 		{ | ||||||
|  | 			// if (args[argidx] == "-singleton") {
 | ||||||
|  | 			// 	singleton_mode = true;
 | ||||||
|  | 			// 	continue;
 | ||||||
|  | 			// }
 | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		extra_args(args, argidx, design); | ||||||
|  | 
 | ||||||
|  | 		for (auto module : design->selected_modules()) | ||||||
|  | 			ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry); | ||||||
|  | 	} | ||||||
|  | } Ice40WrapCarryPass; | ||||||
|  | 
 | ||||||
|  | PRIVATE_NAMESPACE_END | ||||||
							
								
								
									
										11
									
								
								passes/pmgen/ice40_wrapcarry.pmg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								passes/pmgen/ice40_wrapcarry.pmg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | pattern ice40_wrapcarry | ||||||
|  | 
 | ||||||
|  | match carry | ||||||
|  | 	select carry->type.in(\SB_CARRY) | ||||||
|  | endmatch | ||||||
|  | 
 | ||||||
|  | match lut | ||||||
|  | 	select lut->type.in(\SB_LUT4) | ||||||
|  | 	index <SigSpec> port(lut, \I1) === port(carry, \I0) | ||||||
|  | 	index <SigSpec> port(lut, \I2) === port(carry, \I1) | ||||||
|  | endmatch | ||||||
|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue