diff --git a/.editorconfig b/.editorconfig index f5444d81a74..4d6f5ef7abe 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,8 +5,3 @@ indent_style = tab indent_size = tab trim_trailing_whitespace = true insert_final_newline = true - -[abc/**] -indent_style = space -indent_size = 2 -trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index f85ae06c930..00000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.v linguist-language=Verilog diff --git a/.gitignore b/.gitignore index 0460c7c1339..76f53cd06af 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,6 @@ __pycache__ /yosys /yosys.exe /yosys.js -/yosys.wasm /yosys-abc /yosys-abc.exe /yosys-config diff --git a/Brewfile b/Brewfile index 2a985f09e65..8465d86f9e2 100644 --- a/Brewfile +++ b/Brewfile @@ -8,4 +8,3 @@ brew "pkg-config" brew "python3" brew "tcl-tk" brew "xdot" -brew "bash" diff --git a/CHANGELOG b/CHANGELOG index 638ce558bfb..a49c27b05c7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,7 +8,7 @@ Yosys 0.9 .. Yosys 0.9-dev * Various - Added "write_xaiger" backend - - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only) + - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only, no FFs) - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) @@ -50,23 +50,9 @@ Yosys 0.9 .. Yosys 0.9-dev - "synth_ecp5" to now infer DSP blocks (-nodsp to disable, experimental) - "synth_ice40 -dsp" to infer DSP blocks - Added latch support to synth_xilinx - - Added support for flip-flops with synchronous reset to synth_xilinx - - Added support for flip-flops with reset and enable to synth_xilinx - Added "check -mapped" - Added checking of SystemVerilog always block types (always_comb, always_latch and always_ff) - - Added support for SystemVerilog wildcard port connections (.*) - - Added "xilinx_dffopt" pass - - Added "scratchpad" pass - - Added "synth_xilinx -dff" - - Improved support of $readmem[hb] Memory Content File inclusion - - Added "opt_lut_ins" pass - - Added "logger" pass - - Removed "dffsr2dff" (use opt_rmdff instead) - - Added "design -delete" - - Added "select -unset" - - Use YosysHQ/abc instead of upstream berkeley-abc/abc - - Added $divfloor and $modfloor cells Yosys 0.8 .. Yosys 0.9 ---------------------- diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index a73779920c1..00000000000 --- a/CODEOWNERS +++ /dev/null @@ -1,37 +0,0 @@ -## CODE NOTIFICATIONS -# Register yourself here to be notified about modifications -# for any files you have an interest in/know your way around. - -# Each line is a file pattern followed by one or more users. -# Both github usernames and email addresses are supported. -# Order is important; the last matching pattern takes the most -# precedence. Previous matches will not be applied. - - -# PATH (can use glob) USERNAME(S) - -passes/cmds/scratchpad.cc @nakengelhardt -frontends/rpc/ @whitequark -backends/cxxrtl/ @whitequark -passes/cmds/bugpoint.cc @whitequark -passes/techmap/flowmap.cc @whitequark -passes/opt/opt_lut.cc @whitequark - - -## External Contributors -# Only users with write permission to the repository get review -# requests automatically, but we add information for other -# contributors here too, so we know who to ask to take a look. -# These still override previous lines, so be careful not to -# accidentally disable any of the above rules. - -techlibs/intel_alm/ @ZirconiumX - -# pyosys -misc/*.py @btut - -backends/firrtl @ucbjrl @azidar - -passes/sat/qbfsat.cc @boqwxp -passes/cmds/exec.cc @boqwxp -passes/cmds/printattrs.cc @boqwxp diff --git a/COPYING b/COPYING index 7cd2464cd6f..0839088c364 100644 --- a/COPYING +++ b/COPYING @@ -1,6 +1,4 @@ -ISC License - -Copyright (C) 2012 - 2020 Claire Wolf +Copyright (C) 2012 - 2019 Clifford Wolf Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/Makefile b/Makefile index 3d3e60359b1..6e7681cf39a 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,6 @@ CONFIG := clang # CONFIG := gcc-4.8 # CONFIG := afl-gcc # CONFIG := emcc -# CONFIG := wasi # CONFIG := mxe # CONFIG := msys2 # CONFIG := msys2-64 @@ -33,9 +32,7 @@ ENABLE_NDEBUG := 0 LINK_CURSES := 0 LINK_TERMCAP := 0 LINK_ABC := 0 -# Needed for environments that can't run executables (i.e. emscripten, wasm) -DISABLE_SPAWN := 0 -# Needed for environments that don't have proper thread support (i.e. emscripten, wasm--for now) +# Needed for environments that don't have proper thread support (i.e. emscripten) DISABLE_ABC_THREADS := 0 # clang sanitizers @@ -45,7 +42,6 @@ SANITIZER = # SANITIZER = undefined # SANITIZER = cfi -PROGRAM_PREFIX := OS := $(shell uname -s) PREFIX ?= /usr/local @@ -55,20 +51,16 @@ ifneq ($(wildcard Makefile.conf),) include Makefile.conf endif -ifeq ($(ENABLE_PYOSYS),1) -ENABLE_LIBYOSYS := 1 -endif - BINDIR := $(PREFIX)/bin -LIBDIR := $(PREFIX)/lib/$(PROGRAM_PREFIX)yosys -DATDIR := $(PREFIX)/share/$(PROGRAM_PREFIX)yosys +LIBDIR := $(PREFIX)/lib +DATDIR := $(PREFIX)/share/yosys EXE = OBJS = GENFILES = EXTRA_OBJS = EXTRA_TARGETS = -TARGETS = $(PROGRAM_PREFIX)yosys$(EXE) $(PROGRAM_PREFIX)yosys-config +TARGETS = yosys$(EXE) yosys-config PRETTY = 1 SMALL = 0 @@ -82,6 +74,7 @@ YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST))) VPATH := $(YOSYS_SRC) CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include +LDFLAGS := $(LDFLAGS) -L$(LIBDIR) LDLIBS := $(LDLIBS) -lstdc++ -lm PLUGIN_LDFLAGS := @@ -122,7 +115,7 @@ LDFLAGS += -rdynamic LDLIBS += -lrt endif -YOSYS_VER := 0.9+2406 +YOSYS_VER := 0.9+932 GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN) OBJS = kernel/version_$(GIT_REV).o @@ -135,9 +128,9 @@ bumpversion: # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = 341db25 +ABCREV = 623b5e8 ABCPULL = 1 -ABCURL ?= https://github.com/YosysHQ/abc +ABCURL ?= https://github.com/berkeley-abc/abc ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 # set ABCEXTERNAL = to use an external ABC instance @@ -150,10 +143,7 @@ define newline endef ifneq ($(wildcard Makefile.conf),) -# don't echo Makefile.conf contents when invoked to print source versions -ifeq ($(findstring echo-,$(MAKECMDGOALS)),) $(info $(subst $$--$$,$(newline),$(shell sed 's,^,[Makefile.conf] ,; s,$$,$$--$$,;' < Makefile.conf | tr -d '\n' | sed 's,\$$--\$$$$,,'))) -endif include Makefile.conf endif @@ -162,15 +152,7 @@ ifeq ($(ENABLE_PYOSYS),1) PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)" PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"") PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.) - -ENABLE_PYTHON_CONFIG_EMBED ?= $(shell $(PYTHON_EXECUTABLE)-config --embed --libs > /dev/null && echo 1) -ifeq ($(ENABLE_PYTHON_CONFIG_EMBED),1) -PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config --embed -else -PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config -endif - -PYTHON_PREFIX := $(shell $(PYTHON_CONFIG) --prefix) +PYTHON_PREFIX := $(shell $(PYTHON_EXECUTABLE)-config --prefix) PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages # Reload Makefile.conf to override python specific variables if defined @@ -247,17 +229,14 @@ ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DABC_MEMALIGN=8" EMCCFLAGS := -Os -Wno-warn-absolute-paths EMCCFLAGS += --memory-init-file 0 --embed-file share -s NO_EXIT_RUNTIME=1 EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt','_errmsg']" -EMCCFLAGS += -s TOTAL_MEMORY=134217728 -EMCCFLAGS += -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' +EMCCFLAGS += -s TOTAL_MEMORY=128*1024*1024 # https://github.com/kripken/emscripten/blob/master/src/settings.js CXXFLAGS += $(EMCCFLAGS) LDFLAGS += $(EMCCFLAGS) LDLIBS = EXE = .js -DISABLE_SPAWN := 1 - -TARGETS := $(filter-out $(PROGRAM_PREFIX)yosys-config,$(TARGETS)) +TARGETS := $(filter-out yosys-config,$(TARGETS)) EXTRA_TARGETS += yosysjs-$(YOSYS_VER).zip ifeq ($(ENABLE_ABC),1) @@ -269,44 +248,15 @@ viz.js: wget -O viz.js.part https://github.com/mdaines/viz.js/releases/download/0.0.3/viz.js mv viz.js.part viz.js -yosysjs-$(YOSYS_VER).zip: yosys.js yosys.wasm viz.js misc/yosysjs/* +yosysjs-$(YOSYS_VER).zip: yosys.js viz.js misc/yosysjs/* rm -rf yosysjs-$(YOSYS_VER) yosysjs-$(YOSYS_VER).zip mkdir -p yosysjs-$(YOSYS_VER) - cp viz.js misc/yosysjs/* yosys.js yosys.wasm yosysjs-$(YOSYS_VER)/ + cp viz.js misc/yosysjs/* yosys.js yosysjs-$(YOSYS_VER)/ zip -r yosysjs-$(YOSYS_VER).zip yosysjs-$(YOSYS_VER) yosys.html: misc/yosys.html $(P) cp misc/yosys.html yosys.html -else ifeq ($(CONFIG),wasi) -ifeq ($(WASI_SDK),) -CXX = clang -LD = clang++ -AR = llvm-ar -RANLIB = llvm-ranlib -WASIFLAGS := -target wasm32-wasi --sysroot $(WASI_SYSROOT) $(WASIFLAGS) -else -CXX = $(WASI_SDK)/bin/clang -LD = $(WASI_SDK)/bin/clang++ -AR = $(WASI_SDK)/bin/ar -RANLIB = $(WASI_SDK)/bin/ranlib -WASIFLAGS := --sysroot $(WASI_SDK)/share/wasi-sysroot $(WASIFLAGS) -endif -CXXFLAGS := $(WASIFLAGS) -std=c++11 -Os $(filter-out -fPIC,$(CXXFLAGS)) -LDFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LDFLAGS)) -LDLIBS := $(filter-out -lrt,$(LDLIBS)) -ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)" -ABCMKARGS += ARCHFLAGS="$(WASIFLAGS) -DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING" -ABCMKARGS += OPTFLAGS="-Os" -EXE = .wasm - -DISABLE_SPAWN := 1 - -ifeq ($(ENABLE_ABC),1) -LINK_ABC := 1 -DISABLE_ABC_THREADS := 1 -endif - else ifeq ($(CONFIG),mxe) PKG_CONFIG = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-pkg-config CXX = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++ @@ -355,39 +305,39 @@ ifeq ($(ENABLE_PYOSYS),1) #Detect name of boost_python library. Some distros usbe boost_python-py, other boost_python, some only use the major version number, some a concatenation of major and minor version numbers ifeq ($(OS), Darwin) BOOST_PYTHON_LIB ?= $(shell \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ echo ""; fi; fi; fi; fi;) else BOOST_PYTHON_LIB ?= $(shell \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ echo ""; fi; fi; fi; fi;) endif ifeq ($(BOOST_PYTHON_LIB),) -$(error BOOST_PYTHON_LIB could not be detected. Please define manually) +$(error BOOST_PYTHON_LIB could not be detected. Please define manualy) endif ifeq ($(OS), Darwin) ifeq ($(PYTHON_MAJOR_VERSION),3) -LDLIBS += $(shell $(PYTHON_CONFIG) --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem -CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON +LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem +CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON else -LDLIBS += $(shell $(PYTHON_CONFIG) --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem -CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON +LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem +CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON endif else ifeq ($(PYTHON_MAJOR_VERSION),3) -LDLIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem -CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON +LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem +CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON else -LDLIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem -CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON +LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem +CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON endif endif @@ -429,10 +379,6 @@ ifeq ($(DISABLE_ABC_THREADS),1) ABCMKARGS += "ABC_USE_NO_PTHREADS=1" endif -ifeq ($(DISABLE_SPAWN),1) -CXXFLAGS += -DYOSYS_DISABLE_SPAWN -endif - ifeq ($(ENABLE_PLUGINS),1) CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags libffi) -DYOSYS_ENABLE_PLUGINS LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi) @@ -504,7 +450,7 @@ LDLIBS += -lpthread endif else ifeq ($(ABCEXTERNAL),) -TARGETS += $(PROGRAM_PREFIX)yosys-abc$(EXE) +TARGETS += yosys-abc$(EXE) endif endif endif @@ -554,8 +500,8 @@ endef ifeq ($(PRETTY), 1) P_STATUS = 0 P_OFFSET = 0 -P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) $(PROGRAM_PREFIX)yosys$(EXE) | $(AWK) 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }')) -P_SHOW = [$(shell $(AWK) "BEGIN { N=$(words $(OBJS) $(PROGRAM_PREFIX)yosys$(EXE)); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%] +P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) yosys$(EXE) | $(AWK) 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }')) +P_SHOW = [$(shell $(AWK) "BEGIN { N=$(words $(OBJS) yosys$(EXE)); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%] P = @echo "$(if $(findstring $@,$(TARGETS) $(EXTRA_TARGETS)),$(eval P_OFFSET = 10))$(call P_UPDATE)$(call P_SHOW) Building $@"; Q = @ S = -s @@ -574,7 +520,6 @@ $(eval $(call add_include_file,kernel/register.h)) $(eval $(call add_include_file,kernel/celltypes.h)) $(eval $(call add_include_file,kernel/celledges.h)) $(eval $(call add_include_file,kernel/consteval.h)) -$(eval $(call add_include_file,kernel/constids.inc)) $(eval $(call add_include_file,kernel/sigtools.h)) $(eval $(call add_include_file,kernel/modtools.h)) $(eval $(call add_include_file,kernel/macc.h)) @@ -587,18 +532,12 @@ $(eval $(call add_include_file,libs/json11/json11.hpp)) $(eval $(call add_include_file,passes/fsm/fsmdata.h)) $(eval $(call add_include_file,frontends/ast/ast.h)) $(eval $(call add_include_file,backends/ilang/ilang_backend.h)) -$(eval $(call add_include_file,backends/cxxrtl/cxxrtl.h)) -$(eval $(call add_include_file,backends/cxxrtl/cxxrtl_vcd.h)) -$(eval $(call add_include_file,backends/cxxrtl/cxxrtl_capi.cc)) -$(eval $(call add_include_file,backends/cxxrtl/cxxrtl_capi.h)) -$(eval $(call add_include_file,backends/cxxrtl/cxxrtl_vcd_capi.cc)) -$(eval $(call add_include_file,backends/cxxrtl/cxxrtl_vcd_capi.h)) OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o OBJS += kernel/cellaigs.o kernel/celledges.o kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"' -kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"' +kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' OBJS += libs/bigint/BigIntegerAlgorithms.o libs/bigint/BigInteger.o libs/bigint/BigIntegerUtils.o OBJS += libs/bigint/BigUnsigned.o libs/bigint/BigUnsignedInABase.o @@ -626,10 +565,10 @@ include $(YOSYS_SRC)/techlibs/*/Makefile.inc else -include $(YOSYS_SRC)/frontends/verilog/Makefile.inc -include $(YOSYS_SRC)/frontends/ilang/Makefile.inc -include $(YOSYS_SRC)/frontends/ast/Makefile.inc -include $(YOSYS_SRC)/frontends/blif/Makefile.inc +include frontends/verilog/Makefile.inc +include frontends/ilang/Makefile.inc +include frontends/ast/Makefile.inc +include frontends/blif/Makefile.inc OBJS += passes/hierarchy/hierarchy.o OBJS += passes/cmds/select.o @@ -639,19 +578,19 @@ OBJS += passes/cmds/cover.o OBJS += passes/cmds/design.o OBJS += passes/cmds/plugin.o -include $(YOSYS_SRC)/passes/proc/Makefile.inc -include $(YOSYS_SRC)/passes/opt/Makefile.inc -include $(YOSYS_SRC)/passes/techmap/Makefile.inc +include passes/proc/Makefile.inc +include passes/opt/Makefile.inc +include passes/techmap/Makefile.inc -include $(YOSYS_SRC)/backends/verilog/Makefile.inc -include $(YOSYS_SRC)/backends/ilang/Makefile.inc +include backends/verilog/Makefile.inc +include backends/ilang/Makefile.inc -include $(YOSYS_SRC)/techlibs/common/Makefile.inc +include techlibs/common/Makefile.inc endif ifeq ($(LINK_ABC),1) -OBJS += $(PROGRAM_PREFIX)yosys-libabc.a +OBJS += yosys-libabc.a endif top-all: $(TARGETS) $(EXTRA_TARGETS) @@ -663,14 +602,14 @@ ifeq ($(CONFIG),emcc) yosys.js: $(filter-out yosysjs-$(YOSYS_VER).zip,$(EXTRA_TARGETS)) endif -$(PROGRAM_PREFIX)yosys$(EXE): $(OBJS) - $(P) $(LD) -o $(PROGRAM_PREFIX)yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS) +yosys$(EXE): $(OBJS) + $(P) $(LD) -o yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS) libyosys.so: $(filter-out kernel/driver.o,$(OBJS)) ifeq ($(OS), Darwin) - $(P) $(LD) -o libyosys.so -shared -Wl,-install_name,$(DESTDIR)$(LIBDIR)/libyosys.so $(LDFLAGS) $^ $(LDLIBS) + $(P) $(LD) -o libyosys.so -shared -Wl,-install_name,libyosys.so $(LDFLAGS) $^ $(LDLIBS) else - $(P) $(LD) -o libyosys.so -shared -Wl,-soname,$(DESTDIR)$(LIBDIR)/libyosys.so $(LDFLAGS) $^ $(LDLIBS) + $(P) $(LD) -o libyosys.so -shared -Wl,-soname,libyosys.so $(LDFLAGS) $^ $(LDLIBS) endif %.o: %.cc @@ -706,11 +645,11 @@ CXXFLAGS_NOVERIFIC = $(CXXFLAGS) LDLIBS_NOVERIFIC = $(LDLIBS) endif -$(PROGRAM_PREFIX)yosys-config: misc/yosys-config.in +yosys-config: misc/yosys-config.in $(P) $(SED) -e 's#@CXXFLAGS@#$(subst -I. -I"$(YOSYS_SRC)",-I"$(DATDIR)/include",$(strip $(CXXFLAGS_NOVERIFIC)))#;' \ -e 's#@CXX@#$(strip $(CXX))#;' -e 's#@LDFLAGS@#$(strip $(LDFLAGS) $(PLUGIN_LDFLAGS))#;' -e 's#@LDLIBS@#$(strip $(LDLIBS_NOVERIFIC))#;' \ - -e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > $(PROGRAM_PREFIX)yosys-config - $(Q) chmod +x $(PROGRAM_PREFIX)yosys-config + -e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > yosys-config + $(Q) chmod +x yosys-config abc/abc-$(ABCREV)$(EXE) abc/libabc-$(ABCREV).a: $(P) @@ -721,12 +660,11 @@ ifneq ($(ABCREV),default) $(Q) if ( cd abc 2> /dev/null && ! git diff-index --quiet HEAD; ); then \ echo 'REEBE: NOP pbagnvaf ybpny zbqvsvpngvbaf! Frg NOPERI=qrsnhyg va Lbflf Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; false; \ fi -# set a variable so the test fails if git fails to run - when comparing outputs directly, empty string would match empty string - $(Q) if ! (cd abc 2> /dev/null && rev="`git rev-parse $(ABCREV)`" && test "`git rev-parse HEAD`" == "$$rev"); then \ + $(Q) if test "`cd abc 2> /dev/null && git rev-parse --short HEAD`" != "$(ABCREV)"; then \ test $(ABCPULL) -ne 0 || { echo 'REEBE: NOP abg hc gb qngr naq NOPCHYY frg gb 0 va Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; exit 1; }; \ echo "Pulling ABC from $(ABCURL):"; set -x; \ test -d abc || git clone $(ABCURL) abc; \ - cd abc && $(MAKE) DEP= clean && git fetch $(ABCURL) && git checkout $(ABCREV); \ + cd abc && $(MAKE) DEP= clean && git fetch origin master && git checkout $(ABCREV); \ fi endif $(Q) rm -f abc/abc-[0-9a-f]* @@ -737,11 +675,11 @@ ifeq ($(ABCREV),default) .PHONY: abc/libabc-$(ABCREV).a endif -$(PROGRAM_PREFIX)yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE) - $(P) cp abc/abc-$(ABCREV)$(EXE) $(PROGRAM_PREFIX)yosys-abc$(EXE) +yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE) + $(P) cp abc/abc-$(ABCREV)$(EXE) yosys-abc$(EXE) -$(PROGRAM_PREFIX)yosys-libabc.a: abc/libabc-$(ABCREV).a - $(P) cp abc/libabc-$(ABCREV).a $(PROGRAM_PREFIX)yosys-libabc.a +yosys-libabc.a: abc/libabc-$(ABCREV).a + $(P) cp abc/libabc-$(ABCREV).a yosys-libabc.a ifneq ($(SEED),) SEEDOPT="-S $(SEED)" @@ -768,7 +706,6 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT) +cd tests/bram && bash run-test.sh $(SEEDOPT) +cd tests/various && bash run-test.sh - +cd tests/select && bash run-test.sh +cd tests/sat && bash run-test.sh +cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) +cd tests/svtypes && bash run-test.sh $(SEEDOPT) @@ -782,10 +719,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/arch/efinix && bash run-test.sh $(SEEDOPT) +cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT) +cd tests/arch/gowin && bash run-test.sh $(SEEDOPT) - +cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT) +cd tests/rpc && bash run-test.sh - +cd tests/memfile && bash run-test.sh - +cd tests/verilog && bash run-test.sh @echo "" @echo " Passed \"make test\"." @echo "" @@ -822,15 +756,15 @@ clean-unit-test: install: $(TARGETS) $(EXTRA_TARGETS) $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR) - $(INSTALL_SUDO) cp $(filter-out libyosys.so,$(TARGETS)) $(DESTDIR)$(BINDIR) -ifneq ($(filter $(PROGRAM_PREFIX)yosys,$(TARGETS)),) - $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys + $(INSTALL_SUDO) cp $(TARGETS) $(DESTDIR)$(BINDIR) +ifneq ($(filter yosys,$(TARGETS)),) + $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/yosys endif -ifneq ($(filter $(PROGRAM_PREFIX)yosys-abc,$(TARGETS)),) - $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc +ifneq ($(filter yosys-abc,$(TARGETS)),) + $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/yosys-abc endif -ifneq ($(filter $(PROGRAM_PREFIX)yosys-filterlib,$(TARGETS)),) - $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib +ifneq ($(filter yosys-filterlib,$(TARGETS)),) + $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/yosys-filterlib endif $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR) $(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/. @@ -839,9 +773,9 @@ ifeq ($(ENABLE_LIBYOSYS),1) $(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(LIBDIR)/ $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so ifeq ($(ENABLE_PYOSYS),1) - $(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys - $(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so - $(INSTALL_SUDO) cp misc/__init__.py $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/ + $(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/pyosys + $(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/pyosys/ + $(INSTALL_SUDO) cp misc/__init__.py $(PYTHON_DESTDIR)/pyosys/ endif endif @@ -851,14 +785,14 @@ uninstall: ifeq ($(ENABLE_LIBYOSYS),1) $(INSTALL_SUDO) rm -vf $(DESTDIR)$(LIBDIR)/libyosys.so ifeq ($(ENABLE_PYOSYS),1) - $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so - $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/__init__.py - $(INSTALL_SUDO) rmdir $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys + $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/pyosys/libyosys.so + $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/pyosys/__init__.py + $(INSTALL_SUDO) rmdir $(PYTHON_DESTDIR)/pyosys endif endif update-manual: $(TARGETS) $(EXTRA_TARGETS) - cd manual && ../$(PROGRAM_PREFIX)yosys -p 'help -write-tex-command-reference-manual' + cd manual && ../yosys -p 'help -write-tex-command-reference-manual' manual: $(TARGETS) $(EXTRA_TARGETS) cd manual && bash appnotes.sh @@ -884,13 +818,13 @@ clean: clean-abc: $(MAKE) -C abc DEP= clean - rm -f $(PROGRAM_PREFIX)yosys-abc$(EXE) $(PROGRAM_PREFIX)yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a + rm -f yosys-abc$(EXE) yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a mrproper: clean git clean -xdf coverage: - ./$(PROGRAM_PREFIX)yosys -qp 'help; help -all' + ./yosys -qp 'help; help -all' rm -rf coverage.info coverage_html lcov --capture -d . --no-external -o coverage.info genhtml coverage.info --output-directory coverage_html @@ -916,9 +850,9 @@ ifeq ($(CONFIG),mxe) mxebin: $(TARGETS) $(EXTRA_TARGETS) rm -rf yosys-win32-mxebin-$(YOSYS_VER){,.zip} mkdir -p yosys-win32-mxebin-$(YOSYS_VER) - cp -r $(PROGRAM_PREFIX)yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/ + cp -r yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/ ifeq ($(ENABLE_ABC),1) - cp -r $(PROGRAM_PREFIX)yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/ + cp -r yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/ endif echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-mxebin-$(YOSYS_VER)/readme.txt echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt @@ -952,15 +886,6 @@ config-emcc: clean echo 'ENABLE_ABC := 0' >> Makefile.conf echo 'ENABLE_PLUGINS := 0' >> Makefile.conf echo 'ENABLE_READLINE := 0' >> Makefile.conf - echo 'ENABLE_ZLIB := 0' >> Makefile.conf - -config-wasi: clean - echo 'CONFIG := wasi' > Makefile.conf - echo 'ENABLE_TCL := 0' >> Makefile.conf - echo 'ENABLE_ABC := 0' >> Makefile.conf - echo 'ENABLE_PLUGINS := 0' >> Makefile.conf - echo 'ENABLE_READLINE := 0' >> Makefile.conf - echo 'ENABLE_ZLIB := 0' >> Makefile.conf config-mxe: clean echo 'CONFIG := mxe' > Makefile.conf @@ -995,9 +920,6 @@ echo-yosys-ver: echo-git-rev: @echo "$(GIT_REV)" -echo-abc-rev: - @echo "$(ABCREV)" - -include libs/*/*.d -include frontends/*/*.d -include passes/*/*.d diff --git a/README.md b/README.md index 203a292d1b9..1ce5d47ea65 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ``` yosys -- Yosys Open SYnthesis Suite -Copyright (C) 2012 - 2020 Claire Wolf +Copyright (C) 2012 - 2019 Clifford Wolf Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -69,7 +69,7 @@ prerequisites for building yosys: graphviz xdot pkg-config python3 libboost-system-dev \ libboost-python-dev libboost-filesystem-dev zlib1g-dev -Similarily, on Mac OS X Homebrew can be used to install dependencies (from within cloned yosys repository): +Similarily, on Mac OS X Homebrew can be used to install dependencies: $ brew tap Homebrew/bundle && brew bundle @@ -118,13 +118,6 @@ Tests are located in the tests subdirectory and can be executed using the test t $ make test -To use a separate (out-of-tree) build directory, provide a path to the Makefile. - - $ mkdir build; cd build - $ make -f ../Makefile - -Out-of-tree builds require a clean source tree. - Getting Started =============== @@ -281,9 +274,6 @@ Verilog Attributes and non-standard features temporary variable within an always block. This is mostly used internally by Yosys to synthesize Verilog functions and access arrays. -- The ``nowrshmsk`` attribute on a register prohibits the generation of - shift-and-mask type circuits for writing to bit slices of that register. - - The ``onehot`` attribute on wires mark them as one-hot state register. This is used for example for memory port sharing and set by the fsm_map pass. @@ -309,9 +299,7 @@ Verilog Attributes and non-standard features that have ports with a width that depends on a parameter. - The ``hdlname`` attribute is used by some passes to document the original - (HDL) name of a module when renaming a module. It should contain a single - name, or, when describing a hierarchical name in a flattened design, multiple - names separated by a single space character. + (HDL) name of a module when renaming a module. - The ``keep`` attribute on cells and wires is used to mark objects that should never be removed by the optimizer. This is used for example for cells that @@ -376,32 +364,25 @@ Verilog Attributes and non-standard features it as the external-facing pin of an I/O pad, and prevents ``iopadmap`` from inserting another pad cell on it. -- The module attribute ``abc9_lut`` is an integer attribute indicating to - `abc9` that this module describes a LUT with an area cost of this value, and - propagation delays described using `specify` statements. - -- The module attribute ``abc9_box`` is a boolean specifying a black/white-box - definition, with propagation delays described using `specify` statements, for - use by `abc9`. +- The module attribute ``abc_box_id`` specifies a positive integer linking a + blackbox or whitebox definition to a corresponding entry in a `abc9` + box-file. -- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and +- The port attribute ``abc_carry`` marks the carry-in (if an input port) and carry-out (if output port) ports of a box. This information is necessary for `abc9` to preserve the integrity of carry-chains. Specifying this attribute onto a bus port will affect only its most significant bit. -- The module attribute ``abc9_flop`` is a boolean marking the module as a - flip-flop. This allows `abc9` to analyse its contents in order to perform - sequential synthesis. +- The port attribute ``abc_arrival`` specifies an integer (for output ports + only) to be used as the arrival time of this sequential port. It can be used, + for example, to specify the clk-to-Q delay of a flip-flop for consideration + during techmapping. - The frontend sets attributes ``always_comb``, ``always_latch`` and ``always_ff`` on processes derived from SystemVerilog style always blocks according to the type of the always. These are checked for correctness in ``proc_dlatch``. -- The cell attribute ``wildcard_port_conns`` represents wildcard port - connections (SystemVerilog ``.*``). These are resolved to concrete - connections to matching wires in ``hierarchy``. - - In addition to the ``(* ... *)`` attribute syntax, Yosys supports the non-standard ``{* ... *}`` attribute syntax to set default attributes for everything that comes after the ``{* ... *}`` statement. (Reset @@ -452,17 +433,6 @@ Verilog Attributes and non-standard features ... endmodule -- The ``wiretype`` attribute is added by the verilog parser for wires of a - typedef'd type to indicate the type identifier. - -- Various ``enum_value_{value}`` attributes are added to wires of an enumerated type - to give a map of possible enum items to their values. - -- The ``enum_base_type`` attribute is added to enum items to indicate which - enum they belong to (enums -- anonymous and otherwise -- are - automatically named with an auto-incrementing counter). Note that enums - are currently not strongly typed. - - A limited subset of DPI-C functions is supported. The plugin mechanism (see ``help plugin``) can be used to load .so files with implementations of DPI-C routines. As a non-standard extension it is possible to specify @@ -484,10 +454,10 @@ Verilog Attributes and non-standard features expressions over parameters and constant values are allowed). The intended use for this is synthesis-time DRC. -- There is limited support for converting ``specify`` .. ``endspecify`` - statements to special ``$specify2``, ``$specify3``, and ``$specrule`` cells, - for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to - enable this functionality. (By default these blocks are ignored.) +- There is limited support for converting specify .. endspecify statements to + special ``$specify2``, ``$specify3``, and ``$specrule`` cells, for use in + blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this + functionality. (By default specify .. endspecify blocks are ignored.) Non-standard or SystemVerilog features for formal verification @@ -553,12 +523,6 @@ from SystemVerilog: SystemVerilog files being read into the same design afterwards. - typedefs are supported (including inside packages) - - type casts are currently not supported - -- enums are supported (including inside packages) - - but are currently not strongly typed - -- packed structs and unions are supported. - SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether ports are inputs or outputs are supported. diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 81a3f483bba..44718baaed0 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -126,9 +126,9 @@ struct AigerWriter for (auto wire : module->wires()) { - if (wire->attributes.count(ID::init)) { + if (wire->attributes.count("\\init")) { SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) if (initval[i] == State::S0 || initval[i] == State::S1) init_map[initsig[i]] = initval[i] == State::S1; @@ -169,31 +169,31 @@ struct AigerWriter for (auto cell : module->cells()) { - if (cell->type == ID($_NOT_)) + if (cell->type == "$_NOT_") { - SigBit A = sigmap(cell->getPort(ID::A).as_bit()); - SigBit Y = sigmap(cell->getPort(ID::Y).as_bit()); + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; continue; } - if (cell->type.in(ID($_FF_), ID($_DFF_N_), ID($_DFF_P_))) + if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) { - SigBit D = sigmap(cell->getPort(ID::D).as_bit()); - SigBit Q = sigmap(cell->getPort(ID::Q).as_bit()); + SigBit D = sigmap(cell->getPort("\\D").as_bit()); + SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); unused_bits.erase(D); undriven_bits.erase(Q); ff_map[Q] = D; continue; } - if (cell->type == ID($_AND_)) + if (cell->type == "$_AND_") { - SigBit A = sigmap(cell->getPort(ID::A).as_bit()); - SigBit B = sigmap(cell->getPort(ID::B).as_bit()); - SigBit Y = sigmap(cell->getPort(ID::Y).as_bit()); + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit B = sigmap(cell->getPort("\\B").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); unused_bits.erase(A); unused_bits.erase(B); undriven_bits.erase(Y); @@ -201,66 +201,66 @@ struct AigerWriter continue; } - if (cell->type == ID($initstate)) + if (cell->type == "$initstate") { - SigBit Y = sigmap(cell->getPort(ID::Y).as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); undriven_bits.erase(Y); initstate_bits.insert(Y); continue; } - if (cell->type == ID($assert)) + if (cell->type == "$assert") { - SigBit A = sigmap(cell->getPort(ID::A).as_bit()); - SigBit EN = sigmap(cell->getPort(ID::EN).as_bit()); + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); unused_bits.erase(A); unused_bits.erase(EN); asserts.push_back(make_pair(A, EN)); continue; } - if (cell->type == ID($assume)) + if (cell->type == "$assume") { - SigBit A = sigmap(cell->getPort(ID::A).as_bit()); - SigBit EN = sigmap(cell->getPort(ID::EN).as_bit()); + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); unused_bits.erase(A); unused_bits.erase(EN); assumes.push_back(make_pair(A, EN)); continue; } - if (cell->type == ID($live)) + if (cell->type == "$live") { - SigBit A = sigmap(cell->getPort(ID::A).as_bit()); - SigBit EN = sigmap(cell->getPort(ID::EN).as_bit()); + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); unused_bits.erase(A); unused_bits.erase(EN); liveness.push_back(make_pair(A, EN)); continue; } - if (cell->type == ID($fair)) + if (cell->type == "$fair") { - SigBit A = sigmap(cell->getPort(ID::A).as_bit()); - SigBit EN = sigmap(cell->getPort(ID::EN).as_bit()); + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); unused_bits.erase(A); unused_bits.erase(EN); fairness.push_back(make_pair(A, EN)); continue; } - if (cell->type == ID($anyconst)) + if (cell->type == "$anyconst") { - for (auto bit : sigmap(cell->getPort(ID::Y))) { + for (auto bit : sigmap(cell->getPort("\\Y"))) { undriven_bits.erase(bit); ff_map[bit] = bit; } continue; } - if (cell->type == ID($anyseq)) + if (cell->type == "$anyseq") { - for (auto bit : sigmap(cell->getPort(ID::Y))) { + for (auto bit : sigmap(cell->getPort("\\Y"))) { undriven_bits.erase(bit); input_bits.insert(bit); } @@ -629,30 +629,30 @@ struct AigerWriter int a = aig_map.at(sig[i]); if (verbose_map) - wire_lines[a] += stringf("wire %d %d %s\n", a, wire->start_offset+i, log_id(wire)); + wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); if (wire->port_input) { log_assert((a & 1) == 0); - input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire)); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } if (wire->port_output) { int o = ordered_outputs.at(sig[i]); - output_lines[o] += stringf("output %d %d %s\n", o, wire->start_offset+i, log_id(wire)); + output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } if (init_inputs.count(sig[i])) { int a = init_inputs.at(sig[i]); log_assert((a & 1) == 0); - init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire)); + init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); if (zinit_mode && (aig_latchinit.at(l) == 1)) - latch_lines[l] += stringf("invlatch %d %d %s\n", l, wire->start_offset+i, log_id(wire)); + latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); else - latch_lines[l] += stringf("latch %d %d %s\n", l, wire->start_offset+i, log_id(wire)); + latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); } } } @@ -681,7 +681,7 @@ struct AigerWriter struct AigerBackend : public Backend { AigerBackend() : Backend("aiger", "write design to AIGER file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -719,7 +719,7 @@ struct AigerBackend : public Backend { log(" AIGER file happy.\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; bool zinit_mode = false; @@ -787,14 +787,6 @@ struct AigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - if (!design->selected_whole_module(top_module)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module)); - - if (!top_module->processes.empty()) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", log_id(top_module)); - if (!top_module->memories.empty()) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", log_id(top_module)); - AigerWriter writer(top_module, zinit_mode, imode, omode, bmode, lmode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ef0103c179b..627133314e4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -47,7 +47,6 @@ inline static uint32_t bswap32(uint32_t x) #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/utils.h" -#include "kernel/timinginfo.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -76,16 +75,14 @@ void aiger_encode(std::ostream &f, int x) struct XAigerWriter { - Design *design; Module *module; SigMap sigmap; - dict init_map; pool input_bits, output_bits; dict not_map, alias_map; dict> and_map; - vector ci_bits, co_bits; - vector ff_list; + vector> ci_bits; + vector> co_bits; dict arrival_times; vector> aig_gates; @@ -96,6 +93,7 @@ struct XAigerWriter dict ordered_outputs; vector box_list; + bool omode = false; int mkgate(int a0, int a1) { @@ -139,10 +137,11 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool dff_mode) : design(module->design), module(module), sigmap(module) + XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; + pool keep_bits; // promote public wires for (auto wire : module->wires()) @@ -154,323 +153,362 @@ struct XAigerWriter if (wire->port_input) sigmap.add(wire); - // promote keep wires for (auto wire : module->wires()) - if (wire->get_bool_attribute(ID::keep) || wire->get_bool_attribute(ID::abc9_keep)) - sigmap.add(wire); + { + bool keep = wire->attributes.count("\\keep"); - for (auto wire : module->wires()) { - auto it = wire->attributes.find(ID::init); for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); SigBit bit = sigmap(wirebit); - if (bit.wire == nullptr) { - if (wire->port_output) { - aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); - } - continue; + if (bit.wire) { + undriven_bits.insert(bit); + unused_bits.insert(bit); } - undriven_bits.insert(bit); - unused_bits.insert(bit); + if (keep) + keep_bits.insert(wirebit); - bool keep = wire->get_bool_attribute(ID::abc9_keep); - if (wire->port_input || keep) - input_bits.insert(bit); - - keep = keep || wire->get_bool_attribute(ID::keep); - if (wire->port_output || keep) { + if (wire->port_input || keep) { if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); + alias_map[bit] = wirebit; + input_bits.insert(wirebit); } - if (it != wire->attributes.end()) { - auto s = it->second[i]; - if (s != State::Sx) { - auto r = init_map.insert(std::make_pair(bit, it->second[i])); - if (!r.second && r.first->second != it->second[i]) - log_error("Bit '%s' has a conflicting (* init *) value.\n", log_signal(bit)); + if (wire->port_output || keep) { + if (bit != RTLIL::Sx) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); } + else + log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit)); } } } - TimingInfo timing; - - for (auto cell : module->cells()) { - if (!cell->has_keep_attr()) { - if (cell->type == ID($_NOT_)) - { - SigBit A = sigmap(cell->getPort(ID::A).as_bit()); - SigBit Y = sigmap(cell->getPort(ID::Y).as_bit()); - unused_bits.erase(A); - undriven_bits.erase(Y); - not_map[Y] = A; - continue; - } + for (auto bit : input_bits) + undriven_bits.erase(sigmap(bit)); + for (auto bit : output_bits) + if (!bit.wire->port_input) + unused_bits.erase(bit); - if (cell->type == ID($_AND_)) - { - SigBit A = sigmap(cell->getPort(ID::A).as_bit()); - SigBit B = sigmap(cell->getPort(ID::B).as_bit()); - SigBit Y = sigmap(cell->getPort(ID::Y).as_bit()); - unused_bits.erase(A); - unused_bits.erase(B); - undriven_bits.erase(Y); - and_map[Y] = make_pair(A, B); - continue; - } + // TODO: Speed up toposort -- ultimately we care about + // box ordering, but not individual AIG cells + dict> bit_drivers, bit_users; + TopoSort toposort; + bool abc9_box_seen = false; - if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep)) - { - SigBit D = sigmap(cell->getPort(ID::D).as_bit()); - SigBit Q = sigmap(cell->getPort(ID::Q).as_bit()); - unused_bits.erase(D); - undriven_bits.erase(Q); - alias_map[Q] = D; - ff_list.emplace_back(cell); - continue; + for (auto cell : module->selected_cells()) { + if (cell->type == "$_NOT_") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + unused_bits.erase(A); + undriven_bits.erase(Y); + not_map[Y] = A; + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); } - - if (cell->type.in(ID($specify2), ID($specify3), ID($specrule))) - continue; + continue; } - RTLIL::Module* inst_module = design->module(cell->type); - if (inst_module && inst_module->get_blackbox_attribute()) { - bool abc9_flop = false; - - auto it = cell->attributes.find(ID::abc9_box_seq); - if (it != cell->attributes.end()) { - log_assert(!cell->has_keep_attr()); - log_assert(cell->parameters.empty()); - int abc9_box_seq = it->second.as_int(); - if (GetSize(box_list) <= abc9_box_seq) - box_list.resize(abc9_box_seq+1); - box_list[abc9_box_seq] = cell; - // Only flop boxes may have arrival times - // (all others are combinatorial) - log_assert(cell->parameters.empty()); - abc9_flop = inst_module->get_bool_attribute(ID::abc9_flop); - if (!abc9_flop) - continue; + if (cell->type == "$_AND_") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit B = sigmap(cell->getPort("\\B").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + unused_bits.erase(A); + unused_bits.erase(B); + undriven_bits.erase(Y); + and_map[Y] = make_pair(A, B); + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); } + continue; + } - if (!timing.count(inst_module->name)) - timing.setup_module(inst_module); - auto &t = timing.at(inst_module->name).arrival; - for (const auto &conn : cell->connections()) { - auto port_wire = inst_module->wire(conn.first); - if (!port_wire->port_output) - continue; - - for (int i = 0; i < GetSize(conn.second); i++) { - auto d = t.at(TimingInfo::NameBit(conn.first,i), 0); - if (d == 0) - continue; - -#ifndef NDEBUG - if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(inst_module->name, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n", - log_id(cell->type), log_id(conn.first), i, d); + log_assert(!holes_mode); + + RTLIL::Module* inst_module = module->design->module(cell->type); + if (inst_module && inst_module->attributes.count("\\abc9_box_id")) { + abc9_box_seen = true; + + if (!holes_mode) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + auto port_wire = inst_module->wire(conn.first); + if (port_wire->port_input) { + // Ignore inout for the sake of topographical ordering + if (port_wire->port_output) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); } -#endif - arrival_times[conn.second[i]] = d; + + if (port_wire->port_output) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); } } - - if (abc9_flop) - continue; } + else { + bool cell_known = inst_module || cell->known(); + for (const auto &c : cell->connections()) { + if (c.second.is_fully_const()) continue; + auto port_wire = inst_module ? inst_module->wire(c.first) : nullptr; + auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first); + auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first); + if (!is_input && !is_output) + log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); + + if (is_input) { + for (auto b : c.second) { + Wire *w = b.wire; + if (!w) continue; + if (!w->port_output || !cell_known) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + output_bits.insert(b); + unused_bits.erase(b); + + if (!cell_known) + keep_bits.insert(b); + } + } + } + if (is_output) { + int arrival = 0; + if (port_wire) { + auto it = port_wire->attributes.find("\\abc9_arrival"); + if (it != port_wire->attributes.end()) { + if (it->second.flags != 0) + log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); + arrival = it->second.as_int(); + } + } - bool cell_known = inst_module || cell->known(); - for (const auto &c : cell->connections()) { - if (c.second.is_fully_const()) continue; - auto port_wire = inst_module ? inst_module->wire(c.first) : nullptr; - auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first); - auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first); - if (!is_input && !is_output) - log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); - - if (is_input) - for (auto b : c.second) { - Wire *w = b.wire; - if (!w) continue; - // Do not add as PO if bit is already a PI - if (input_bits.count(b)) - continue; - if (!w->port_output || !cell_known) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - output_bits.insert(b); + for (auto b : c.second) { + Wire *w = b.wire; + if (!w) continue; + input_bits.insert(b); + SigBit O = sigmap(b); + if (O != b) + alias_map[O] = b; + undriven_bits.erase(O); + + if (arrival) + arrival_times[b] = arrival; } } + } } //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } - dict> box_ports; - for (auto cell : box_list) { - log_assert(cell); + if (abc9_box_seen) { + for (auto &it : bit_users) + if (bit_drivers.count(it.first)) + for (auto driver_cell : bit_drivers.at(it.first)) + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); - RTLIL::Module* box_module = design->module(cell->type); - log_assert(box_module); - log_assert(box_module->has_attribute(ID::abc9_box_id)); +#if 0 + toposort.analyze_loops = true; +#endif + bool no_loops YS_ATTRIBUTE(unused) = toposort.sort(); +#if 0 + unsigned i = 0; + for (auto &it : toposort.loops) { + log(" loop %d\n", i++); + for (auto cell_name : it) { + auto cell = module->cell(cell_name); + log_assert(cell); + log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str()); + } + } +#endif + log_assert(no_loops); + + for (auto cell_name : toposort.sorted) { + RTLIL::Cell *cell = module->cell(cell_name); + log_assert(cell); - auto r = box_ports.insert(cell->type); - if (r.second) { - // Make carry in the last PI, and carry out the last PO - // since ABC requires it this way - IdString carry_in, carry_out; + RTLIL::Module* box_module = module->design->module(cell->type); + if (!box_module || !box_module->attributes.count("\\abc9_box_id")) + continue; + + bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); + + // Fully pad all unused input connections of this box cell with S0 + // Fully pad all undriven output connections of this box cell with anonymous wires + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) for (const auto &port_name : box_module->ports) { - auto w = box_module->wire(port_name); + RTLIL::Wire* w = box_module->wire(port_name); log_assert(w); - if (w->get_bool_attribute(ID::abc9_carry)) { - if (w->port_input) { - if (carry_in != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module)); - carry_in = port_name; + auto it = cell->connections_.find(port_name); + if (w->port_input) { + RTLIL::SigSpec rhs; + if (it != cell->connections_.end()) { + if (GetSize(it->second) < GetSize(w)) + it->second.append(RTLIL::SigSpec(State::S0, GetSize(w)-GetSize(it->second))); + rhs = it->second; + } + else { + rhs = RTLIL::SigSpec(State::S0, GetSize(w)); + cell->setPort(port_name, rhs); } - if (w->port_output) { - if (carry_out != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module)); - carry_out = port_name; + + int offset = 0; + for (auto b : rhs.bits()) { + SigBit I = sigmap(b); + if (b == RTLIL::Sx) + b = State::S0; + else if (I != b) { + if (I == RTLIL::Sx) + alias_map[b] = State::S0; + else + alias_map[b] = I; + } + co_bits.emplace_back(b, cell, port_name, offset++, 0); + unused_bits.erase(b); } } - else - r.first->second.push_back(port_name); - } + if (w->port_output) { + RTLIL::SigSpec rhs; + auto it = cell->connections_.find(w->name); + if (it != cell->connections_.end()) { + if (GetSize(it->second) < GetSize(w)) + it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); + rhs = it->second; + } + else { + Wire *wire = module->addWire(NEW_ID, GetSize(w)); + if (blackbox) + wire->set_bool_attribute(ID(abc9_padding)); + rhs = wire; + cell->setPort(port_name, rhs); + } - if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_module)); - if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module)); - if (carry_in != IdString()) { - r.first->second.push_back(carry_in); - r.first->second.push_back(carry_out); + int offset = 0; + for (const auto &b : rhs.bits()) { + ci_bits.emplace_back(b, cell, port_name, offset++); + SigBit O = sigmap(b); + if (O != b) + alias_map[O] = b; + undriven_bits.erase(O); + input_bits.erase(b); + } + } } + box_list.emplace_back(cell); } - for (auto port_name : r.first->second) { - auto w = box_module->wire(port_name); - log_assert(w); - auto rhs = cell->connections_.at(port_name, SigSpec()); - rhs.append(Const(State::Sx, GetSize(w)-GetSize(rhs))); - if (w->port_input) - for (auto b : rhs) { - SigBit I = sigmap(b); - if (b == RTLIL::Sx) - b = State::S0; - else if (I != b) { - if (I == RTLIL::Sx) - alias_map[b] = State::S0; - else - alias_map[b] = I; - } - co_bits.emplace_back(b); - unused_bits.erase(I); - } - if (w->port_output) - for (const auto &b : rhs) { - SigBit O = sigmap(b); - if (O != b) - alias_map[O] = b; - ci_bits.emplace_back(b); - undriven_bits.erase(O); - } + // TODO: Free memory from toposort, bit_drivers, bit_users + } + + for (auto bit : input_bits) { + if (!output_bits.count(bit)) + continue; + RTLIL::Wire *wire = bit.wire; + // If encountering an inout port, or a keep-ed wire, then create a new wire + // with $inout.out suffix, make it a PO driven by the existing inout, and + // inherit existing inout's drivers + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + || keep_bits.count(bit)) { + RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str()); + RTLIL::Wire *new_wire = module->wire(wire_name); + if (!new_wire) + new_wire = module->addWire(wire_name, GetSize(wire)); + SigBit new_bit(new_wire, bit.offset); + module->connect(new_bit, bit); + if (not_map.count(bit)) { + auto a = not_map.at(bit); + not_map[new_bit] = a; + } + else if (and_map.count(bit)) { + auto a = and_map.at(bit); + and_map[new_bit] = a; + } + else if (alias_map.count(bit)) { + auto a = alias_map.at(bit); + alias_map[new_bit] = a; + } + else + alias_map[new_bit] = bit; + output_bits.erase(bit); + output_bits.insert(new_bit); } } - for (auto bit : input_bits) - undriven_bits.erase(bit); - for (auto bit : output_bits) - unused_bits.erase(sigmap(bit)); for (auto bit : unused_bits) undriven_bits.erase(bit); - // Make all undriven bits a primary input - for (auto bit : undriven_bits) { - input_bits.insert(bit); - undriven_bits.erase(bit); + if (!undriven_bits.empty() && !holes_mode) { + undriven_bits.sort(); + for (auto bit : undriven_bits) { + log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + input_bits.insert(bit); + } + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } - struct sort_by_port_id { - bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { - return a.wire->port_id < b.wire->port_id || - (a.wire->port_id == b.wire->port_id && a.offset < b.offset); - } - }; - input_bits.sort(sort_by_port_id()); - output_bits.sort(sort_by_port_id()); + if (holes_mode) { + struct sort_by_port_id { + bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { + return a.wire->port_id < b.wire->port_id; + } + }; + input_bits.sort(sort_by_port_id()); + output_bits.sort(sort_by_port_id()); + } + else { + input_bits.sort(); + output_bits.sort(); + } + + not_map.sort(); + and_map.sort(); aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (const auto &bit : input_bits) { + for (auto bit : input_bits) { aig_m++, aig_i++; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } - for (auto cell : ff_list) { - const SigBit &q = sigmap(cell->getPort(ID::Q)); - aig_m++, aig_i++; - log_assert(!aig_map.count(q)); - aig_map[q] = 2*aig_m; - } - - for (auto &bit : ci_bits) { + for (auto &c : ci_bits) { + RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - // 1'bx may exist here due to a box output - // that has been padded to its full width - if (bit == State::Sx) - continue; - log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } - for (auto bit : co_bits) { - ordered_outputs[bit] = aig_o++; + for (auto &c : co_bits) { + RTLIL::SigBit bit = std::get<0>(c); + std::get<4>(c) = ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } - for (const auto &bit : output_bits) { - ordered_outputs[bit] = aig_o++; - int aig; - // Unlike bit2aig() which checks aig_map first for - // inout/scc bits, since aig_map will point to - // the PI, first attempt to find the NOT/AND driver - // before resorting to an aig_map lookup (which - // could be another PO) - if (input_bits.count(bit)) { - if (not_map.count(bit)) { - aig = bit2aig(not_map.at(bit)) ^ 1; - } else if (and_map.count(bit)) { - auto args = and_map.at(bit); - int a0 = bit2aig(args.first); - int a1 = bit2aig(args.second); - aig = mkgate(a0, a1); - } - else - aig = aig_map.at(bit); - } - else - aig = bit2aig(bit); - aig_outputs.push_back(aig); + if (output_bits.empty()) { + output_bits.insert(State::S0); + omode = true; } - for (auto cell : ff_list) { - const SigBit &d = sigmap(cell->getPort(ID::D)); - aig_o++; - aig_outputs.push_back(aig_map.at(d)); + for (auto bit : output_bits) { + ordered_outputs[bit] = aig_o++; + aig_outputs.push_back(bit2aig(bit)); } + } void write_aiger(std::ostream &f, bool ascii_mode) @@ -532,6 +570,7 @@ struct XAigerWriter f << "c"; + log_assert(!output_bits.empty()); auto write_buffer = [](std::stringstream &buffer, int i32) { int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); @@ -539,16 +578,16 @@ struct XAigerWriter std::stringstream h_buffer; auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); - log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ff_list) + GetSize(ci_bits)); - write_h_buffer(GetSize(input_bits) + GetSize(ff_list) + GetSize(ci_bits)); - log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(ff_list) + GetSize(co_bits)); - write_h_buffer(GetSize(output_bits) + GetSize(ff_list) + GetSize(co_bits)); - log_debug("piNum = %d\n", GetSize(input_bits) + GetSize(ff_list)); - write_h_buffer(GetSize(input_bits) + GetSize(ff_list)); - log_debug("poNum = %d\n", GetSize(output_bits) + GetSize(ff_list)); - write_h_buffer(GetSize(output_bits) + GetSize(ff_list)); + log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); + write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); + write_h_buffer(output_bits.size() + GetSize(co_bits)); + log_debug("piNum = %d\n", GetSize(input_bits)); + write_h_buffer(input_bits.size()); + log_debug("poNum = %d\n", GetSize(output_bits)); + write_h_buffer(output_bits.size()); log_debug("boxNum = %d\n", GetSize(box_list)); - write_h_buffer(GetSize(box_list)); + write_h_buffer(box_list.size()); auto write_buffer_float = [](std::stringstream &buffer, float f32) { buffer.write(reinterpret_cast(&f32), sizeof(f32)); @@ -562,106 +601,126 @@ struct XAigerWriter //for (auto bit : output_bits) // write_o_buffer(0); - if (!box_list.empty() || !ff_list.empty()) { - dict> cell_cache; + if (!box_list.empty()) { + RTLIL::Module *holes_module = module->design->addModule("$__holes__"); + log_assert(holes_module); + int port_id = 1; int box_count = 0; for (auto cell : box_list) { - log_assert(cell); - log_assert(cell->parameters.empty()); - - auto r = cell_cache.insert(cell->type); - auto &v = r.first->second; - if (r.second) { - RTLIL::Module* box_module = design->module(cell->type); - log_assert(box_module); - - int box_inputs = 0, box_outputs = 0; - for (auto port_name : box_module->ports) { - RTLIL::Wire *w = box_module->wire(port_name); - log_assert(w); - if (w->port_input) - box_inputs += GetSize(w); - if (w->port_output) - box_outputs += GetSize(w); - } + RTLIL::Module* box_module = module->design->module(cell->type); + int box_inputs = 0, box_outputs = 0; + Cell *holes_cell = nullptr; + if (box_module->get_bool_attribute("\\whitebox")) { + holes_cell = holes_module->addCell(cell->name, cell->type); + holes_cell->parameters = cell->parameters; + } - std::get<0>(v) = box_inputs; - std::get<1>(v) = box_outputs; - std::get<2>(v) = box_module->attributes.at(ID::abc9_box_id).as_int(); + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (const auto &port_name : box_module->ports) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + RTLIL::Wire *holes_wire; + RTLIL::SigSpec port_wire; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + } + if (holes_cell) + port_wire.append(holes_wire); + } + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); + } + if (w->port_output) { + box_outputs += GetSize(w); + for (int i = 0; i < GetSize(w); i++) { + if (GetSize(w) == 1) + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); + else + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); + holes_wire->port_output = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + if (holes_cell) + port_wire.append(holes_wire); + else + holes_module->connect(holes_wire, State::S0); + } + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); + } } - write_h_buffer(std::get<0>(v)); - write_h_buffer(std::get<1>(v)); - write_h_buffer(std::get<2>(v)); + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_module->attributes.at("\\abc9_box_id").as_int()); write_h_buffer(box_count++); } std::stringstream r_buffer; auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - log_debug("flopNum = %d\n", GetSize(ff_list)); - write_r_buffer(ff_list.size()); - - std::stringstream s_buffer; - auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); - write_s_buffer(ff_list.size()); - - dict clk_to_mergeability; - for (const auto cell : ff_list) { - const SigBit &d = sigmap(cell->getPort(ID::D)); - const SigBit &q = sigmap(cell->getPort(ID::Q)); - - SigSpec clk_and_pol{sigmap(cell->getPort(ID::C)), cell->type[6] == 'P' ? State::S1 : State::S0}; - auto r = clk_to_mergeability.insert(std::make_pair(clk_and_pol, clk_to_mergeability.size()+1)); - int mergeability = r.first->second; - log_assert(mergeability > 0); - write_r_buffer(mergeability); - - State init = init_map.at(q, State::Sx); - log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", log_id(cell), log_id(cell->type), log_signal(init)); - if (init == State::S1) - write_s_buffer(1); - else if (init == State::S0) - write_s_buffer(0); - else { - log_assert(init == State::Sx); - write_s_buffer(2); - } - - // Use arrival time from output of flop box - write_i_buffer(arrival_times.at(d, 0)); - //write_o_buffer(0); - } - + write_r_buffer(0); f << "r"; std::string buffer_str = r_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - f << "s"; - buffer_str = s_buffer.str(); - buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - - RTLIL::Design *holes_design; - auto it = saved_designs.find("$abc9_holes"); - if (it != saved_designs.end()) - holes_design = it->second; - else - holes_design = nullptr; - RTLIL::Module *holes_module = holes_design ? holes_design->module(module->name) : nullptr; if (holes_module) { + log_push(); + + // NB: fixup_ports() will sort ports by name + //holes_module->fixup_ports(); + holes_module->check(); + + holes_module->design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = holes_module->design->selection_stack.back(); + sel.select(holes_module); + + // TODO: Should not need to opt_merge if we only instantiate + // each box type once... + Pass::call(holes_module->design, "opt_merge -share_all"); + + Pass::call(holes_module->design, "flatten -wb"); + + // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, + // instead of per write_xaiger call + Pass::call(holes_module->design, "techmap"); + Pass::call(holes_module->design, "aigmap"); + for (auto cell : holes_module->cells()) + if (!cell->type.in("$_NOT_", "$_AND_")) + log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); + + holes_module->design->selection_stack.pop_back(); + + // Move into a new (temporary) design so that "clean" will only + // operate (and run checks on) this one module + RTLIL::Design *holes_design = new RTLIL::Design; + holes_module->design->modules_.erase(holes_module->name); + holes_design->add(holes_module); + Pass::call(holes_design, "clean -purge"); + std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /* dff_mode */); + XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); + delete holes_design; + f << "a"; std::string buffer_str = a_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + + log_pop(); } } @@ -683,32 +742,42 @@ struct XAigerWriter //f.write(buffer_str.data(), buffer_str.size()); f << stringf("Generated by %s\n", yosys_version_str); - - design->scratchpad_set_int("write_xaiger.num_ands", and_map.size()); - design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); - design->scratchpad_set_int("write_xaiger.num_inputs", input_bits.size()); - design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size()); } - void write_map(std::ostream &f) + void write_map(std::ostream &f, bool verbose_map) { dict input_lines; dict output_lines; + dict wire_lines; for (auto wire : module->wires()) { + //if (!verbose_map && wire->name[0] == '$') + // continue; + + SigSpec sig = sigmap(wire); + for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); if (input_bits.count(b)) { int a = aig_map.at(b); log_assert((a & 1) == 0); - input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire)); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, log_id(wire)); + output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), i, log_id(wire)); + continue; + } + + if (verbose_map) { + if (aig_map.count(sig[i]) == 0) + continue; + + int a = aig_map.at(sig[i]); + wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); } } } @@ -723,25 +792,28 @@ struct XAigerWriter f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); output_lines.sort(); + if (omode) + output_lines[State::S0] = "output 0 0 $__dummy__\n"; for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); + + wire_lines.sort(); + for (auto &it : wire_lines) + f << it.second; } }; struct XAigerBackend : public Backend { XAigerBackend() : Backend("xaiger", "write design to XAIGER file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" write_xaiger [options] [filename]\n"); log("\n"); - log("Write the top module (according to the (* top *) attribute or if only one module\n"); - log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, (optionally\n"); - log("$_DFF_N_, $_DFF_P_), or non (* abc9_box *) cells will be converted into psuedo-\n"); - log("inputs and pseudo-outputs. Whitebox contents will be taken from the equivalent\n"); - log("module in the '$abc9_holes' design, if it exists.\n"); + log("Write the current design to an XAIGER file. The design must be flattened and\n"); + log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n"); log("\n"); log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); @@ -749,13 +821,14 @@ struct XAigerBackend : public Backend { log(" -map \n"); log(" write an extra file with port and box symbols\n"); log("\n"); - log(" -dff\n"); - log(" write $_DFF_[NP]_ cells\n"); + log(" -vmap \n"); + log(" like -map, but more verbose\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { - bool ascii_mode = false, dff_mode = false; + bool ascii_mode = false; + bool verbose_map = false; std::string map_filename; log_header(design, "Executing XAIGER backend.\n"); @@ -771,8 +844,9 @@ struct XAigerBackend : public Backend { map_filename = args[++argidx]; continue; } - if (args[argidx] == "-dff") { - dff_mode = true; + if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) { + map_filename = args[++argidx]; + verbose_map = true; continue; } break; @@ -784,15 +858,7 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - if (!design->selected_whole_module(top_module)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module)); - - if (!top_module->processes.empty()) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", log_id(top_module)); - if (!top_module->memories.empty()) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module)); - - XAigerWriter writer(top_module, dff_mode); + XAigerWriter writer(top_module); writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { @@ -800,7 +866,7 @@ struct XAigerBackend : public Backend { mapf.open(map_filename.c_str(), std::ofstream::trunc); if (mapf.fail()) log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno)); - writer.write_map(mapf); + writer.write_map(mapf, verbose_map); } } } XAigerBackend; diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index 780a163202d..b6e38c16c03 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -69,9 +69,9 @@ struct BlifDumper f(f), module(module), design(design), config(config), ct(design), sigmap(module) { for (Wire *wire : module->wires()) - if (wire->attributes.count(ID::init)) { + if (wire->attributes.count("\\init")) { SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) switch (initval[i]) { case State::S0: @@ -138,9 +138,9 @@ struct BlifDumper { if (!config->gates_mode) return "subckt"; - if (design->module(RTLIL::escape_id(cell_type)) == nullptr) + if (!design->modules_.count(RTLIL::escape_id(cell_type))) return "gate"; - if (design->module(RTLIL::escape_id(cell_type))->get_blackbox_attribute()) + if (design->modules_.at(RTLIL::escape_id(cell_type))->get_blackbox_attribute()) return "gate"; return "subckt"; } @@ -148,7 +148,7 @@ struct BlifDumper void dump_params(const char *command, dict ¶ms) { for (auto ¶m : params) { - f << stringf("%s %s ", command, log_id(param.first)); + f << stringf("%s %s ", command, RTLIL::id2cstr(param.first)); if (param.second.flags & RTLIL::CONST_FLAG_STRING) { std::string str = param.second.decode_string(); f << stringf("\""); @@ -172,7 +172,8 @@ struct BlifDumper std::map inputs, outputs; - for (auto wire : module->wires()) { + for (auto &wire_it : module->wires_) { + RTLIL::Wire *wire = wire_it.second; if (wire->port_input) inputs[wire->port_id] = wire; if (wire->port_output) @@ -228,8 +229,10 @@ struct BlifDumper f << stringf(".names $undef\n"); } - for (auto cell : module->cells()) + for (auto &cell_it : module->cells_) { + RTLIL::Cell *cell = cell_it.second; + if (config->unbuf_types.count(cell->type)) { auto portnames = config->unbuf_types.at(cell->type); f << stringf(".names %s %s\n1 1\n", @@ -237,142 +240,142 @@ struct BlifDumper continue; } - if (!config->icells_mode && cell->type == ID($_NOT_)) { + if (!config->icells_mode && cell->type == "$_NOT_") { f << stringf(".names %s %s\n0 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_AND_)) { + if (!config->icells_mode && cell->type == "$_AND_") { f << stringf(".names %s %s %s\n11 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_OR_)) { + if (!config->icells_mode && cell->type == "$_OR_") { f << stringf(".names %s %s %s\n1- 1\n-1 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_XOR_)) { + if (!config->icells_mode && cell->type == "$_XOR_") { f << stringf(".names %s %s %s\n10 1\n01 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_NAND_)) { + if (!config->icells_mode && cell->type == "$_NAND_") { f << stringf(".names %s %s %s\n0- 1\n-0 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_NOR_)) { + if (!config->icells_mode && cell->type == "$_NOR_") { f << stringf(".names %s %s %s\n00 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_XNOR_)) { + if (!config->icells_mode && cell->type == "$_XNOR_") { f << stringf(".names %s %s %s\n11 1\n00 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_ANDNOT_)) { + if (!config->icells_mode && cell->type == "$_ANDNOT_") { f << stringf(".names %s %s %s\n10 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_ORNOT_)) { + if (!config->icells_mode && cell->type == "$_ORNOT_") { f << stringf(".names %s %s %s\n1- 1\n-0 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_AOI3_)) { + if (!config->icells_mode && cell->type == "$_AOI3_") { f << stringf(".names %s %s %s %s\n-00 1\n0-0 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::C)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\C")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_OAI3_)) { + if (!config->icells_mode && cell->type == "$_OAI3_") { f << stringf(".names %s %s %s %s\n00- 1\n--0 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::C)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\C")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_AOI4_)) { + if (!config->icells_mode && cell->type == "$_AOI4_") { f << stringf(".names %s %s %s %s %s\n-0-0 1\n-00- 1\n0--0 1\n0-0- 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), - cstr(cell->getPort(ID::C)), cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), + cstr(cell->getPort("\\C")), cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_OAI4_)) { + if (!config->icells_mode && cell->type == "$_OAI4_") { f << stringf(".names %s %s %s %s %s\n00-- 1\n--00 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), - cstr(cell->getPort(ID::C)), cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Y))); + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), + cstr(cell->getPort("\\C")), cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Y"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_MUX_)) { + if (!config->icells_mode && cell->type == "$_MUX_") { f << stringf(".names %s %s %s %s\n1-0 1\n-11 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), - cstr(cell->getPort(ID::S)), cstr(cell->getPort(ID::Y))); + 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 == ID($_NMUX_)) { + if (!config->icells_mode && cell->type == "$_NMUX_") { f << stringf(".names %s %s %s %s\n0-0 1\n-01 1\n", - cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), - cstr(cell->getPort(ID::S)), cstr(cell->getPort(ID::Y))); + 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 == ID($_FF_)) { - f << stringf(".latch %s %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)), - cstr_init(cell->getPort(ID::Q))); + if (!config->icells_mode && cell->type == "$_FF_") { + f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), + cstr_init(cell->getPort("\\Q"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_DFF_N_)) { - f << stringf(".latch %s %s fe %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)), - cstr(cell->getPort(ID::C)), cstr_init(cell->getPort(ID::Q))); + if (!config->icells_mode && cell->type == "$_DFF_N_") { + f << stringf(".latch %s %s fe %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), + cstr(cell->getPort("\\C")), cstr_init(cell->getPort("\\Q"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_DFF_P_)) { - f << stringf(".latch %s %s re %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)), - cstr(cell->getPort(ID::C)), cstr_init(cell->getPort(ID::Q))); + if (!config->icells_mode && cell->type == "$_DFF_P_") { + f << stringf(".latch %s %s re %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), + cstr(cell->getPort("\\C")), cstr_init(cell->getPort("\\Q"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_DLATCH_N_)) { - f << stringf(".latch %s %s al %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)), - cstr(cell->getPort(ID::E)), cstr_init(cell->getPort(ID::Q))); + if (!config->icells_mode && cell->type == "$_DLATCH_N_") { + f << stringf(".latch %s %s al %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), + cstr(cell->getPort("\\E")), cstr_init(cell->getPort("\\Q"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($_DLATCH_P_)) { - f << stringf(".latch %s %s ah %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)), - cstr(cell->getPort(ID::E)), cstr_init(cell->getPort(ID::Q))); + if (!config->icells_mode && cell->type == "$_DLATCH_P_") { + f << stringf(".latch %s %s ah %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), + cstr(cell->getPort("\\E")), cstr_init(cell->getPort("\\Q"))); goto internal_cell; } - if (!config->icells_mode && cell->type == ID($lut)) { + if (!config->icells_mode && cell->type == "$lut") { f << stringf(".names"); - auto &inputs = cell->getPort(ID::A); - auto width = cell->parameters.at(ID::WIDTH).as_int(); + auto &inputs = cell->getPort("\\A"); + auto width = cell->parameters.at("\\WIDTH").as_int(); log_assert(inputs.size() == width); for (int i = width-1; i >= 0; i--) f << stringf(" %s", cstr(inputs.extract(i, 1))); - auto &output = cell->getPort(ID::Y); + auto &output = cell->getPort("\\Y"); log_assert(output.size() == 1); f << stringf(" %s", cstr(output)); f << stringf("\n"); - RTLIL::SigSpec mask = cell->parameters.at(ID::LUT); + RTLIL::SigSpec mask = cell->parameters.at("\\LUT"); for (int i = 0; i < (1 << width); i++) if (mask[i] == State::S1) { for (int j = width-1; j >= 0; j--) { @@ -383,18 +386,18 @@ struct BlifDumper goto internal_cell; } - if (!config->icells_mode && cell->type == ID($sop)) { + if (!config->icells_mode && cell->type == "$sop") { f << stringf(".names"); - auto &inputs = cell->getPort(ID::A); - auto width = cell->parameters.at(ID::WIDTH).as_int(); - auto depth = cell->parameters.at(ID::DEPTH).as_int(); - vector table = cell->parameters.at(ID::TABLE).bits; + auto &inputs = cell->getPort("\\A"); + auto width = cell->parameters.at("\\WIDTH").as_int(); + auto depth = cell->parameters.at("\\DEPTH").as_int(); + vector table = cell->parameters.at("\\TABLE").bits; while (GetSize(table) < 2*width*depth) table.push_back(State::S0); log_assert(inputs.size() == width); for (int i = 0; i < width; i++) f << stringf(" %s", cstr(inputs.extract(i, 1))); - auto &output = cell->getPort(ID::Y); + auto &output = cell->getPort("\\Y"); log_assert(output.size() == 1); f << stringf(" %s", cstr(output)); f << stringf("\n"); @@ -482,7 +485,7 @@ struct BlifDumper struct BlifBackend : public Backend { BlifBackend() : Backend("blif", "write design to BLIF file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -552,7 +555,7 @@ struct BlifBackend : public Backend { log(" do not write definitions for the $true, $false and $undef wires.\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string top_module_name; std::string buf_type, buf_in, buf_out; @@ -646,24 +649,25 @@ struct BlifBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto module : design->modules()) - if (module->get_bool_attribute(ID::top)) - top_module_name = module->name.str(); + for (auto & mod_it:design->modules_) + if (mod_it.second->get_bool_attribute("\\top")) + top_module_name = mod_it.first.str(); *f << stringf("# Generated by %s\n", yosys_version_str); std::vector mod_list; design->sort(); - for (auto module : design->modules()) + for (auto module_it : design->modules_) { + RTLIL::Module *module = module_it.second; if (module->get_blackbox_attribute() && !config.blackbox_mode) continue; if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", log_id(module->name)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", RTLIL::id2cstr(module->name)); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", log_id(module->name)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", RTLIL::id2cstr(module->name)); if (module->name == RTLIL::escape_id(top_module_name)) { BlifDumper::dump(*f, module, design, config); diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index e5da6c1e7e1..c1da4b1272b 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -39,8 +39,6 @@ struct BtorWorker RTLIL::Module *module; bool verbose; bool single_bad; - bool cover_mode; - bool print_internal_names; int next_nid = 1; int initstate_nid = -1; @@ -73,13 +71,9 @@ struct BtorWorker vector bad_properties; dict initbits; pool statewires; - pool srcsymbols; + string indent; - string indent, info_filename; - vector info_lines; - dict info_clocks; - - void btorf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 2, 3)) + void btorf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -87,41 +81,6 @@ struct BtorWorker va_end(ap); } - void infof(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 2, 3)) - { - va_list ap; - va_start(ap, fmt); - info_lines.push_back(vstringf(fmt, ap)); - va_end(ap); - } - - template - string getinfo(T *obj, bool srcsym = false) - { - string infostr = log_id(obj); - if (!srcsym && !print_internal_names && infostr[0] == '$') return ""; - if (obj->attributes.count(ID::src)) { - string src = obj->attributes.at(ID::src).decode_string().c_str(); - if (srcsym && infostr[0] == '$') { - std::replace(src.begin(), src.end(), ' ', '_'); - if (srcsymbols.count(src) || module->count_id("\\" + src)) { - for (int i = 1;; i++) { - string s = stringf("%s-%d", src.c_str(), i); - if (!srcsymbols.count(s) && !module->count_id("\\" + s)) { - src = s; - break; - } - } - } - srcsymbols.insert(src); - infostr = src; - } else { - infostr += " ; " + src; - } - } - return " " + infostr; - } - void btorf_push(const string &id) { if (verbose) { @@ -185,40 +144,40 @@ struct BtorWorker cell_recursion_guard.insert(cell); btorf_push(log_id(cell)); - if (cell->type.in(ID($add), ID($sub), ID($mul), ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($sshl), ID($shr), ID($sshr), ID($shift), ID($shiftx), - ID($concat), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_))) + if (cell->type.in("$add", "$sub", "$mul", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx", + "$concat", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) { string btor_op; - if (cell->type == ID($add)) btor_op = "add"; - if (cell->type == ID($sub)) btor_op = "sub"; - if (cell->type == ID($mul)) btor_op = "mul"; - if (cell->type.in(ID($shl), ID($sshl))) btor_op = "sll"; - if (cell->type == ID($shr)) btor_op = "srl"; - if (cell->type == ID($sshr)) btor_op = "sra"; - if (cell->type.in(ID($shift), ID($shiftx))) btor_op = "shift"; - if (cell->type.in(ID($and), ID($_AND_))) btor_op = "and"; - if (cell->type.in(ID($or), ID($_OR_))) btor_op = "or"; - if (cell->type.in(ID($xor), ID($_XOR_))) btor_op = "xor"; - if (cell->type == ID($concat)) btor_op = "concat"; - if (cell->type == ID($_NAND_)) btor_op = "nand"; - if (cell->type == ID($_NOR_)) btor_op = "nor"; - if (cell->type.in(ID($xnor), ID($_XNOR_))) btor_op = "xnor"; + if (cell->type == "$add") btor_op = "add"; + if (cell->type == "$sub") btor_op = "sub"; + if (cell->type == "$mul") btor_op = "mul"; + if (cell->type.in("$shl", "$sshl")) btor_op = "sll"; + if (cell->type == "$shr") btor_op = "srl"; + if (cell->type == "$sshr") btor_op = "sra"; + if (cell->type.in("$shift", "$shiftx")) btor_op = "shift"; + if (cell->type.in("$and", "$_AND_")) btor_op = "and"; + if (cell->type.in("$or", "$_OR_")) btor_op = "or"; + if (cell->type.in("$xor", "$_XOR_")) btor_op = "xor"; + if (cell->type == "$concat") btor_op = "concat"; + if (cell->type == "$_NAND_") btor_op = "nand"; + if (cell->type == "$_NOR_") btor_op = "nor"; + if (cell->type.in("$xnor", "$_XNOR_")) btor_op = "xnor"; log_assert(!btor_op.empty()); - int width = GetSize(cell->getPort(ID::Y)); - width = std::max(width, GetSize(cell->getPort(ID::A))); - width = std::max(width, GetSize(cell->getPort(ID::B))); + int width = GetSize(cell->getPort("\\Y")); + width = std::max(width, GetSize(cell->getPort("\\A"))); + width = std::max(width, GetSize(cell->getPort("\\B"))); - bool a_signed = cell->hasParam(ID::A_SIGNED) ? cell->getParam(ID::A_SIGNED).as_bool() : false; - bool b_signed = cell->hasParam(ID::B_SIGNED) ? cell->getParam(ID::B_SIGNED).as_bool() : false; + bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; + bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false; if (btor_op == "shift" && !b_signed) btor_op = "srl"; - if (cell->type.in(ID($shl), ID($sshl), ID($shr), ID($sshr))) + if (cell->type.in("$shl", "$sshl", "$shr", "$sshr")) b_signed = false; - if (cell->type == ID($sshr) && !a_signed) + if (cell->type == "$sshr" && !a_signed) btor_op = "srl"; int sid = get_bv_sid(width); @@ -226,8 +185,8 @@ struct BtorWorker if (btor_op == "shift") { - int nid_a = get_sig_nid(cell->getPort(ID::A), width, false); - int nid_b = get_sig_nid(cell->getPort(ID::B), width, b_signed); + int nid_a = get_sig_nid(cell->getPort("\\A"), width, false); + int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); int nid_r = next_nid++; btorf("%d srl %d %d %d\n", nid_r, sid, nid_a, nid_b); @@ -244,18 +203,18 @@ struct BtorWorker btorf("%d slt %d %d %d\n", nid_b_ltz, sid_bit, nid_b, nid_zero); nid = next_nid++; - btorf("%d ite %d %d %d %d%s\n", nid, sid, nid_b_ltz, nid_l, nid_r, getinfo(cell).c_str()); + btorf("%d ite %d %d %d %d\n", nid, sid, nid_b_ltz, nid_l, nid_r); } else { - int nid_a = get_sig_nid(cell->getPort(ID::A), width, a_signed); - int nid_b = get_sig_nid(cell->getPort(ID::B), width, b_signed); + int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); + int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); nid = next_nid++; - btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); } - SigSpec sig = sigmap(cell->getPort(ID::Y)); + SigSpec sig = sigmap(cell->getPort("\\Y")); if (GetSize(sig) < width) { int sid = get_bv_sid(GetSize(sig)); @@ -268,34 +227,28 @@ struct BtorWorker goto okay; } - if (cell->type.in(ID($div), ID($mod), ID($modfloor))) + if (cell->type.in("$div", "$mod")) { - bool a_signed = cell->hasParam(ID::A_SIGNED) ? cell->getParam(ID::A_SIGNED).as_bool() : false; - bool b_signed = cell->hasParam(ID::B_SIGNED) ? cell->getParam(ID::B_SIGNED).as_bool() : false; - string btor_op; - if (cell->type == ID($div)) btor_op = "div"; - // "rem" = truncating modulo - if (cell->type == ID($mod)) btor_op = "rem"; - // "mod" = flooring modulo - if (cell->type == ID($modfloor)) { - // "umod" doesn't exist because it's the same as "urem" - btor_op = a_signed || b_signed ? "mod" : "rem"; - } + if (cell->type == "$div") btor_op = "div"; + if (cell->type == "$mod") btor_op = "rem"; log_assert(!btor_op.empty()); - int width = GetSize(cell->getPort(ID::Y)); - width = std::max(width, GetSize(cell->getPort(ID::A))); - width = std::max(width, GetSize(cell->getPort(ID::B))); + int width = GetSize(cell->getPort("\\Y")); + width = std::max(width, GetSize(cell->getPort("\\A"))); + width = std::max(width, GetSize(cell->getPort("\\B"))); - int nid_a = get_sig_nid(cell->getPort(ID::A), width, a_signed); - int nid_b = get_sig_nid(cell->getPort(ID::B), width, b_signed); + bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; + bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false; + + int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); + int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); int sid = get_bv_sid(width); int nid = next_nid++; - btorf("%d %c%s %d %d %d%s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + btorf("%d %c%s %d %d %d\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b); - SigSpec sig = sigmap(cell->getPort(ID::Y)); + SigSpec sig = sigmap(cell->getPort("\\Y")); if (GetSize(sig) < width) { int sid = get_bv_sid(GetSize(sig)); @@ -308,120 +261,120 @@ struct BtorWorker goto okay; } - if (cell->type.in(ID($_ANDNOT_), ID($_ORNOT_))) + if (cell->type.in("$_ANDNOT_", "$_ORNOT_")) { int sid = get_bv_sid(1); - int nid_a = get_sig_nid(cell->getPort(ID::A)); - int nid_b = get_sig_nid(cell->getPort(ID::B)); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_b = get_sig_nid(cell->getPort("\\B")); int nid1 = next_nid++; int nid2 = next_nid++; - if (cell->type == ID($_ANDNOT_)) { + if (cell->type == "$_ANDNOT_") { btorf("%d not %d %d\n", nid1, sid, nid_b); - btorf("%d and %d %d %d%s\n", nid2, sid, nid_a, nid1, getinfo(cell).c_str()); + btorf("%d and %d %d %d\n", nid2, sid, nid_a, nid1); } - if (cell->type == ID($_ORNOT_)) { + if (cell->type == "$_ORNOT_") { btorf("%d not %d %d\n", nid1, sid, nid_b); - btorf("%d or %d %d %d%s\n", nid2, sid, nid_a, nid1, getinfo(cell).c_str()); + btorf("%d or %d %d %d\n", nid2, sid, nid_a, nid1); } - SigSpec sig = sigmap(cell->getPort(ID::Y)); + SigSpec sig = sigmap(cell->getPort("\\Y")); add_nid_sig(nid2, sig); goto okay; } - if (cell->type.in(ID($_OAI3_), ID($_AOI3_))) + if (cell->type.in("$_OAI3_", "$_AOI3_")) { int sid = get_bv_sid(1); - int nid_a = get_sig_nid(cell->getPort(ID::A)); - int nid_b = get_sig_nid(cell->getPort(ID::B)); - int nid_c = get_sig_nid(cell->getPort(ID::C)); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_b = get_sig_nid(cell->getPort("\\B")); + int nid_c = get_sig_nid(cell->getPort("\\C")); int nid1 = next_nid++; int nid2 = next_nid++; int nid3 = next_nid++; - if (cell->type == ID($_OAI3_)) { + if (cell->type == "$_OAI3_") { btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b); btorf("%d and %d %d %d\n", nid2, sid, nid1, nid_c); - btorf("%d not %d %d%s\n", nid3, sid, nid2, getinfo(cell).c_str()); + btorf("%d not %d %d\n", nid3, sid, nid2); } - if (cell->type == ID($_AOI3_)) { + if (cell->type == "$_AOI3_") { btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b); btorf("%d or %d %d %d\n", nid2, sid, nid1, nid_c); - btorf("%d not %d %d%s\n", nid3, sid, nid2, getinfo(cell).c_str()); + btorf("%d not %d %d\n", nid3, sid, nid2); } - SigSpec sig = sigmap(cell->getPort(ID::Y)); + SigSpec sig = sigmap(cell->getPort("\\Y")); add_nid_sig(nid3, sig); goto okay; } - if (cell->type.in(ID($_OAI4_), ID($_AOI4_))) + if (cell->type.in("$_OAI4_", "$_AOI4_")) { int sid = get_bv_sid(1); - int nid_a = get_sig_nid(cell->getPort(ID::A)); - int nid_b = get_sig_nid(cell->getPort(ID::B)); - int nid_c = get_sig_nid(cell->getPort(ID::C)); - int nid_d = get_sig_nid(cell->getPort(ID::D)); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_b = get_sig_nid(cell->getPort("\\B")); + int nid_c = get_sig_nid(cell->getPort("\\C")); + int nid_d = get_sig_nid(cell->getPort("\\D")); int nid1 = next_nid++; int nid2 = next_nid++; int nid3 = next_nid++; int nid4 = next_nid++; - if (cell->type == ID($_OAI4_)) { + if (cell->type == "$_OAI4_") { btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b); btorf("%d or %d %d %d\n", nid2, sid, nid_c, nid_d); btorf("%d and %d %d %d\n", nid3, sid, nid1, nid2); - btorf("%d not %d %d%s\n", nid4, sid, nid3, getinfo(cell).c_str()); + btorf("%d not %d %d\n", nid4, sid, nid3); } - if (cell->type == ID($_AOI4_)) { + if (cell->type == "$_AOI4_") { btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b); btorf("%d and %d %d %d\n", nid2, sid, nid_c, nid_d); btorf("%d or %d %d %d\n", nid3, sid, nid1, nid2); - btorf("%d not %d %d%s\n", nid4, sid, nid3, getinfo(cell).c_str()); + btorf("%d not %d %d\n", nid4, sid, nid3); } - SigSpec sig = sigmap(cell->getPort(ID::Y)); + SigSpec sig = sigmap(cell->getPort("\\Y")); add_nid_sig(nid4, sig); goto okay; } - if (cell->type.in(ID($lt), ID($le), ID($eq), ID($eqx), ID($ne), ID($nex), ID($ge), ID($gt))) + if (cell->type.in("$lt", "$le", "$eq", "$eqx", "$ne", "$nex", "$ge", "$gt")) { string btor_op; - if (cell->type == ID($lt)) btor_op = "lt"; - if (cell->type == ID($le)) btor_op = "lte"; - if (cell->type.in(ID($eq), ID($eqx))) btor_op = "eq"; - if (cell->type.in(ID($ne), ID($nex))) btor_op = "neq"; - if (cell->type == ID($ge)) btor_op = "gte"; - if (cell->type == ID($gt)) btor_op = "gt"; + if (cell->type == "$lt") btor_op = "lt"; + if (cell->type == "$le") btor_op = "lte"; + if (cell->type.in("$eq", "$eqx")) btor_op = "eq"; + if (cell->type.in("$ne", "$nex")) btor_op = "neq"; + if (cell->type == "$ge") btor_op = "gte"; + if (cell->type == "$gt") btor_op = "gt"; log_assert(!btor_op.empty()); int width = 1; - width = std::max(width, GetSize(cell->getPort(ID::A))); - width = std::max(width, GetSize(cell->getPort(ID::B))); + width = std::max(width, GetSize(cell->getPort("\\A"))); + width = std::max(width, GetSize(cell->getPort("\\B"))); - bool a_signed = cell->hasParam(ID::A_SIGNED) ? cell->getParam(ID::A_SIGNED).as_bool() : false; - bool b_signed = cell->hasParam(ID::B_SIGNED) ? cell->getParam(ID::B_SIGNED).as_bool() : false; + bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; + bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false; int sid = get_bv_sid(1); - int nid_a = get_sig_nid(cell->getPort(ID::A), width, a_signed); - int nid_b = get_sig_nid(cell->getPort(ID::B), width, b_signed); + int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); + int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); int nid = next_nid++; - if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt))) { - btorf("%d %c%s %d %d %d%s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + if (cell->type.in("$lt", "$le", "$ge", "$gt")) { + btorf("%d %c%s %d %d %d\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b); } else { - btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); } - SigSpec sig = sigmap(cell->getPort(ID::Y)); + SigSpec sig = sigmap(cell->getPort("\\Y")); if (GetSize(sig) > 1) { int sid = get_bv_sid(GetSize(sig)); @@ -434,24 +387,25 @@ struct BtorWorker goto okay; } - if (cell->type.in(ID($not), ID($neg), ID($_NOT_))) + if (cell->type.in("$not", "$neg", "$_NOT_")) { string btor_op; - if (cell->type.in(ID($not), ID($_NOT_))) btor_op = "not"; - if (cell->type == ID($neg)) btor_op = "neg"; + if (cell->type.in("$not", "$_NOT_")) btor_op = "not"; + if (cell->type == "$neg") btor_op = "neg"; log_assert(!btor_op.empty()); - int width = std::max(GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::Y))); + int width = GetSize(cell->getPort("\\Y")); + width = std::max(width, GetSize(cell->getPort("\\A"))); - bool a_signed = cell->hasParam(ID::A_SIGNED) ? cell->getParam(ID::A_SIGNED).as_bool() : false; + bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; int sid = get_bv_sid(width); - int nid_a = get_sig_nid(cell->getPort(ID::A), width, a_signed); + int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); int nid = next_nid++; - btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); + btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a); - SigSpec sig = sigmap(cell->getPort(ID::Y)); + SigSpec sig = sigmap(cell->getPort("\\Y")); if (GetSize(sig) < width) { int sid = get_bv_sid(GetSize(sig)); @@ -464,25 +418,25 @@ struct BtorWorker goto okay; } - if (cell->type.in(ID($logic_and), ID($logic_or), ID($logic_not))) + if (cell->type.in("$logic_and", "$logic_or", "$logic_not")) { string btor_op; - if (cell->type == ID($logic_and)) btor_op = "and"; - if (cell->type == ID($logic_or)) btor_op = "or"; - if (cell->type == ID($logic_not)) btor_op = "not"; + if (cell->type == "$logic_and") btor_op = "and"; + if (cell->type == "$logic_or") btor_op = "or"; + if (cell->type == "$logic_not") btor_op = "not"; log_assert(!btor_op.empty()); int sid = get_bv_sid(1); - int nid_a = get_sig_nid(cell->getPort(ID::A)); - int nid_b = btor_op != "not" ? get_sig_nid(cell->getPort(ID::B)) : 0; + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_b = btor_op != "not" ? get_sig_nid(cell->getPort("\\B")) : 0; - if (GetSize(cell->getPort(ID::A)) > 1) { + if (GetSize(cell->getPort("\\A")) > 1) { int nid_red_a = next_nid++; btorf("%d redor %d %d\n", nid_red_a, sid, nid_a); nid_a = nid_red_a; } - if (btor_op != "not" && GetSize(cell->getPort(ID::B)) > 1) { + if (btor_op != "not" && GetSize(cell->getPort("\\B")) > 1) { int nid_red_b = next_nid++; btorf("%d redor %d %d\n", nid_red_b, sid, nid_b); nid_b = nid_red_b; @@ -490,11 +444,11 @@ struct BtorWorker int nid = next_nid++; if (btor_op != "not") - btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b); else - btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); + btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a); - SigSpec sig = sigmap(cell->getPort(ID::Y)); + SigSpec sig = sigmap(cell->getPort("\\Y")); if (GetSize(sig) > 1) { int sid = get_bv_sid(GetSize(sig)); @@ -508,29 +462,27 @@ struct BtorWorker goto okay; } - if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor))) + if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool", "$reduce_xor", "$reduce_xnor")) { string btor_op; - if (cell->type == ID($reduce_and)) btor_op = "redand"; - if (cell->type.in(ID($reduce_or), ID($reduce_bool))) btor_op = "redor"; - if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) btor_op = "redxor"; + if (cell->type == "$reduce_and") btor_op = "redand"; + if (cell->type.in("$reduce_or", "$reduce_bool")) btor_op = "redor"; + if (cell->type.in("$reduce_xor", "$reduce_xnor")) btor_op = "redxor"; log_assert(!btor_op.empty()); int sid = get_bv_sid(1); - int nid_a = get_sig_nid(cell->getPort(ID::A)); + int nid_a = get_sig_nid(cell->getPort("\\A")); int nid = next_nid++; + btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a); - if (cell->type == ID($reduce_xnor)) { + if (cell->type == "$reduce_xnor") { int nid2 = next_nid++; - btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); - btorf("%d not %d %d\n", nid2, sid, nid); + btorf("%d not %d %d %d\n", nid2, sid, nid); nid = nid2; - } else { - btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); } - SigSpec sig = sigmap(cell->getPort(ID::Y)); + SigSpec sig = sigmap(cell->getPort("\\Y")); if (GetSize(sig) > 1) { int sid = get_bv_sid(GetSize(sig)); @@ -544,12 +496,12 @@ struct BtorWorker goto okay; } - if (cell->type.in(ID($mux), ID($_MUX_), ID($_NMUX_))) + if (cell->type.in("$mux", "$_MUX_", "$_NMUX_")) { - SigSpec sig_a = sigmap(cell->getPort(ID::A)); - SigSpec sig_b = sigmap(cell->getPort(ID::B)); - SigSpec sig_s = sigmap(cell->getPort(ID::S)); - SigSpec sig_y = sigmap(cell->getPort(ID::Y)); + SigSpec sig_a = sigmap(cell->getPort("\\A")); + SigSpec sig_b = sigmap(cell->getPort("\\B")); + SigSpec sig_s = sigmap(cell->getPort("\\S")); + SigSpec sig_y = sigmap(cell->getPort("\\Y")); int nid_a = get_sig_nid(sig_a); int nid_b = get_sig_nid(sig_b); @@ -557,26 +509,24 @@ struct BtorWorker int sid = get_bv_sid(GetSize(sig_y)); int nid = next_nid++; + btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a); - if (cell->type == ID($_NMUX_)) { + if (cell->type == "$_NMUX_") { int tmp = nid; nid = next_nid++; - btorf("%d ite %d %d %d %d\n", tmp, sid, nid_s, nid_b, nid_a); - btorf("%d not %d %d%s\n", nid, sid, tmp, getinfo(cell).c_str()); - } else { - btorf("%d ite %d %d %d %d%s\n", nid, sid, nid_s, nid_b, nid_a, getinfo(cell).c_str()); + btorf("%d not %d %d\n", nid, sid, tmp); } add_nid_sig(nid, sig_y); goto okay; } - if (cell->type == ID($pmux)) + if (cell->type == "$pmux") { - SigSpec sig_a = sigmap(cell->getPort(ID::A)); - SigSpec sig_b = sigmap(cell->getPort(ID::B)); - SigSpec sig_s = sigmap(cell->getPort(ID::S)); - SigSpec sig_y = sigmap(cell->getPort(ID::Y)); + SigSpec sig_a = sigmap(cell->getPort("\\A")); + SigSpec sig_b = sigmap(cell->getPort("\\B")); + SigSpec sig_s = sigmap(cell->getPort("\\S")); + SigSpec sig_y = sigmap(cell->getPort("\\Y")); int width = GetSize(sig_a); int sid = get_bv_sid(width); @@ -586,10 +536,7 @@ struct BtorWorker int nid_b = get_sig_nid(sig_b.extract(i*width, width)); int nid_s = get_sig_nid(sig_s.extract(i)); int nid2 = next_nid++; - if (i == GetSize(sig_s)-1) - btorf("%d ite %d %d %d %d%s\n", nid2, sid, nid_s, nid_b, nid, getinfo(cell).c_str()); - else - btorf("%d ite %d %d %d %d\n", nid2, sid, nid_s, nid_b, nid); + btorf("%d ite %d %d %d %d\n", nid2, sid, nid_s, nid_b, nid); nid = nid2; } @@ -597,25 +544,10 @@ struct BtorWorker goto okay; } - if (cell->type.in(ID($dff), ID($ff), ID($_DFF_P_), ID($_DFF_N), ID($_FF_))) + if (cell->type.in("$dff", "$ff", "$_DFF_P_", "$_DFF_N", "$_FF_")) { - SigSpec sig_d = sigmap(cell->getPort(ID::D)); - SigSpec sig_q = sigmap(cell->getPort(ID::Q)); - - if (!info_filename.empty() && cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_))) - { - SigSpec sig_c = sigmap(cell->getPort(cell->type == ID($dff) ? ID::CLK : ID::C)); - int nid = get_sig_nid(sig_c); - bool negedge = false; - - if (cell->type == ID($_DFF_N_)) - negedge = true; - - if (cell->type == ID($dff) && !cell->getParam(ID::CLK_POLARITY).as_bool()) - negedge = true; - - info_clocks[nid] |= negedge ? 2 : 1; - } + SigSpec sig_d = sigmap(cell->getPort("\\D")); + SigSpec sig_q = sigmap(cell->getPort("\\Q")); IdString symbol; @@ -642,7 +574,7 @@ struct BtorWorker int sid = get_bv_sid(GetSize(sig_q)); int nid = next_nid++; - if (symbol.empty() || (!print_internal_names && symbol[0] == '$')) + if (symbol.empty()) btorf("%d state %d\n", nid, sid); else btorf("%d state %d %s\n", nid, sid, log_id(symbol)); @@ -659,16 +591,16 @@ struct BtorWorker goto okay; } - if (cell->type.in(ID($anyconst), ID($anyseq))) + if (cell->type.in("$anyconst", "$anyseq")) { - SigSpec sig_y = sigmap(cell->getPort(ID::Y)); + SigSpec sig_y = sigmap(cell->getPort("\\Y")); int sid = get_bv_sid(GetSize(sig_y)); int nid = next_nid++; btorf("%d state %d\n", nid, sid); - if (cell->type == ID($anyconst)) { + if (cell->type == "$anyconst") { int nid2 = next_nid++; btorf("%d next %d %d %d\n", nid2, sid, nid, nid); } @@ -677,9 +609,9 @@ struct BtorWorker goto okay; } - if (cell->type == ID($initstate)) + if (cell->type == "$initstate") { - SigSpec sig_y = sigmap(cell->getPort(ID::Y)); + SigSpec sig_y = sigmap(cell->getPort("\\Y")); if (initstate_nid < 0) { @@ -696,16 +628,16 @@ struct BtorWorker goto okay; } - if (cell->type == ID($mem)) + if (cell->type == "$mem") { - int abits = cell->getParam(ID::ABITS).as_int(); - int width = cell->getParam(ID::WIDTH).as_int(); - int nwords = cell->getParam(ID::SIZE).as_int(); - int rdports = cell->getParam(ID::RD_PORTS).as_int(); - int wrports = cell->getParam(ID::WR_PORTS).as_int(); + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); + int nwords = cell->getParam("\\SIZE").as_int(); + int rdports = cell->getParam("\\RD_PORTS").as_int(); + int wrports = cell->getParam("\\WR_PORTS").as_int(); - Const wr_clk_en = cell->getParam(ID::WR_CLK_ENABLE); - Const rd_clk_en = cell->getParam(ID::RD_CLK_ENABLE); + Const wr_clk_en = cell->getParam("\\WR_CLK_ENABLE"); + Const rd_clk_en = cell->getParam("\\RD_CLK_ENABLE"); bool asyncwr = wr_clk_en.is_fully_zero(); @@ -717,18 +649,18 @@ struct BtorWorker log_error("Memory %s.%s has sync read ports.\n", log_id(module), log_id(cell)); - SigSpec sig_rd_addr = sigmap(cell->getPort(ID::RD_ADDR)); - SigSpec sig_rd_data = sigmap(cell->getPort(ID::RD_DATA)); + SigSpec sig_rd_addr = sigmap(cell->getPort("\\RD_ADDR")); + SigSpec sig_rd_data = sigmap(cell->getPort("\\RD_DATA")); - SigSpec sig_wr_addr = sigmap(cell->getPort(ID::WR_ADDR)); - SigSpec sig_wr_data = sigmap(cell->getPort(ID::WR_DATA)); - SigSpec sig_wr_en = sigmap(cell->getPort(ID::WR_EN)); + SigSpec sig_wr_addr = sigmap(cell->getPort("\\WR_ADDR")); + SigSpec sig_wr_data = sigmap(cell->getPort("\\WR_DATA")); + SigSpec sig_wr_en = sigmap(cell->getPort("\\WR_EN")); int data_sid = get_bv_sid(width); int bool_sid = get_bv_sid(1); int sid = get_mem_sid(abits, width); - Const initdata = cell->getParam(ID::INIT); + Const initdata = cell->getParam("\\INIT"); initdata.exts(nwords*width); int nid_init_val = -1; @@ -1051,18 +983,15 @@ struct BtorWorker return nid; } - BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose, bool single_bad, bool cover_mode, bool print_internal_names, string info_filename) : - f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad), cover_mode(cover_mode), print_internal_names(print_internal_names), info_filename(info_filename) + BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose, bool single_bad) : + f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad) { - if (!info_filename.empty()) - infof("name %s\n", log_id(module)); - btorf_push("inputs"); for (auto wire : module->wires()) { - if (wire->attributes.count(ID::init)) { - Const attrval = wire->attributes.at(ID::init); + if (wire->attributes.count("\\init")) { + Const attrval = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(wire) && i < GetSize(attrval); i++) if (attrval[i] == State::S0 || attrval[i] == State::S1) initbits[sigmap(SigBit(wire, i))] = (attrval[i] == State::S1); @@ -1075,7 +1004,7 @@ struct BtorWorker int sid = get_bv_sid(GetSize(sig)); int nid = next_nid++; - btorf("%d input %d%s\n", nid, sid, getinfo(wire).c_str()); + btorf("%d input %d %s\n", nid, sid, log_id(wire)); add_nid_sig(nid, sig); } @@ -1099,20 +1028,20 @@ struct BtorWorker btorf_push(stringf("output %s", log_id(wire))); int nid = get_sig_nid(wire); - btorf("%d output %d%s\n", next_nid++, nid, getinfo(wire).c_str()); + btorf("%d output %d %s\n", next_nid++, nid, log_id(wire)); btorf_pop(stringf("output %s", log_id(wire))); } for (auto cell : module->cells()) { - if (cell->type == ID($assume)) + if (cell->type == "$assume") { btorf_push(log_id(cell)); int sid = get_bv_sid(1); - int nid_a = get_sig_nid(cell->getPort(ID::A)); - int nid_en = get_sig_nid(cell->getPort(ID::EN)); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_en = get_sig_nid(cell->getPort("\\EN")); int nid_not_en = next_nid++; int nid_a_or_not_en = next_nid++; int nid = next_nid++; @@ -1124,49 +1053,29 @@ struct BtorWorker btorf_pop(log_id(cell)); } - if (cell->type == ID($assert)) + if (cell->type == "$assert") { btorf_push(log_id(cell)); int sid = get_bv_sid(1); - int nid_a = get_sig_nid(cell->getPort(ID::A)); - int nid_en = get_sig_nid(cell->getPort(ID::EN)); + int nid_a = get_sig_nid(cell->getPort("\\A")); + int nid_en = get_sig_nid(cell->getPort("\\EN")); int nid_not_a = next_nid++; int nid_en_and_not_a = next_nid++; btorf("%d not %d %d\n", nid_not_a, sid, nid_a); btorf("%d and %d %d %d\n", nid_en_and_not_a, sid, nid_en, nid_not_a); - if (single_bad && !cover_mode) { - bad_properties.push_back(nid_en_and_not_a); - } else { - if (cover_mode) { - infof("bad %d%s\n", nid_en_and_not_a, getinfo(cell, true).c_str()); - } else { - int nid = next_nid++; - btorf("%d bad %d%s\n", nid, nid_en_and_not_a, getinfo(cell, true).c_str()); - } - } - - btorf_pop(log_id(cell)); - } - - if (cell->type == ID($cover) && cover_mode) - { - btorf_push(log_id(cell)); - - int sid = get_bv_sid(1); - int nid_a = get_sig_nid(cell->getPort(ID::A)); - int nid_en = get_sig_nid(cell->getPort(ID::EN)); - int nid_en_and_a = next_nid++; - - btorf("%d and %d %d %d\n", nid_en_and_a, sid, nid_en, nid_a); - if (single_bad) { - bad_properties.push_back(nid_en_and_a); + bad_properties.push_back(nid_en_and_not_a); } else { int nid = next_nid++; - btorf("%d bad %d%s\n", nid, nid_en_and_a, getinfo(cell, true).c_str()); + string infostr = log_id(cell); + if (infostr[0] == '$' && cell->attributes.count("\\src")) { + infostr = cell->attributes.at("\\src").decode_string().c_str(); + std::replace(infostr.begin(), infostr.end(), ' ', '_'); + } + btorf("%d bad %d %s\n", nid, nid_en_and_not_a, infostr.c_str()); } btorf_pop(log_id(cell)); @@ -1187,7 +1096,7 @@ struct BtorWorker continue; int this_nid = next_nid++; - btorf("%d uext %d %d %d%s\n", this_nid, sid, nid, 0, getinfo(wire).c_str()); + btorf("%d uext %d %d %d %s\n", this_nid, sid, nid, 0, log_id(wire)); btorf_pop(stringf("wire %s", log_id(wire))); continue; @@ -1205,15 +1114,15 @@ struct BtorWorker btorf_push(stringf("next %s", log_id(cell))); - if (cell->type == ID($mem)) + if (cell->type == "$mem") { - int abits = cell->getParam(ID::ABITS).as_int(); - int width = cell->getParam(ID::WIDTH).as_int(); - int wrports = cell->getParam(ID::WR_PORTS).as_int(); + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); + int wrports = cell->getParam("\\WR_PORTS").as_int(); - SigSpec sig_wr_addr = sigmap(cell->getPort(ID::WR_ADDR)); - SigSpec sig_wr_data = sigmap(cell->getPort(ID::WR_DATA)); - SigSpec sig_wr_en = sigmap(cell->getPort(ID::WR_EN)); + SigSpec sig_wr_addr = sigmap(cell->getPort("\\WR_ADDR")); + SigSpec sig_wr_data = sigmap(cell->getPort("\\WR_DATA")); + SigSpec sig_wr_en = sigmap(cell->getPort("\\WR_EN")); int data_sid = get_bv_sid(width); int bool_sid = get_bv_sid(1); @@ -1258,14 +1167,14 @@ struct BtorWorker } int nid2 = next_nid++; - btorf("%d next %d %d %d%s\n", nid2, sid, nid, nid_head, getinfo(cell).c_str()); + btorf("%d next %d %d %d\n", nid2, sid, nid, nid_head); } else { - SigSpec sig = sigmap(cell->getPort(ID::D)); + SigSpec sig = sigmap(cell->getPort("\\D")); int nid_q = get_sig_nid(sig); int sid = get_bv_sid(GetSize(sig)); - btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell).c_str()); + btorf("%d next %d %d %d\n", next_nid++, sid, nid, nid_q); } btorf_pop(stringf("next %s", log_id(cell))); @@ -1301,41 +1210,12 @@ struct BtorWorker btorf("%d bad %d\n", nid, todo[cursor]); } } - - if (!info_filename.empty()) - { - for (auto &it : info_clocks) - { - switch (it.second) - { - case 1: - infof("posedge %d\n", it.first); - break; - case 2: - infof("negedge %d\n", it.first); - break; - case 3: - infof("event %d\n", it.first); - break; - default: - log_abort(); - } - } - - std::ofstream f; - f.open(info_filename.c_str(), std::ofstream::trunc); - if (f.fail()) - log_error("Can't open file `%s' for writing: %s\n", info_filename.c_str(), strerror(errno)); - for (auto &it : info_lines) - f << it; - f.close(); - } } }; struct BtorBackend : public Backend { BtorBackend() : Backend("btor", "write design to BTOR file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1349,20 +1229,10 @@ struct BtorBackend : public Backend { log(" -s\n"); log(" Output only a single bad property for all asserts\n"); log("\n"); - log(" -c\n"); - log(" Output cover properties using 'bad' statements instead of asserts\n"); - log("\n"); - log(" -i \n"); - log(" Create additional info file with auxiliary information\n"); - log("\n"); - log(" -x\n"); - log(" Output symbols for internal netnames (starting with '$')\n"); - log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { - bool verbose = false, single_bad = false, cover_mode = false, print_internal_names = false; - string info_filename; + bool verbose = false, single_bad = false; log_header(design, "Executing BTOR backend.\n"); @@ -1377,18 +1247,6 @@ struct BtorBackend : public Backend { single_bad = true; continue; } - if (args[argidx] == "-c") { - cover_mode = true; - continue; - } - if (args[argidx] == "-i" && argidx+1 < args.size()) { - info_filename = args[++argidx]; - continue; - } - if (args[argidx] == "-x") { - print_internal_names = true; - continue; - } break; } extra_args(f, filename, args, argidx); @@ -1401,7 +1259,7 @@ struct BtorBackend : public Backend { *f << stringf("; BTOR description generated by %s for module %s.\n", yosys_version_str, log_id(topmod)); - BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename); + BtorWorker(*f, topmod, verbose, single_bad); *f << stringf("; end of yosys output\n"); } diff --git a/backends/btor/test_cells.sh b/backends/btor/test_cells.sh index 3f077201a0e..e0f1a051400 100644 --- a/backends/btor/test_cells.sh +++ b/backends/btor/test_cells.sh @@ -6,7 +6,7 @@ rm -rf test_cells.tmp mkdir -p test_cells.tmp cd test_cells.tmp -../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod /$divfloor /$modfloor' +../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod' for fn in test_*.il; do ../../../yosys -p " diff --git a/backends/cxxrtl/Makefile.inc b/backends/cxxrtl/Makefile.inc deleted file mode 100644 index aaa304502e0..00000000000 --- a/backends/cxxrtl/Makefile.inc +++ /dev/null @@ -1,2 +0,0 @@ - -OBJS += backends/cxxrtl/cxxrtl_backend.o diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h deleted file mode 100644 index f0d7b9fc7a0..00000000000 --- a/backends/cxxrtl/cxxrtl.h +++ /dev/null @@ -1,1456 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2019-2020 whitequark - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted. - * - * 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. - * - */ - -// This file is included by the designs generated with `write_cxxrtl`. It is not used in Yosys itself. -// -// The CXXRTL support library implements compile time specialized arbitrary width arithmetics, as well as provides -// composite lvalues made out of bit slices and concatenations of lvalues. This allows the `write_cxxrtl` pass -// to perform a straightforward translation of RTLIL structures to readable C++, relying on the C++ compiler -// to unwrap the abstraction and generate efficient code. - -#ifndef CXXRTL_H -#define CXXRTL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -// CXXRTL essentially uses the C++ compiler as a hygienic macro engine that feeds an instruction selector. -// It generates a lot of specialized template functions with relatively large bodies that, when inlined -// into the caller and (for those with loops) unrolled, often expose many new optimization opportunities. -// Because of this, most of the CXXRTL runtime must be always inlined for best performance. -#ifndef __has_attribute -# define __has_attribute(x) 0 -#endif -#if __has_attribute(always_inline) -#define CXXRTL_ALWAYS_INLINE inline __attribute__((__always_inline__)) -#else -#define CXXRTL_ALWAYS_INLINE inline -#endif - -namespace cxxrtl { - -// All arbitrary-width values in CXXRTL are backed by arrays of unsigned integers called chunks. The chunk size -// is the same regardless of the value width to simplify manipulating values via FFI interfaces, e.g. driving -// and introspecting the simulation in Python. -// -// It is practical to use chunk sizes between 32 bits and platform register size because when arithmetics on -// narrower integer types is legalized by the C++ compiler, it inserts code to clear the high bits of the register. -// However, (a) most of our operations do not change those bits in the first place because of invariants that are -// invisible to the compiler, (b) we often operate on non-power-of-2 values and have to clear the high bits anyway. -// Therefore, using relatively wide chunks and clearing the high bits explicitly and only when we know they may be -// clobbered results in simpler generated code. -typedef uint32_t chunk_t; -typedef uint64_t wide_chunk_t; - -template -struct chunk_traits { - static_assert(std::is_integral::value && std::is_unsigned::value, - "chunk type must be an unsigned integral type"); - using type = T; - static constexpr size_t bits = std::numeric_limits::digits; - static constexpr T mask = std::numeric_limits::max(); -}; - -template -struct expr_base; - -template -struct value : public expr_base> { - static constexpr size_t bits = Bits; - - using chunk = chunk_traits; - static constexpr chunk::type msb_mask = (Bits % chunk::bits == 0) ? chunk::mask - : chunk::mask >> (chunk::bits - (Bits % chunk::bits)); - - static constexpr size_t chunks = (Bits + chunk::bits - 1) / chunk::bits; - chunk::type data[chunks] = {}; - - value() = default; - template - explicit constexpr value(Init ...init) : data{init...} {} - - value(const value &) = default; - value(value &&) = default; - value &operator=(const value &) = default; - - // A (no-op) helper that forces the cast to value<>. - CXXRTL_ALWAYS_INLINE - const value &val() const { - return *this; - } - - std::string str() const { - std::stringstream ss; - ss << *this; - return ss.str(); - } - - // Conversion operations. - // - // These functions ensure that a conversion is never out of range, and should be always used, if at all - // possible, instead of direct manipulation of the `data` member. For very large types, .slice() and - // .concat() can be used to split them into more manageable parts. - template - CXXRTL_ALWAYS_INLINE - IntegerT get() const { - static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, - "get() requires T to be an unsigned integral type"); - static_assert(std::numeric_limits::digits >= Bits, - "get() requires T to be at least as wide as the value is"); - IntegerT result = 0; - for (size_t n = 0; n < chunks; n++) - result |= IntegerT(data[n]) << (n * chunk::bits); - return result; - } - - template - CXXRTL_ALWAYS_INLINE - void set(IntegerT other) { - static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, - "set() requires T to be an unsigned integral type"); - static_assert(std::numeric_limits::digits >= Bits, - "set() requires the value to be at least as wide as T is"); - for (size_t n = 0; n < chunks; n++) - data[n] = (other >> (n * chunk::bits)) & chunk::mask; - } - - // Operations with compile-time parameters. - // - // These operations are used to implement slicing, concatenation, and blitting. - // The trunc, zext and sext operations add or remove most significant bits (i.e. on the left); - // the rtrunc and rzext operations add or remove least significant bits (i.e. on the right). - template - CXXRTL_ALWAYS_INLINE - value trunc() const { - static_assert(NewBits <= Bits, "trunc() may not increase width"); - value result; - for (size_t n = 0; n < result.chunks; n++) - result.data[n] = data[n]; - result.data[result.chunks - 1] &= result.msb_mask; - return result; - } - - template - CXXRTL_ALWAYS_INLINE - value zext() const { - static_assert(NewBits >= Bits, "zext() may not decrease width"); - value result; - for (size_t n = 0; n < chunks; n++) - result.data[n] = data[n]; - return result; - } - - template - CXXRTL_ALWAYS_INLINE - value sext() const { - static_assert(NewBits >= Bits, "sext() may not decrease width"); - value result; - for (size_t n = 0; n < chunks; n++) - result.data[n] = data[n]; - if (is_neg()) { - result.data[chunks - 1] |= ~msb_mask; - for (size_t n = chunks; n < result.chunks; n++) - result.data[n] = chunk::mask; - result.data[result.chunks - 1] &= result.msb_mask; - } - return result; - } - - template - CXXRTL_ALWAYS_INLINE - value rtrunc() const { - static_assert(NewBits <= Bits, "rtrunc() may not increase width"); - value result; - constexpr size_t shift_chunks = (Bits - NewBits) / chunk::bits; - constexpr size_t shift_bits = (Bits - NewBits) % chunk::bits; - chunk::type carry = 0; - if (shift_chunks + result.chunks < chunks) { - carry = (shift_bits == 0) ? 0 - : data[shift_chunks + result.chunks] << (chunk::bits - shift_bits); - } - for (size_t n = result.chunks; n > 0; n--) { - result.data[n - 1] = carry | (data[shift_chunks + n - 1] >> shift_bits); - carry = (shift_bits == 0) ? 0 - : data[shift_chunks + n - 1] << (chunk::bits - shift_bits); - } - return result; - } - - template - CXXRTL_ALWAYS_INLINE - value rzext() const { - static_assert(NewBits >= Bits, "rzext() may not decrease width"); - value result; - constexpr size_t shift_chunks = (NewBits - Bits) / chunk::bits; - constexpr size_t shift_bits = (NewBits - Bits) % chunk::bits; - chunk::type carry = 0; - for (size_t n = 0; n < chunks; n++) { - result.data[shift_chunks + n] = (data[n] << shift_bits) | carry; - carry = (shift_bits == 0) ? 0 - : data[n] >> (chunk::bits - shift_bits); - } - if (shift_chunks + chunks < result.chunks) - result.data[shift_chunks + chunks] = carry; - return result; - } - - // Bit blit operation, i.e. a partial read-modify-write. - template - CXXRTL_ALWAYS_INLINE - value blit(const value &source) const { - static_assert(Stop >= Start, "blit() may not reverse bit order"); - constexpr chunk::type start_mask = ~(chunk::mask << (Start % chunk::bits)); - constexpr chunk::type stop_mask = (Stop % chunk::bits + 1 == chunk::bits) ? 0 - : (chunk::mask << (Stop % chunk::bits + 1)); - value masked = *this; - if (Start / chunk::bits == Stop / chunk::bits) { - masked.data[Start / chunk::bits] &= stop_mask | start_mask; - } else { - masked.data[Start / chunk::bits] &= start_mask; - for (size_t n = Start / chunk::bits + 1; n < Stop / chunk::bits; n++) - masked.data[n] = 0; - masked.data[Stop / chunk::bits] &= stop_mask; - } - value shifted = source - .template rzext() - .template zext(); - return masked.bit_or(shifted); - } - - // Helpers for selecting extending or truncating operation depending on whether the result is wider or narrower - // than the operand. In C++17 these can be replaced with `if constexpr`. - template - struct zext_cast { - CXXRTL_ALWAYS_INLINE - value operator()(const value &val) { - return val.template zext(); - } - }; - - template - struct zext_cast::type> { - CXXRTL_ALWAYS_INLINE - value operator()(const value &val) { - return val.template trunc(); - } - }; - - template - struct sext_cast { - CXXRTL_ALWAYS_INLINE - value operator()(const value &val) { - return val.template sext(); - } - }; - - template - struct sext_cast::type> { - CXXRTL_ALWAYS_INLINE - value operator()(const value &val) { - return val.template trunc(); - } - }; - - template - CXXRTL_ALWAYS_INLINE - value zcast() const { - return zext_cast()(*this); - } - - template - CXXRTL_ALWAYS_INLINE - value scast() const { - return sext_cast()(*this); - } - - // Operations with run-time parameters (offsets, amounts, etc). - // - // These operations are used for computations. - bool bit(size_t offset) const { - return data[offset / chunk::bits] & (1 << (offset % chunk::bits)); - } - - void set_bit(size_t offset, bool value = true) { - size_t offset_chunks = offset / chunk::bits; - size_t offset_bits = offset % chunk::bits; - data[offset_chunks] &= ~(1 << offset_bits); - data[offset_chunks] |= value ? 1 << offset_bits : 0; - } - - explicit operator bool() const { - return !is_zero(); - } - - bool is_zero() const { - for (size_t n = 0; n < chunks; n++) - if (data[n] != 0) - return false; - return true; - } - - bool is_neg() const { - return data[chunks - 1] & (1 << ((Bits - 1) % chunk::bits)); - } - - bool operator ==(const value &other) const { - for (size_t n = 0; n < chunks; n++) - if (data[n] != other.data[n]) - return false; - return true; - } - - bool operator !=(const value &other) const { - return !(*this == other); - } - - value bit_not() const { - value result; - for (size_t n = 0; n < chunks; n++) - result.data[n] = ~data[n]; - result.data[chunks - 1] &= msb_mask; - return result; - } - - value bit_and(const value &other) const { - value result; - for (size_t n = 0; n < chunks; n++) - result.data[n] = data[n] & other.data[n]; - return result; - } - - value bit_or(const value &other) const { - value result; - for (size_t n = 0; n < chunks; n++) - result.data[n] = data[n] | other.data[n]; - return result; - } - - value bit_xor(const value &other) const { - value result; - for (size_t n = 0; n < chunks; n++) - result.data[n] = data[n] ^ other.data[n]; - return result; - } - - value update(const value &val, const value &mask) const { - return bit_and(mask.bit_not()).bit_or(val.bit_and(mask)); - } - - template - value shl(const value &amount) const { - // Ensure our early return is correct by prohibiting values larger than 4 Gbit. - static_assert(Bits <= chunk::mask, "shl() of unreasonably large values is not supported"); - // Detect shifts definitely large than Bits early. - for (size_t n = 1; n < amount.chunks; n++) - if (amount.data[n] != 0) - return {}; - // Past this point we can use the least significant chunk as the shift size. - size_t shift_chunks = amount.data[0] / chunk::bits; - size_t shift_bits = amount.data[0] % chunk::bits; - if (shift_chunks >= chunks) - return {}; - value result; - chunk::type carry = 0; - for (size_t n = 0; n < chunks - shift_chunks; n++) { - result.data[shift_chunks + n] = (data[n] << shift_bits) | carry; - carry = (shift_bits == 0) ? 0 - : data[n] >> (chunk::bits - shift_bits); - } - return result; - } - - template - value shr(const value &amount) const { - // Ensure our early return is correct by prohibiting values larger than 4 Gbit. - static_assert(Bits <= chunk::mask, "shr() of unreasonably large values is not supported"); - // Detect shifts definitely large than Bits early. - for (size_t n = 1; n < amount.chunks; n++) - if (amount.data[n] != 0) - return {}; - // Past this point we can use the least significant chunk as the shift size. - size_t shift_chunks = amount.data[0] / chunk::bits; - size_t shift_bits = amount.data[0] % chunk::bits; - if (shift_chunks >= chunks) - return {}; - value result; - chunk::type carry = 0; - for (size_t n = 0; n < chunks - shift_chunks; n++) { - result.data[chunks - shift_chunks - 1 - n] = carry | (data[chunks - 1 - n] >> shift_bits); - carry = (shift_bits == 0) ? 0 - : data[chunks - 1 - n] << (chunk::bits - shift_bits); - } - if (Signed && is_neg()) { - size_t top_chunk_idx = (Bits - shift_bits) / chunk::bits; - size_t top_chunk_bits = (Bits - shift_bits) % chunk::bits; - for (size_t n = top_chunk_idx + 1; n < chunks; n++) - result.data[n] = chunk::mask; - if (shift_bits != 0) - result.data[top_chunk_idx] |= chunk::mask << top_chunk_bits; - } - return result; - } - - template - value sshr(const value &amount) const { - return shr(amount); - } - - size_t ctpop() const { - size_t count = 0; - for (size_t n = 0; n < chunks; n++) { - // This loop implements the population count idiom as recognized by LLVM and GCC. - for (chunk::type x = data[n]; x != 0; count++) - x = x & (x - 1); - } - return count; - } - - size_t ctlz() const { - size_t count = 0; - for (size_t n = 0; n < chunks; n++) { - chunk::type x = data[chunks - 1 - n]; - if (x == 0) { - count += (n == 0 ? Bits % chunk::bits : chunk::bits); - } else { - // This loop implements the find first set idiom as recognized by LLVM. - for (; x != 0; count++) - x >>= 1; - } - } - return count; - } - - template - std::pair, bool /*CarryOut*/> alu(const value &other) const { - value result; - bool carry = CarryIn; - for (size_t n = 0; n < result.chunks; n++) { - result.data[n] = data[n] + (Invert ? ~other.data[n] : other.data[n]) + carry; - carry = (result.data[n] < data[n]) || - (result.data[n] == data[n] && carry); - } - result.data[result.chunks - 1] &= result.msb_mask; - return {result, carry}; - } - - value add(const value &other) const { - return alu(other).first; - } - - value sub(const value &other) const { - return alu(other).first; - } - - value neg() const { - return value { 0u }.sub(*this); - } - - bool ucmp(const value &other) const { - bool carry; - std::tie(std::ignore, carry) = alu(other); - return !carry; // a.ucmp(b) ≡ a u< b - } - - bool scmp(const value &other) const { - value result; - bool carry; - std::tie(result, carry) = alu(other); - bool overflow = (is_neg() == !other.is_neg()) && (is_neg() != result.is_neg()); - return result.is_neg() ^ overflow; // a.scmp(b) ≡ a s< b - } - - template - value mul(const value &other) const { - value result; - wide_chunk_t wide_result[result.chunks + 1] = {}; - for (size_t n = 0; n < chunks; n++) { - for (size_t m = 0; m < chunks && n + m < result.chunks; m++) { - wide_result[n + m] += wide_chunk_t(data[n]) * wide_chunk_t(other.data[m]); - wide_result[n + m + 1] += wide_result[n + m] >> chunk::bits; - wide_result[n + m] &= chunk::mask; - } - } - for (size_t n = 0; n < result.chunks; n++) { - result.data[n] = wide_result[n]; - } - result.data[result.chunks - 1] &= result.msb_mask; - return result; - } -}; - -// Expression template for a slice, usable as lvalue or rvalue, and composable with other expression templates here. -template -struct slice_expr : public expr_base> { - static_assert(Stop >= Start, "slice_expr() may not reverse bit order"); - static_assert(Start < T::bits && Stop < T::bits, "slice_expr() must be within bounds"); - static constexpr size_t bits = Stop - Start + 1; - - T &expr; - - slice_expr(T &expr) : expr(expr) {} - slice_expr(const slice_expr &) = delete; - - CXXRTL_ALWAYS_INLINE - operator value() const { - return static_cast &>(expr) - .template rtrunc() - .template trunc(); - } - - CXXRTL_ALWAYS_INLINE - slice_expr &operator=(const value &rhs) { - // Generic partial assignment implemented using a read-modify-write operation on the sliced expression. - expr = static_cast &>(expr) - .template blit(rhs); - return *this; - } - - // A helper that forces the cast to value<>, which allows deduction to work. - CXXRTL_ALWAYS_INLINE - value val() const { - return static_cast &>(*this); - } -}; - -// Expression template for a concatenation, usable as lvalue or rvalue, and composable with other expression templates here. -template -struct concat_expr : public expr_base> { - static constexpr size_t bits = T::bits + U::bits; - - T &ms_expr; - U &ls_expr; - - concat_expr(T &ms_expr, U &ls_expr) : ms_expr(ms_expr), ls_expr(ls_expr) {} - concat_expr(const concat_expr &) = delete; - - CXXRTL_ALWAYS_INLINE - operator value() const { - value ms_shifted = static_cast &>(ms_expr) - .template rzext(); - value ls_extended = static_cast &>(ls_expr) - .template zext(); - return ms_shifted.bit_or(ls_extended); - } - - CXXRTL_ALWAYS_INLINE - concat_expr &operator=(const value &rhs) { - ms_expr = rhs.template rtrunc(); - ls_expr = rhs.template trunc(); - return *this; - } - - // A helper that forces the cast to value<>, which allows deduction to work. - CXXRTL_ALWAYS_INLINE - value val() const { - return static_cast &>(*this); - } -}; - -// Base class for expression templates, providing helper methods for operations that are valid on both rvalues and lvalues. -// -// Note that expression objects (slices and concatenations) constructed in this way should NEVER be captured because -// they refer to temporaries that will, in general, only live until the end of the statement. For example, both of -// these snippets perform use-after-free: -// -// const auto &a = val.slice<7,0>().slice<1>(); -// value<1> b = a; -// -// auto &&c = val.slice<7,0>().slice<1>(); -// c = value<1>{1u}; -// -// An easy way to write code using slices and concatenations safely is to follow two simple rules: -// * Never explicitly name any type except `value` or `const value &`. -// * Never use a `const auto &` or `auto &&` in any such expression. -// Then, any code that compiles will be well-defined. -template -struct expr_base { - template - CXXRTL_ALWAYS_INLINE - slice_expr slice() const { - return {*static_cast(this)}; - } - - template - CXXRTL_ALWAYS_INLINE - slice_expr slice() { - return {*static_cast(this)}; - } - - template - CXXRTL_ALWAYS_INLINE - concat_expr::type> concat(const U &other) const { - return {*static_cast(this), other}; - } - - template - CXXRTL_ALWAYS_INLINE - concat_expr::type> concat(U &&other) { - return {*static_cast(this), other}; - } -}; - -template -std::ostream &operator<<(std::ostream &os, const value &val) { - auto old_flags = os.flags(std::ios::right); - auto old_width = os.width(0); - auto old_fill = os.fill('0'); - os << val.bits << '\'' << std::hex; - for (size_t n = val.chunks - 1; n != (size_t)-1; n--) { - if (n == val.chunks - 1 && Bits % value::chunk::bits != 0) - os.width((Bits % value::chunk::bits + 3) / 4); - else - os.width((value::chunk::bits + 3) / 4); - os << val.data[n]; - } - os.fill(old_fill); - os.width(old_width); - os.flags(old_flags); - return os; -} - -template -struct wire { - static constexpr size_t bits = Bits; - - value curr; - value next; - - wire() = default; - constexpr wire(const value &init) : curr(init), next(init) {} - template - explicit constexpr wire(Init ...init) : curr{init...}, next{init...} {} - - wire(const wire &) = delete; - wire(wire &&) = default; - wire &operator=(const wire &) = delete; - - template - CXXRTL_ALWAYS_INLINE - IntegerT get() const { - return curr.template get(); - } - - template - CXXRTL_ALWAYS_INLINE - void set(IntegerT other) { - next.template set(other); - } - - bool commit() { - if (curr != next) { - curr = next; - return true; - } - return false; - } -}; - -template -std::ostream &operator<<(std::ostream &os, const wire &val) { - os << val.curr; - return os; -} - -template -struct memory { - std::vector> data; - - size_t depth() const { - return data.size(); - } - - memory() = delete; - explicit memory(size_t depth) : data(depth) {} - - memory(const memory &) = delete; - memory &operator=(const memory &) = delete; - - // The only way to get the compiler to put the initializer in .rodata and do not copy it on stack is to stuff it - // into a plain array. You'd think an std::initializer_list would work here, but it doesn't, because you can't - // construct an initializer_list in a constexpr (or something) and so if you try to do that the whole thing is - // first copied on the stack (probably overflowing it) and then again into `data`. - template - struct init { - size_t offset; - value data[Size]; - }; - - template - explicit memory(size_t depth, const init &...init) : data(depth) { - data.resize(depth); - // This utterly reprehensible construct is the most reasonable way to apply a function to every element - // of a parameter pack, if the elements all have different types and so cannot be cast to an initializer list. - auto _ = {std::move(std::begin(init.data), std::end(init.data), data.begin() + init.offset)...}; - (void)_; - } - - // An operator for direct memory reads. May be used at any time during the simulation. - const value &operator [](size_t index) const { - assert(index < data.size()); - return data[index]; - } - - // An operator for direct memory writes. May only be used before the simulation is started. If used - // after the simulation is started, the design may malfunction. - value &operator [](size_t index) { - assert(index < data.size()); - return data[index]; - } - - // A simple way to make a writable memory would be to use an array of wires instead of an array of values. - // However, there are two significant downsides to this approach: first, it has large overhead (2× space - // overhead, and O(depth) time overhead during commit); second, it does not simplify handling write port - // priorities. Although in principle write ports could be ordered or conditionally enabled in generated - // code based on their priorities and selected addresses, the feedback arc set problem is computationally - // expensive, and the heuristic based algorithms are not easily modified to guarantee (rather than prefer) - // a particular write port evaluation order. - // - // The approach used here instead is to queue writes into a buffer during the eval phase, then perform - // the writes during the commit phase in the priority order. This approach has low overhead, with both space - // and time proportional to the amount of write ports. Because virtually every memory in a practical design - // has at most two write ports, linear search is used on every write, being the fastest and simplest approach. - struct write { - size_t index; - value val; - value mask; - int priority; - }; - std::vector write_queue; - - void update(size_t index, const value &val, const value &mask, int priority = 0) { - assert(index < data.size()); - // Queue up the write while keeping the queue sorted by priority. - write_queue.insert( - std::upper_bound(write_queue.begin(), write_queue.end(), priority, - [](const int a, const write& b) { return a < b.priority; }), - write { index, val, mask, priority }); - } - - bool commit() { - bool changed = false; - for (const write &entry : write_queue) { - value elem = data[entry.index]; - elem = elem.update(entry.val, entry.mask); - changed |= (data[entry.index] != elem); - data[entry.index] = elem; - } - write_queue.clear(); - return changed; - } -}; - -struct metadata { - const enum { - MISSING = 0, - UINT = 1, - SINT = 2, - STRING = 3, - DOUBLE = 4, - } value_type; - - // In debug mode, using the wrong .as_*() function will assert. - // In release mode, using the wrong .as_*() function will safely return a default value. - const unsigned uint_value = 0; - const signed sint_value = 0; - const std::string string_value = ""; - const double double_value = 0.0; - - metadata() : value_type(MISSING) {} - metadata(unsigned value) : value_type(UINT), uint_value(value) {} - metadata(signed value) : value_type(SINT), sint_value(value) {} - metadata(const std::string &value) : value_type(STRING), string_value(value) {} - metadata(const char *value) : value_type(STRING), string_value(value) {} - metadata(double value) : value_type(DOUBLE), double_value(value) {} - - metadata(const metadata &) = default; - metadata &operator=(const metadata &) = delete; - - unsigned as_uint() const { - assert(value_type == UINT); - return uint_value; - } - - signed as_sint() const { - assert(value_type == SINT); - return sint_value; - } - - const std::string &as_string() const { - assert(value_type == STRING); - return string_value; - } - - double as_double() const { - assert(value_type == DOUBLE); - return double_value; - } -}; - -typedef std::map metadata_map; - -// Helper class to disambiguate values/wires and their aliases. -struct debug_alias {}; - -// This structure is intended for consumption via foreign function interfaces, like Python's ctypes. -// Because of this it uses a C-style layout that is easy to parse rather than more idiomatic C++. -// -// To avoid violating strict aliasing rules, this structure has to be a subclass of the one used -// in the C API, or it would not be possible to cast between the pointers to these. -struct debug_item : ::cxxrtl_object { - enum : uint32_t { - VALUE = CXXRTL_VALUE, - WIRE = CXXRTL_WIRE, - MEMORY = CXXRTL_MEMORY, - ALIAS = CXXRTL_ALIAS, - }; - - debug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {} - - template - debug_item(value &item, size_t lsb_offset = 0) { - static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), - "value is not compatible with C layout"); - type = VALUE; - width = Bits; - lsb_at = lsb_offset; - depth = 1; - zero_at = 0; - curr = item.data; - next = item.data; - } - - template - debug_item(const value &item, size_t lsb_offset = 0) { - static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), - "value is not compatible with C layout"); - type = VALUE; - width = Bits; - lsb_at = lsb_offset; - depth = 1; - zero_at = 0; - curr = const_cast(item.data); - next = nullptr; - } - - template - debug_item(wire &item, size_t lsb_offset = 0) { - static_assert(sizeof(item.curr) == value::chunks * sizeof(chunk_t) && - sizeof(item.next) == value::chunks * sizeof(chunk_t), - "wire is not compatible with C layout"); - type = WIRE; - width = Bits; - lsb_at = lsb_offset; - depth = 1; - zero_at = 0; - curr = item.curr.data; - next = item.next.data; - } - - template - debug_item(memory &item, size_t zero_offset = 0) { - static_assert(sizeof(item.data[0]) == value::chunks * sizeof(chunk_t), - "memory is not compatible with C layout"); - type = MEMORY; - width = Width; - lsb_at = 0; - depth = item.data.size(); - zero_at = zero_offset; - curr = item.data.empty() ? nullptr : item.data[0].data; - next = nullptr; - } - - template - debug_item(debug_alias, const value &item, size_t lsb_offset = 0) { - static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), - "value is not compatible with C layout"); - type = ALIAS; - width = Bits; - lsb_at = lsb_offset; - depth = 1; - zero_at = 0; - curr = const_cast(item.data); - next = nullptr; - } - - template - debug_item(debug_alias, const wire &item, size_t lsb_offset = 0) { - static_assert(sizeof(item.curr) == value::chunks * sizeof(chunk_t) && - sizeof(item.next) == value::chunks * sizeof(chunk_t), - "wire is not compatible with C layout"); - type = ALIAS; - width = Bits; - lsb_at = lsb_offset; - depth = 1; - zero_at = 0; - curr = const_cast(item.curr.data); - next = nullptr; - } -}; -static_assert(std::is_standard_layout::value, "debug_item is not compatible with C layout"); - -struct debug_items { - std::map> table; - - void add(const std::string &name, debug_item &&item) { - std::vector &parts = table[name]; - parts.emplace_back(item); - std::sort(parts.begin(), parts.end(), - [](const debug_item &a, const debug_item &b) { - return a.lsb_at < b.lsb_at; - }); - } - - size_t count(const std::string &name) const { - if (table.count(name) == 0) - return 0; - return table.at(name).size(); - } - - const std::vector &parts_at(const std::string &name) const { - return table.at(name); - } - - const debug_item &at(const std::string &name) const { - const std::vector &parts = table.at(name); - assert(parts.size() == 1); - return parts.at(0); - } - - const debug_item &operator [](const std::string &name) const { - return at(name); - } -}; - -struct module { - module() {} - virtual ~module() {} - - module(const module &) = delete; - module &operator=(const module &) = delete; - - virtual bool eval() = 0; - virtual bool commit() = 0; - - size_t step() { - size_t deltas = 0; - bool converged = false; - do { - converged = eval(); - deltas++; - } while (commit() && !converged); - return deltas; - } - - virtual void debug_info(debug_items &items, std::string path = "") { - (void)items, (void)path; - } -}; - -} // namespace cxxrtl - -// Internal structure used to communicate with the implementation of the C interface. -typedef struct _cxxrtl_toplevel { - std::unique_ptr module; -} *cxxrtl_toplevel; - -// Definitions of internal Yosys cells. Other than the functions in this namespace, CXXRTL is fully generic -// and indepenent of Yosys implementation details. -// -// The `write_cxxrtl` pass translates internal cells (cells with names that start with `$`) to calls of these -// functions. All of Yosys arithmetic and logical cells perform sign or zero extension on their operands, -// whereas basic operations on arbitrary width values require operands to be of the same width. These functions -// bridge the gap by performing the necessary casts. They are named similar to `cell_A[B]`, where A and B are `u` -// if the corresponding operand is unsigned, and `s` if it is signed. -namespace cxxrtl_yosys { - -using namespace cxxrtl; - -// std::max isn't constexpr until C++14 for no particular reason (it's an oversight), so we define our own. -template -CXXRTL_ALWAYS_INLINE -constexpr T max(const T &a, const T &b) { - return a > b ? a : b; -} - -// Logic operations -template -CXXRTL_ALWAYS_INLINE -value logic_not(const value &a) { - return value { a ? 0u : 1u }; -} - -template -CXXRTL_ALWAYS_INLINE -value logic_and(const value &a, const value &b) { - return value { (bool(a) && bool(b)) ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value logic_or(const value &a, const value &b) { - return value { (bool(a) || bool(b)) ? 1u : 0u }; -} - -// Reduction operations -template -CXXRTL_ALWAYS_INLINE -value reduce_and(const value &a) { - return value { a.bit_not().is_zero() ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value reduce_or(const value &a) { - return value { a ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value reduce_xor(const value &a) { - return value { (a.ctpop() % 2) ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value reduce_xnor(const value &a) { - return value { (a.ctpop() % 2) ? 0u : 1u }; -} - -template -CXXRTL_ALWAYS_INLINE -value reduce_bool(const value &a) { - return value { a ? 1u : 0u }; -} - -// Bitwise operations -template -CXXRTL_ALWAYS_INLINE -value not_u(const value &a) { - return a.template zcast().bit_not(); -} - -template -CXXRTL_ALWAYS_INLINE -value not_s(const value &a) { - return a.template scast().bit_not(); -} - -template -CXXRTL_ALWAYS_INLINE -value and_uu(const value &a, const value &b) { - return a.template zcast().bit_and(b.template zcast()); -} - -template -CXXRTL_ALWAYS_INLINE -value and_ss(const value &a, const value &b) { - return a.template scast().bit_and(b.template scast()); -} - -template -CXXRTL_ALWAYS_INLINE -value or_uu(const value &a, const value &b) { - return a.template zcast().bit_or(b.template zcast()); -} - -template -CXXRTL_ALWAYS_INLINE -value or_ss(const value &a, const value &b) { - return a.template scast().bit_or(b.template scast()); -} - -template -CXXRTL_ALWAYS_INLINE -value xor_uu(const value &a, const value &b) { - return a.template zcast().bit_xor(b.template zcast()); -} - -template -CXXRTL_ALWAYS_INLINE -value xor_ss(const value &a, const value &b) { - return a.template scast().bit_xor(b.template scast()); -} - -template -CXXRTL_ALWAYS_INLINE -value xnor_uu(const value &a, const value &b) { - return a.template zcast().bit_xor(b.template zcast()).bit_not(); -} - -template -CXXRTL_ALWAYS_INLINE -value xnor_ss(const value &a, const value &b) { - return a.template scast().bit_xor(b.template scast()).bit_not(); -} - -template -CXXRTL_ALWAYS_INLINE -value shl_uu(const value &a, const value &b) { - return a.template zcast().template shl(b); -} - -template -CXXRTL_ALWAYS_INLINE -value shl_su(const value &a, const value &b) { - return a.template scast().template shl(b); -} - -template -CXXRTL_ALWAYS_INLINE -value sshl_uu(const value &a, const value &b) { - return a.template zcast().template shl(b); -} - -template -CXXRTL_ALWAYS_INLINE -value sshl_su(const value &a, const value &b) { - return a.template scast().template shl(b); -} - -template -CXXRTL_ALWAYS_INLINE -value shr_uu(const value &a, const value &b) { - return a.template shr(b).template zcast(); -} - -template -CXXRTL_ALWAYS_INLINE -value shr_su(const value &a, const value &b) { - return a.template shr(b).template scast(); -} - -template -CXXRTL_ALWAYS_INLINE -value sshr_uu(const value &a, const value &b) { - return a.template shr(b).template zcast(); -} - -template -CXXRTL_ALWAYS_INLINE -value sshr_su(const value &a, const value &b) { - return a.template sshr(b).template scast(); -} - -template -CXXRTL_ALWAYS_INLINE -value shift_uu(const value &a, const value &b) { - return shr_uu(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value shift_su(const value &a, const value &b) { - return shr_su(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value shift_us(const value &a, const value &b) { - return b.is_neg() ? shl_uu(a, b.template sext().neg()) : shr_uu(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value shift_ss(const value &a, const value &b) { - return b.is_neg() ? shl_su(a, b.template sext().neg()) : shr_su(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value shiftx_uu(const value &a, const value &b) { - return shift_uu(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value shiftx_su(const value &a, const value &b) { - return shift_su(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value shiftx_us(const value &a, const value &b) { - return shift_us(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value shiftx_ss(const value &a, const value &b) { - return shift_ss(a, b); -} - -// Comparison operations -template -CXXRTL_ALWAYS_INLINE -value eq_uu(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value{ a.template zext() == b.template zext() ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value eq_ss(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value{ a.template sext() == b.template sext() ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value ne_uu(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value{ a.template zext() != b.template zext() ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value ne_ss(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value{ a.template sext() != b.template sext() ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value eqx_uu(const value &a, const value &b) { - return eq_uu(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value eqx_ss(const value &a, const value &b) { - return eq_ss(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value nex_uu(const value &a, const value &b) { - return ne_uu(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value nex_ss(const value &a, const value &b) { - return ne_ss(a, b); -} - -template -CXXRTL_ALWAYS_INLINE -value gt_uu(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value { b.template zext().ucmp(a.template zext()) ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value gt_ss(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value { b.template sext().scmp(a.template sext()) ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value ge_uu(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value { !a.template zext().ucmp(b.template zext()) ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value ge_ss(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value { !a.template sext().scmp(b.template sext()) ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value lt_uu(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value { a.template zext().ucmp(b.template zext()) ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value lt_ss(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value { a.template sext().scmp(b.template sext()) ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value le_uu(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value { !b.template zext().ucmp(a.template zext()) ? 1u : 0u }; -} - -template -CXXRTL_ALWAYS_INLINE -value le_ss(const value &a, const value &b) { - constexpr size_t BitsExt = max(BitsA, BitsB); - return value { !b.template sext().scmp(a.template sext()) ? 1u : 0u }; -} - -// Arithmetic operations -template -CXXRTL_ALWAYS_INLINE -value pos_u(const value &a) { - return a.template zcast(); -} - -template -CXXRTL_ALWAYS_INLINE -value pos_s(const value &a) { - return a.template scast(); -} - -template -CXXRTL_ALWAYS_INLINE -value neg_u(const value &a) { - return a.template zcast().neg(); -} - -template -CXXRTL_ALWAYS_INLINE -value neg_s(const value &a) { - return a.template scast().neg(); -} - -template -CXXRTL_ALWAYS_INLINE -value add_uu(const value &a, const value &b) { - return a.template zcast().add(b.template zcast()); -} - -template -CXXRTL_ALWAYS_INLINE -value add_ss(const value &a, const value &b) { - return a.template scast().add(b.template scast()); -} - -template -CXXRTL_ALWAYS_INLINE -value sub_uu(const value &a, const value &b) { - return a.template zcast().sub(b.template zcast()); -} - -template -CXXRTL_ALWAYS_INLINE -value sub_ss(const value &a, const value &b) { - return a.template scast().sub(b.template scast()); -} - -template -CXXRTL_ALWAYS_INLINE -value mul_uu(const value &a, const value &b) { - constexpr size_t BitsM = BitsA >= BitsB ? BitsA : BitsB; - return a.template zcast().template mul(b.template zcast()); -} - -template -CXXRTL_ALWAYS_INLINE -value mul_ss(const value &a, const value &b) { - return a.template scast().template mul(b.template scast()); -} - -template -CXXRTL_ALWAYS_INLINE -std::pair, value> divmod_uu(const value &a, const value &b) { - constexpr size_t Bits = max(BitsY, max(BitsA, BitsB)); - value quotient; - value dividend = a.template zext(); - value divisor = b.template zext(); - if (dividend.ucmp(divisor)) - return {/*quotient=*/value { 0u }, /*remainder=*/dividend.template trunc()}; - uint32_t divisor_shift = dividend.ctlz() - divisor.ctlz(); - divisor = divisor.shl(value<32> { divisor_shift }); - for (size_t step = 0; step <= divisor_shift; step++) { - quotient = quotient.shl(value<1> { 1u }); - if (!dividend.ucmp(divisor)) { - dividend = dividend.sub(divisor); - quotient.set_bit(0, true); - } - divisor = divisor.shr(value<1> { 1u }); - } - return {quotient.template trunc(), /*remainder=*/dividend.template trunc()}; -} - -template -CXXRTL_ALWAYS_INLINE -std::pair, value> divmod_ss(const value &a, const value &b) { - value ua = a.template sext(); - value ub = b.template sext(); - if (ua.is_neg()) ua = ua.neg(); - if (ub.is_neg()) ub = ub.neg(); - value y, r; - std::tie(y, r) = divmod_uu(ua, ub); - if (a.is_neg() != b.is_neg()) y = y.neg(); - if (a.is_neg()) r = r.neg(); - return {y, r}; -} - -template -CXXRTL_ALWAYS_INLINE -value div_uu(const value &a, const value &b) { - return divmod_uu(a, b).first; -} - -template -CXXRTL_ALWAYS_INLINE -value div_ss(const value &a, const value &b) { - return divmod_ss(a, b).first; -} - -template -CXXRTL_ALWAYS_INLINE -value mod_uu(const value &a, const value &b) { - return divmod_uu(a, b).second; -} - -template -CXXRTL_ALWAYS_INLINE -value mod_ss(const value &a, const value &b) { - return divmod_ss(a, b).second; -} - -// Memory helper -struct memory_index { - bool valid; - size_t index; - - template - memory_index(const value &addr, size_t offset, size_t depth) { - static_assert(value::chunks <= 1, "memory address is too wide"); - size_t offset_index = addr.data[0]; - - valid = (offset_index >= offset && offset_index < offset + depth); - index = offset_index - offset; - } -}; - -} // namespace cxxrtl_yosys - -#endif diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc deleted file mode 100644 index 5e5ba5ac0f0..00000000000 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ /dev/null @@ -1,2671 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2019-2020 whitequark - * - * 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/rtlil.h" -#include "kernel/register.h" -#include "kernel/sigtools.h" -#include "kernel/utils.h" -#include "kernel/celltypes.h" -#include "kernel/log.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -// [[CITE]] -// Peter Eades; Xuemin Lin; W. F. Smyth, "A Fast Effective Heuristic For The Feedback Arc Set Problem" -// Information Processing Letters, Vol. 47, pp 319-323, 1993 -// https://pdfs.semanticscholar.org/c7ed/d9acce96ca357876540e19664eb9d976637f.pdf - -// A topological sort (on a cell/wire graph) is always possible in a fully flattened RTLIL design without -// processes or logic loops where every wire has a single driver. Logic loops are illegal in RTLIL and wires -// with multiple drivers can be split by the `splitnets` pass; however, interdependencies between processes -// or module instances can create strongly connected components without introducing evaluation nondeterminism. -// We wish to support designs with such benign SCCs (as well as designs with multiple drivers per wire), so -// we sort the graph in a way that minimizes feedback arcs. If there are no feedback arcs in the sorted graph, -// then a more efficient evaluation method is possible, since eval() will always immediately converge. -template -struct Scheduler { - struct Vertex { - T *data; - Vertex *prev, *next; - pool preds, succs; - - Vertex() : data(NULL), prev(this), next(this) {} - Vertex(T *data) : data(data), prev(NULL), next(NULL) {} - - bool empty() const - { - log_assert(data == NULL); - if (next == this) { - log_assert(prev == next); - return true; - } - return false; - } - - void link(Vertex *list) - { - log_assert(prev == NULL && next == NULL); - next = list; - prev = list->prev; - list->prev->next = this; - list->prev = this; - } - - void unlink() - { - log_assert(prev->next == this && next->prev == this); - prev->next = next; - next->prev = prev; - next = prev = NULL; - } - - int delta() const - { - return succs.size() - preds.size(); - } - }; - - std::vector vertices; - Vertex *sources = new Vertex; - Vertex *sinks = new Vertex; - dict bins; - - ~Scheduler() - { - delete sources; - delete sinks; - for (auto bin : bins) - delete bin.second; - for (auto vertex : vertices) - delete vertex; - } - - Vertex *add(T *data) - { - Vertex *vertex = new Vertex(data); - vertices.push_back(vertex); - return vertex; - } - - void relink(Vertex *vertex) - { - if (vertex->succs.empty()) - vertex->link(sinks); - else if (vertex->preds.empty()) - vertex->link(sources); - else { - int delta = vertex->delta(); - if (!bins.count(delta)) - bins[delta] = new Vertex; - vertex->link(bins[delta]); - } - } - - Vertex *remove(Vertex *vertex) - { - vertex->unlink(); - for (auto pred : vertex->preds) { - if (pred == vertex) - continue; - log_assert(pred->succs[vertex]); - pred->unlink(); - pred->succs.erase(vertex); - relink(pred); - } - for (auto succ : vertex->succs) { - if (succ == vertex) - continue; - log_assert(succ->preds[vertex]); - succ->unlink(); - succ->preds.erase(vertex); - relink(succ); - } - vertex->preds.clear(); - vertex->succs.clear(); - return vertex; - } - - std::vector schedule() - { - std::vector s1, s2r; - for (auto vertex : vertices) - relink(vertex); - bool bins_empty = false; - while (!(sinks->empty() && sources->empty() && bins_empty)) { - while (!sinks->empty()) - s2r.push_back(remove(sinks->next)); - while (!sources->empty()) - s1.push_back(remove(sources->next)); - // Choosing u in this implementation isn't O(1), but the paper handwaves which data structure they suggest - // using to get O(1) relinking *and* find-max-key ("it is clear"... no it isn't), so this code uses a very - // naive implementation of find-max-key. - bins_empty = true; - bins.template sort>(); - for (auto bin : bins) { - if (!bin.second->empty()) { - bins_empty = false; - s1.push_back(remove(bin.second->next)); - break; - } - } - } - s1.insert(s1.end(), s2r.rbegin(), s2r.rend()); - return s1; - } -}; - -bool is_unary_cell(RTLIL::IdString type) -{ - return type.in( - ID($not), ID($logic_not), ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), - ID($pos), ID($neg)); -} - -bool is_binary_cell(RTLIL::IdString type) -{ - return type.in( - ID($and), ID($or), ID($xor), ID($xnor), ID($logic_and), ID($logic_or), - ID($shl), ID($sshl), ID($shr), ID($sshr), ID($shift), ID($shiftx), - ID($eq), ID($ne), ID($eqx), ID($nex), ID($gt), ID($ge), ID($lt), ID($le), - ID($add), ID($sub), ID($mul), ID($div), ID($mod)); -} - -bool is_extending_cell(RTLIL::IdString type) -{ - return !type.in( - ID($logic_not), ID($logic_and), ID($logic_or), - ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool)); -} - -bool is_elidable_cell(RTLIL::IdString type) -{ - return is_unary_cell(type) || is_binary_cell(type) || type.in( - ID($mux), ID($concat), ID($slice), ID($pmux)); -} - -bool is_sync_ff_cell(RTLIL::IdString type) -{ - return type.in( - ID($dff), ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)); -} - -bool is_ff_cell(RTLIL::IdString type) -{ - return is_sync_ff_cell(type) || type.in( - ID($adff), ID($adffe), ID($dffsr), ID($dffsre), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr)); -} - -bool is_internal_cell(RTLIL::IdString type) -{ - return type[0] == '$' && !type.begins_with("$paramod"); -} - -bool is_cxxrtl_blackbox_cell(const RTLIL::Cell *cell) -{ - RTLIL::Module *cell_module = cell->module->design->module(cell->type); - log_assert(cell_module != nullptr); - return cell_module->get_bool_attribute(ID(cxxrtl_blackbox)); -} - -enum class CxxrtlPortType { - UNKNOWN = 0, // or mixed comb/sync - COMB = 1, - SYNC = 2, -}; - -CxxrtlPortType cxxrtl_port_type(const RTLIL::Cell *cell, RTLIL::IdString port) -{ - RTLIL::Module *cell_module = cell->module->design->module(cell->type); - if (cell_module == nullptr || !cell_module->get_bool_attribute(ID(cxxrtl_blackbox))) - return CxxrtlPortType::UNKNOWN; - RTLIL::Wire *cell_output_wire = cell_module->wire(port); - log_assert(cell_output_wire != nullptr); - bool is_comb = cell_output_wire->get_bool_attribute(ID(cxxrtl_comb)); - bool is_sync = cell_output_wire->get_bool_attribute(ID(cxxrtl_sync)); - if (is_comb && is_sync) - log_cmd_error("Port `%s.%s' is marked as both `cxxrtl_comb` and `cxxrtl_sync`.\n", - log_id(cell_module), log_signal(cell_output_wire)); - else if (is_comb) - return CxxrtlPortType::COMB; - else if (is_sync) - return CxxrtlPortType::SYNC; - return CxxrtlPortType::UNKNOWN; -} - -bool is_cxxrtl_comb_port(const RTLIL::Cell *cell, RTLIL::IdString port) -{ - return cxxrtl_port_type(cell, port) == CxxrtlPortType::COMB; -} - -bool is_cxxrtl_sync_port(const RTLIL::Cell *cell, RTLIL::IdString port) -{ - return cxxrtl_port_type(cell, port) == CxxrtlPortType::SYNC; -} - -struct FlowGraph { - struct Node { - enum class Type { - CONNECT, - CELL_SYNC, - CELL_EVAL, - PROCESS - }; - - Type type; - RTLIL::SigSig connect = {}; - const RTLIL::Cell *cell = NULL; - const RTLIL::Process *process = NULL; - }; - - std::vector nodes; - dict> wire_comb_defs, wire_sync_defs, wire_uses; - dict wire_def_elidable, wire_use_elidable; - - ~FlowGraph() - { - for (auto node : nodes) - delete node; - } - - void add_defs(Node *node, const RTLIL::SigSpec &sig, bool fully_sync, bool elidable) - { - for (auto chunk : sig.chunks()) - if (chunk.wire) { - if (fully_sync) - wire_sync_defs[chunk.wire].insert(node); - else - wire_comb_defs[chunk.wire].insert(node); - } - // Only comb defs of an entire wire in the right order can be elided. - if (!fully_sync && sig.is_wire()) - wire_def_elidable[sig.as_wire()] = elidable; - } - - void add_uses(Node *node, const RTLIL::SigSpec &sig) - { - for (auto chunk : sig.chunks()) - if (chunk.wire) { - wire_uses[chunk.wire].insert(node); - // Only a single use of an entire wire in the right order can be elided. - // (But the use can include other chunks.) - if (!wire_use_elidable.count(chunk.wire)) - wire_use_elidable[chunk.wire] = true; - else - wire_use_elidable[chunk.wire] = false; - } - } - - bool is_elidable(const RTLIL::Wire *wire) const - { - if (wire_def_elidable.count(wire) && wire_use_elidable.count(wire)) - return wire_def_elidable.at(wire) && wire_use_elidable.at(wire); - return false; - } - - // Connections - void add_connect_defs_uses(Node *node, const RTLIL::SigSig &conn) - { - add_defs(node, conn.first, /*fully_sync=*/false, /*elidable=*/true); - add_uses(node, conn.second); - } - - Node *add_node(const RTLIL::SigSig &conn) - { - Node *node = new Node; - node->type = Node::Type::CONNECT; - node->connect = conn; - nodes.push_back(node); - add_connect_defs_uses(node, conn); - return node; - } - - // Cells - void add_cell_sync_defs(Node *node, const RTLIL::Cell *cell) - { - // To understand why this node type is necessary and why it produces comb defs, consider a cell - // with input \i and sync output \o, used in a design such that \i is connected to \o. This does - // not result in a feedback arc because the output is synchronous. However, a naive implementation - // of code generation for cells that assigns to inputs, evaluates cells, assigns from outputs - // would not be able to immediately converge... - // - // wire<1> i_tmp; - // cell->p_i = i_tmp.curr; - // cell->eval(); - // i_tmp.next = cell->p_o.curr; - // - // ... since the wire connecting the input and output ports would not be localizable. To solve - // this, the cell is split into two scheduling nodes; one exclusively for sync outputs, and - // another for inputs and all non-sync outputs. This way the generated code can be rearranged... - // - // value<1> i_tmp; - // i_tmp = cell->p_o.curr; - // cell->p_i = i_tmp; - // cell->eval(); - // - // eliminating the unnecessary delta cycle. Conceptually, the CELL_SYNC node type is a series of - // connections of the form `connect \lhs \cell.\sync_output`; the right-hand side of these is not - // expressible as a wire in RTLIL. If it was expressible, then `\cell.\sync_output` would have - // a sync def, and this node would be an ordinary CONNECT node, with `\lhs` having a comb def. - // Because it isn't, a special node type is used, the right-hand side does not appear anywhere, - // and the left-hand side has a comb def. - for (auto conn : cell->connections()) - if (cell->output(conn.first)) - if (is_cxxrtl_sync_port(cell, conn.first)) { - // See note regarding elidability below. - add_defs(node, conn.second, /*fully_sync=*/false, /*elidable=*/false); - } - } - - void add_cell_eval_defs_uses(Node *node, const RTLIL::Cell *cell) - { - for (auto conn : cell->connections()) { - if (cell->output(conn.first)) { - if (is_elidable_cell(cell->type)) - add_defs(node, conn.second, /*fully_sync=*/false, /*elidable=*/true); - else if (is_sync_ff_cell(cell->type) || (cell->type == ID($memrd) && cell->getParam(ID::CLK_ENABLE).as_bool())) - add_defs(node, conn.second, /*fully_sync=*/true, /*elidable=*/false); - else if (is_internal_cell(cell->type)) - add_defs(node, conn.second, /*fully_sync=*/false, /*elidable=*/false); - else if (!is_cxxrtl_sync_port(cell, conn.first)) { - // Although at first it looks like outputs of user-defined cells may always be elided, the reality is - // more complex. Fully sync outputs produce no defs and so don't participate in elision. Fully comb - // outputs are assigned in a different way depending on whether the cell's eval() immediately converged. - // Unknown/mixed outputs could be elided, but should be rare in practical designs and don't justify - // the infrastructure required to elide outputs of cells with many of them. - add_defs(node, conn.second, /*fully_sync=*/false, /*elidable=*/false); - } - } - if (cell->input(conn.first)) - add_uses(node, conn.second); - } - } - - Node *add_node(const RTLIL::Cell *cell) - { - log_assert(cell->known()); - - bool has_fully_sync_outputs = false; - for (auto conn : cell->connections()) - if (cell->output(conn.first) && is_cxxrtl_sync_port(cell, conn.first)) { - has_fully_sync_outputs = true; - break; - } - if (has_fully_sync_outputs) { - Node *node = new Node; - node->type = Node::Type::CELL_SYNC; - node->cell = cell; - nodes.push_back(node); - add_cell_sync_defs(node, cell); - } - - Node *node = new Node; - node->type = Node::Type::CELL_EVAL; - node->cell = cell; - nodes.push_back(node); - add_cell_eval_defs_uses(node, cell); - return node; - } - - // Processes - void add_case_defs_uses(Node *node, const RTLIL::CaseRule *case_) - { - for (auto &action : case_->actions) { - add_defs(node, action.first, /*is_sync=*/false, /*elidable=*/false); - add_uses(node, action.second); - } - for (auto sub_switch : case_->switches) { - add_uses(node, sub_switch->signal); - for (auto sub_case : sub_switch->cases) { - for (auto &compare : sub_case->compare) - add_uses(node, compare); - add_case_defs_uses(node, sub_case); - } - } - } - - void add_process_defs_uses(Node *node, const RTLIL::Process *process) - { - add_case_defs_uses(node, &process->root_case); - for (auto sync : process->syncs) - for (auto action : sync->actions) { - if (sync->type == RTLIL::STp || sync->type == RTLIL::STn || sync->type == RTLIL::STe) - add_defs(node, action.first, /*is_sync=*/true, /*elidable=*/false); - else - add_defs(node, action.first, /*is_sync=*/false, /*elidable=*/false); - add_uses(node, action.second); - } - } - - Node *add_node(const RTLIL::Process *process) - { - Node *node = new Node; - node->type = Node::Type::PROCESS; - node->process = process; - nodes.push_back(node); - add_process_defs_uses(node, process); - return node; - } -}; - -std::vector split_by(const std::string &str, const std::string &sep) -{ - std::vector result; - size_t prev = 0; - while (true) { - size_t curr = str.find_first_of(sep, prev); - if (curr == std::string::npos) { - std::string part = str.substr(prev); - if (!part.empty()) result.push_back(part); - break; - } else { - std::string part = str.substr(prev, curr - prev); - if (!part.empty()) result.push_back(part); - prev = curr + 1; - } - } - return result; -} - -std::string escape_cxx_string(const std::string &input) -{ - std::string output = "\""; - for (auto c : input) { - if (::isprint(c)) { - if (c == '\\') - output.push_back('\\'); - output.push_back(c); - } else { - char l = c & 0xf, h = (c >> 4) & 0xf; - output.append("\\x"); - output.push_back((h < 10 ? '0' + h : 'a' + h - 10)); - output.push_back((l < 10 ? '0' + l : 'a' + l - 10)); - } - } - output.push_back('"'); - if (output.find('\0') != std::string::npos) { - output.insert(0, "std::string {"); - output.append(stringf(", %zu}", input.size())); - } - return output; -} - -template -std::string get_hdl_name(T *object) -{ - if (object->has_attribute(ID::hdlname)) - return object->get_string_attribute(ID::hdlname); - else - return object->name.str().substr(1); -} - -struct CxxrtlWorker { - bool split_intf = false; - std::string intf_filename; - std::string design_ns = "cxxrtl_design"; - std::ostream *impl_f = nullptr; - std::ostream *intf_f = nullptr; - - bool run_flatten = false; - bool run_proc = false; - - bool unbuffer_internal = false; - bool unbuffer_public = false; - bool localize_internal = false; - bool localize_public = false; - bool elide_internal = false; - bool elide_public = false; - - bool debug_info = false; - - std::ostringstream f; - std::string indent; - int temporary = 0; - - dict sigmaps; - pool edge_wires; - dict edge_types; - pool writable_memories; - dict> transparent_for; - dict elided_wires; - dict> schedule; - pool unbuffered_wires; - pool localized_wires; - dict debug_alias_wires; - dict debug_const_wires; - dict> blackbox_specializations; - dict eval_converges; - - void inc_indent() { - indent += "\t"; - } - void dec_indent() { - indent.resize(indent.size() - 1); - } - - // RTLIL allows any characters in names other than whitespace. This presents an issue for generating C++ code - // because C++ identifiers may be only alphanumeric, cannot clash with C++ keywords, and cannot clash with cxxrtl - // identifiers. This issue can be solved with a name mangling scheme. We choose a name mangling scheme that results - // in readable identifiers, does not depend on an up-to-date list of C++ keywords, and is easy to apply. Its rules: - // 1. All generated identifiers start with `_`. - // 1a. Generated identifiers for public names (beginning with `\`) start with `p_`. - // 1b. Generated identifiers for internal names (beginning with `$`) start with `i_`. - // 2. An underscore is escaped with another underscore, i.e. `__`. - // 3. Any other non-alnum character is escaped with underscores around its lowercase hex code, e.g. `@` as `_40_`. - std::string mangle_name(const RTLIL::IdString &name) - { - std::string mangled; - bool first = true; - for (char c : name.str()) { - if (first) { - first = false; - if (c == '\\') - mangled += "p_"; - else if (c == '$') - mangled += "i_"; - else - log_assert(false); - } else { - if (isalnum(c)) { - mangled += c; - } else if (c == '_') { - mangled += "__"; - } else { - char l = c & 0xf, h = (c >> 4) & 0xf; - mangled += '_'; - mangled += (h < 10 ? '0' + h : 'a' + h - 10); - mangled += (l < 10 ? '0' + l : 'a' + l - 10); - mangled += '_'; - } - } - } - return mangled; - } - - std::string mangle_module_name(const RTLIL::IdString &name, bool is_blackbox = false) - { - // Class namespace. - if (is_blackbox) - return "bb_" + mangle_name(name); - return mangle_name(name); - } - - std::string mangle_memory_name(const RTLIL::IdString &name) - { - // Class member namespace. - return "memory_" + mangle_name(name); - } - - std::string mangle_cell_name(const RTLIL::IdString &name) - { - // Class member namespace. - return "cell_" + mangle_name(name); - } - - std::string mangle_wire_name(const RTLIL::IdString &name) - { - // Class member namespace. - return mangle_name(name); - } - - std::string mangle(const RTLIL::Module *module) - { - return mangle_module_name(module->name, /*is_blackbox=*/module->get_bool_attribute(ID(cxxrtl_blackbox))); - } - - std::string mangle(const RTLIL::Memory *memory) - { - return mangle_memory_name(memory->name); - } - - std::string mangle(const RTLIL::Cell *cell) - { - return mangle_cell_name(cell->name); - } - - std::string mangle(const RTLIL::Wire *wire) - { - return mangle_wire_name(wire->name); - } - - std::string mangle(RTLIL::SigBit sigbit) - { - log_assert(sigbit.wire != NULL); - if (sigbit.wire->width == 1) - return mangle(sigbit.wire); - return mangle(sigbit.wire) + "_" + std::to_string(sigbit.offset); - } - - std::vector template_param_names(const RTLIL::Module *module) - { - if (!module->has_attribute(ID(cxxrtl_template))) - return {}; - - if (module->attributes.at(ID(cxxrtl_template)).flags != RTLIL::CONST_FLAG_STRING) - log_cmd_error("Attribute `cxxrtl_template' of module `%s' is not a string.\n", log_id(module)); - - std::vector param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t"); - for (const auto ¶m_name : param_names) { - // Various lowercase prefixes (p_, i_, cell_, ...) are used for member variables, so require - // parameters to start with an uppercase letter to avoid name conflicts. (This is the convention - // in both Verilog and C++, anyway.) - if (!isupper(param_name[0])) - log_cmd_error("Attribute `cxxrtl_template' of module `%s' includes a parameter `%s', " - "which does not start with an uppercase letter.\n", - log_id(module), param_name.c_str()); - } - return param_names; - } - - std::string template_params(const RTLIL::Module *module, bool is_decl) - { - std::vector param_names = template_param_names(module); - if (param_names.empty()) - return ""; - - std::string params = "<"; - bool first = true; - for (const auto ¶m_name : param_names) { - if (!first) - params += ", "; - first = false; - if (is_decl) - params += "size_t "; - params += param_name; - } - params += ">"; - return params; - } - - std::string template_args(const RTLIL::Cell *cell) - { - RTLIL::Module *cell_module = cell->module->design->module(cell->type); - log_assert(cell_module != nullptr); - if (!cell_module->get_bool_attribute(ID(cxxrtl_blackbox))) - return ""; - - std::vector param_names = template_param_names(cell_module); - if (param_names.empty()) - return ""; - - std::string params = "<"; - bool first = true; - for (const auto ¶m_name : param_names) { - if (!first) - params += ", "; - first = false; - params += "/*" + param_name + "=*/"; - RTLIL::IdString id_param_name = '\\' + param_name; - if (!cell->hasParam(id_param_name)) - log_cmd_error("Cell `%s.%s' does not have a parameter `%s', which is required by the templated module `%s'.\n", - log_id(cell->module), log_id(cell), param_name.c_str(), log_id(cell_module)); - RTLIL::Const param_value = cell->getParam(id_param_name); - if (((param_value.flags & ~RTLIL::CONST_FLAG_SIGNED) != 0) || param_value.as_int() < 0) - log_cmd_error("Parameter `%s' of cell `%s.%s', which is required by the templated module `%s', " - "is not a positive integer.\n", - param_name.c_str(), log_id(cell->module), log_id(cell), log_id(cell_module)); - params += std::to_string(cell->getParam(id_param_name).as_int()); - } - params += ">"; - return params; - } - - std::string fresh_temporary() - { - return stringf("tmp_%d", temporary++); - } - - void dump_attrs(const RTLIL::AttrObject *object) - { - for (auto attr : object->attributes) { - f << indent << "// " << attr.first.str() << ": "; - if (attr.second.flags & RTLIL::CONST_FLAG_STRING) { - f << attr.second.decode_string(); - } else { - f << attr.second.as_int(/*is_signed=*/attr.second.flags & RTLIL::CONST_FLAG_SIGNED); - } - f << "\n"; - } - } - - void dump_const_init(const RTLIL::Const &data, int width, int offset = 0, bool fixed_width = false) - { - const int CHUNK_SIZE = 32; - f << "{"; - while (width > 0) { - int chunk_width = min(width, CHUNK_SIZE); - uint32_t chunk = data.extract(offset, chunk_width).as_int(); - if (fixed_width) - f << stringf("0x%.*xu", (3 + chunk_width) / 4, chunk); - else - f << stringf("%#xu", chunk); - if (width > CHUNK_SIZE) - f << ','; - offset += CHUNK_SIZE; - width -= CHUNK_SIZE; - } - f << "}"; - } - - void dump_const_init(const RTLIL::Const &data) - { - dump_const_init(data, data.size()); - } - - void dump_const(const RTLIL::Const &data, int width, int offset = 0, bool fixed_width = false) - { - f << "value<" << width << ">"; - dump_const_init(data, width, offset, fixed_width); - } - - void dump_const(const RTLIL::Const &data) - { - dump_const(data, data.size()); - } - - bool dump_sigchunk(const RTLIL::SigChunk &chunk, bool is_lhs) - { - if (chunk.wire == NULL) { - dump_const(chunk.data, chunk.width, chunk.offset); - return false; - } else { - if (elided_wires.count(chunk.wire)) { - log_assert(!is_lhs); - const FlowGraph::Node &node = elided_wires[chunk.wire]; - switch (node.type) { - case FlowGraph::Node::Type::CONNECT: - dump_connect_elided(node.connect); - break; - case FlowGraph::Node::Type::CELL_EVAL: - log_assert(is_elidable_cell(node.cell->type)); - dump_cell_elided(node.cell); - break; - default: - log_assert(false); - } - } else if (unbuffered_wires[chunk.wire]) { - f << mangle(chunk.wire); - } else { - f << mangle(chunk.wire) << (is_lhs ? ".next" : ".curr"); - } - if (chunk.width == chunk.wire->width && chunk.offset == 0) - return false; - else if (chunk.width == 1) - f << ".slice<" << chunk.offset << ">()"; - else - f << ".slice<" << chunk.offset+chunk.width-1 << "," << chunk.offset << ">()"; - return true; - } - } - - bool dump_sigspec(const RTLIL::SigSpec &sig, bool is_lhs) - { - if (sig.empty()) { - f << "value<0>()"; - return false; - } else if (sig.is_chunk()) { - return dump_sigchunk(sig.as_chunk(), is_lhs); - } else { - dump_sigchunk(*sig.chunks().rbegin(), is_lhs); - for (auto it = sig.chunks().rbegin() + 1; it != sig.chunks().rend(); ++it) { - f << ".concat("; - dump_sigchunk(*it, is_lhs); - f << ")"; - } - return true; - } - } - - void dump_sigspec_lhs(const RTLIL::SigSpec &sig) - { - dump_sigspec(sig, /*is_lhs=*/true); - } - - void dump_sigspec_rhs(const RTLIL::SigSpec &sig) - { - // In the contexts where we want template argument deduction to occur for `template ... value`, - // it is necessary to have the argument to already be a `value`, since template argument deduction and implicit - // type conversion are mutually exclusive. In these contexts, we use dump_sigspec_rhs() to emit an explicit - // type conversion, but only if the expression needs it. - bool is_complex = dump_sigspec(sig, /*is_lhs=*/false); - if (is_complex) - f << ".val()"; - } - - void collect_sigspec_rhs(const RTLIL::SigSpec &sig, std::vector &cells) - { - for (auto chunk : sig.chunks()) { - if (!chunk.wire || !elided_wires.count(chunk.wire)) - continue; - - const FlowGraph::Node &node = elided_wires[chunk.wire]; - switch (node.type) { - case FlowGraph::Node::Type::CONNECT: - collect_connect(node.connect, cells); - break; - case FlowGraph::Node::Type::CELL_EVAL: - collect_cell_eval(node.cell, cells); - break; - default: - log_assert(false); - } - } - } - - void dump_connect_elided(const RTLIL::SigSig &conn) - { - dump_sigspec_rhs(conn.second); - } - - bool is_connect_elided(const RTLIL::SigSig &conn) - { - return conn.first.is_wire() && elided_wires.count(conn.first.as_wire()); - } - - void collect_connect(const RTLIL::SigSig &conn, std::vector &cells) - { - if (!is_connect_elided(conn)) - return; - - collect_sigspec_rhs(conn.second, cells); - } - - void dump_connect(const RTLIL::SigSig &conn) - { - if (is_connect_elided(conn)) - return; - - f << indent << "// connection\n"; - f << indent; - dump_sigspec_lhs(conn.first); - f << " = "; - dump_connect_elided(conn); - f << ";\n"; - } - - void dump_cell_sync(const RTLIL::Cell *cell) - { - const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : "."; - f << indent << "// cell " << cell->name.str() << " syncs\n"; - for (auto conn : cell->connections()) - if (cell->output(conn.first)) - if (is_cxxrtl_sync_port(cell, conn.first)) { - f << indent; - dump_sigspec_lhs(conn.second); - f << " = " << mangle(cell) << access << mangle_wire_name(conn.first) << ".curr;\n"; - } - } - - void dump_cell_elided(const RTLIL::Cell *cell) - { - // Unary cells - if (is_unary_cell(cell->type)) { - f << cell->type.substr(1); - if (is_extending_cell(cell->type)) - f << '_' << (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u'); - f << "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">("; - dump_sigspec_rhs(cell->getPort(ID::A)); - f << ")"; - // Binary cells - } else if (is_binary_cell(cell->type)) { - f << cell->type.substr(1); - if (is_extending_cell(cell->type)) - f << '_' << (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u') << - (cell->getParam(ID::B_SIGNED).as_bool() ? 's' : 'u'); - f << "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">("; - dump_sigspec_rhs(cell->getPort(ID::A)); - f << ", "; - dump_sigspec_rhs(cell->getPort(ID::B)); - f << ")"; - // Muxes - } else if (cell->type == ID($mux)) { - f << "("; - dump_sigspec_rhs(cell->getPort(ID::S)); - f << " ? "; - dump_sigspec_rhs(cell->getPort(ID::B)); - f << " : "; - dump_sigspec_rhs(cell->getPort(ID::A)); - f << ")"; - // Parallel (one-hot) muxes - } else if (cell->type == ID($pmux)) { - int width = cell->getParam(ID::WIDTH).as_int(); - int s_width = cell->getParam(ID::S_WIDTH).as_int(); - for (int part = 0; part < s_width; part++) { - f << "("; - dump_sigspec_rhs(cell->getPort(ID::S).extract(part)); - f << " ? "; - dump_sigspec_rhs(cell->getPort(ID::B).extract(part * width, width)); - f << " : "; - } - dump_sigspec_rhs(cell->getPort(ID::A)); - for (int part = 0; part < s_width; part++) { - f << ")"; - } - // Concats - } else if (cell->type == ID($concat)) { - dump_sigspec_rhs(cell->getPort(ID::B)); - f << ".concat("; - dump_sigspec_rhs(cell->getPort(ID::A)); - f << ").val()"; - // Slices - } else if (cell->type == ID($slice)) { - dump_sigspec_rhs(cell->getPort(ID::A)); - f << ".slice<"; - f << cell->getParam(ID::OFFSET).as_int() + cell->getParam(ID::Y_WIDTH).as_int() - 1; - f << ","; - f << cell->getParam(ID::OFFSET).as_int(); - f << ">().val()"; - } else { - log_assert(false); - } - } - - bool is_cell_elided(const RTLIL::Cell *cell) - { - return is_elidable_cell(cell->type) && cell->hasPort(ID::Y) && cell->getPort(ID::Y).is_wire() && - elided_wires.count(cell->getPort(ID::Y).as_wire()); - } - - void collect_cell_eval(const RTLIL::Cell *cell, std::vector &cells) - { - if (!is_cell_elided(cell)) - return; - - cells.push_back(cell->name); - for (auto port : cell->connections()) - if (port.first != ID::Y) - collect_sigspec_rhs(port.second, cells); - } - - void dump_cell_eval(const RTLIL::Cell *cell) - { - if (is_cell_elided(cell)) - return; - if (cell->type == ID($meminit)) - return; // Handled elsewhere. - - std::vector elided_cells; - if (is_elidable_cell(cell->type)) { - for (auto port : cell->connections()) - if (port.first != ID::Y) - collect_sigspec_rhs(port.second, elided_cells); - } - if (elided_cells.empty()) { - dump_attrs(cell); - f << indent << "// cell " << cell->name.str() << "\n"; - } else { - f << indent << "// cells"; - for (auto elided_cell : elided_cells) - f << " " << elided_cell.str(); - f << "\n"; - } - - // Elidable cells - if (is_elidable_cell(cell->type)) { - f << indent; - dump_sigspec_lhs(cell->getPort(ID::Y)); - f << " = "; - dump_cell_elided(cell); - f << ";\n"; - // Flip-flops - } else if (is_ff_cell(cell->type)) { - if (cell->hasPort(ID::CLK) && cell->getPort(ID::CLK).is_wire()) { - // Edge-sensitive logic - RTLIL::SigBit clk_bit = cell->getPort(ID::CLK)[0]; - clk_bit = sigmaps[clk_bit.wire->module](clk_bit); - f << indent << "if (" << (cell->getParam(ID::CLK_POLARITY).as_bool() ? "posedge_" : "negedge_") - << mangle(clk_bit) << ") {\n"; - inc_indent(); - if (cell->hasPort(ID::EN)) { - f << indent << "if ("; - dump_sigspec_rhs(cell->getPort(ID::EN)); - f << " == value<1> {" << cell->getParam(ID::EN_POLARITY).as_bool() << "u}) {\n"; - inc_indent(); - } - f << indent; - dump_sigspec_lhs(cell->getPort(ID::Q)); - f << " = "; - dump_sigspec_rhs(cell->getPort(ID::D)); - f << ";\n"; - if (cell->hasPort(ID::EN) && cell->type != ID($sdffce)) { - dec_indent(); - f << indent << "}\n"; - } - if (cell->hasPort(ID::SRST)) { - f << indent << "if ("; - dump_sigspec_rhs(cell->getPort(ID::SRST)); - f << " == value<1> {" << cell->getParam(ID::SRST_POLARITY).as_bool() << "u}) {\n"; - inc_indent(); - f << indent; - dump_sigspec_lhs(cell->getPort(ID::Q)); - f << " = "; - dump_const(cell->getParam(ID::SRST_VALUE)); - f << ";\n"; - dec_indent(); - f << indent << "}\n"; - } - if (cell->hasPort(ID::EN) && cell->type == ID($sdffce)) { - dec_indent(); - f << indent << "}\n"; - } - dec_indent(); - f << indent << "}\n"; - } else if (cell->hasPort(ID::EN)) { - // Level-sensitive logic - f << indent << "if ("; - dump_sigspec_rhs(cell->getPort(ID::EN)); - f << " == value<1> {" << cell->getParam(ID::EN_POLARITY).as_bool() << "u}) {\n"; - inc_indent(); - f << indent; - dump_sigspec_lhs(cell->getPort(ID::Q)); - f << " = "; - dump_sigspec_rhs(cell->getPort(ID::D)); - f << ";\n"; - dec_indent(); - f << indent << "}\n"; - } - if (cell->hasPort(ID::ARST)) { - // Asynchronous reset (entire coarse cell at once) - f << indent << "if ("; - dump_sigspec_rhs(cell->getPort(ID::ARST)); - f << " == value<1> {" << cell->getParam(ID::ARST_POLARITY).as_bool() << "u}) {\n"; - inc_indent(); - f << indent; - dump_sigspec_lhs(cell->getPort(ID::Q)); - f << " = "; - dump_const(cell->getParam(ID::ARST_VALUE)); - f << ";\n"; - dec_indent(); - f << indent << "}\n"; - } - if (cell->hasPort(ID::SET)) { - // Asynchronous set (for individual bits) - f << indent; - dump_sigspec_lhs(cell->getPort(ID::Q)); - f << " = "; - dump_sigspec_lhs(cell->getPort(ID::Q)); - f << ".update("; - dump_const(RTLIL::Const(RTLIL::S1, cell->getParam(ID::WIDTH).as_int())); - f << ", "; - dump_sigspec_rhs(cell->getPort(ID::SET)); - f << (cell->getParam(ID::SET_POLARITY).as_bool() ? "" : ".bit_not()") << ");\n"; - } - if (cell->hasPort(ID::CLR)) { - // Asynchronous clear (for individual bits; priority over set) - f << indent; - dump_sigspec_lhs(cell->getPort(ID::Q)); - f << " = "; - dump_sigspec_lhs(cell->getPort(ID::Q)); - f << ".update("; - dump_const(RTLIL::Const(RTLIL::S0, cell->getParam(ID::WIDTH).as_int())); - f << ", "; - dump_sigspec_rhs(cell->getPort(ID::CLR)); - f << (cell->getParam(ID::CLR_POLARITY).as_bool() ? "" : ".bit_not()") << ");\n"; - } - // Memory ports - } else if (cell->type.in(ID($memrd), ID($memwr))) { - if (cell->getParam(ID::CLK_ENABLE).as_bool()) { - RTLIL::SigBit clk_bit = cell->getPort(ID::CLK)[0]; - clk_bit = sigmaps[clk_bit.wire->module](clk_bit); - f << indent << "if (" << (cell->getParam(ID::CLK_POLARITY).as_bool() ? "posedge_" : "negedge_") - << mangle(clk_bit) << ") {\n"; - inc_indent(); - } - RTLIL::Memory *memory = cell->module->memories[cell->getParam(ID::MEMID).decode_string()]; - std::string valid_index_temp = fresh_temporary(); - f << indent << "auto " << valid_index_temp << " = memory_index("; - dump_sigspec_rhs(cell->getPort(ID::ADDR)); - f << ", " << memory->start_offset << ", " << memory->size << ");\n"; - if (cell->type == ID($memrd)) { - bool has_enable = cell->getParam(ID::CLK_ENABLE).as_bool() && !cell->getPort(ID::EN).is_fully_ones(); - if (has_enable) { - f << indent << "if ("; - dump_sigspec_rhs(cell->getPort(ID::EN)); - f << ") {\n"; - inc_indent(); - } - // The generated code has two bounds checks; one in an assertion, and another that guards the read. - // This is done so that the code does not invoke undefined behavior under any conditions, but nevertheless - // loudly crashes if an illegal condition is encountered. The assert may be turned off with -NDEBUG not - // just for release builds, but also to make sure the simulator (which is presumably embedded in some - // larger program) will never crash the code that calls into it. - // - // If assertions are disabled, out of bounds reads are defined to return zero. - f << indent << "assert(" << valid_index_temp << ".valid && \"out of bounds read\");\n"; - f << indent << "if(" << valid_index_temp << ".valid) {\n"; - inc_indent(); - if (writable_memories[memory]) { - std::string lhs_temp = fresh_temporary(); - f << indent << "value<" << memory->width << "> " << lhs_temp << " = " - << mangle(memory) << "[" << valid_index_temp << ".index];\n"; - std::vector memwr_cells(transparent_for[cell].begin(), transparent_for[cell].end()); - if (!memwr_cells.empty()) { - std::string addr_temp = fresh_temporary(); - f << indent << "const value<" << cell->getPort(ID::ADDR).size() << "> &" << addr_temp << " = "; - dump_sigspec_rhs(cell->getPort(ID::ADDR)); - f << ";\n"; - std::sort(memwr_cells.begin(), memwr_cells.end(), - [](const RTLIL::Cell *a, const RTLIL::Cell *b) { - return a->getParam(ID::PRIORITY).as_int() < b->getParam(ID::PRIORITY).as_int(); - }); - for (auto memwr_cell : memwr_cells) { - f << indent << "if (" << addr_temp << " == "; - dump_sigspec_rhs(memwr_cell->getPort(ID::ADDR)); - f << ") {\n"; - inc_indent(); - f << indent << lhs_temp << " = " << lhs_temp; - f << ".update("; - dump_sigspec_rhs(memwr_cell->getPort(ID::DATA)); - f << ", "; - dump_sigspec_rhs(memwr_cell->getPort(ID::EN)); - f << ");\n"; - dec_indent(); - f << indent << "}\n"; - } - } - f << indent; - dump_sigspec_lhs(cell->getPort(ID::DATA)); - f << " = " << lhs_temp << ";\n"; - } else { - f << indent; - dump_sigspec_lhs(cell->getPort(ID::DATA)); - f << " = " << mangle(memory) << "[" << valid_index_temp << ".index];\n"; - } - dec_indent(); - f << indent << "} else {\n"; - inc_indent(); - f << indent; - dump_sigspec_lhs(cell->getPort(ID::DATA)); - f << " = value<" << memory->width << "> {};\n"; - dec_indent(); - f << indent << "}\n"; - if (has_enable) { - dec_indent(); - f << indent << "}\n"; - } - } else /*if (cell->type == ID($memwr))*/ { - log_assert(writable_memories[memory]); - // See above for rationale of having both the assert and the condition. - // - // If assertions are disabled, out of bounds writes are defined to do nothing. - f << indent << "assert(" << valid_index_temp << ".valid && \"out of bounds write\");\n"; - f << indent << "if (" << valid_index_temp << ".valid) {\n"; - inc_indent(); - f << indent << mangle(memory) << ".update(" << valid_index_temp << ".index, "; - dump_sigspec_rhs(cell->getPort(ID::DATA)); - f << ", "; - dump_sigspec_rhs(cell->getPort(ID::EN)); - f << ", " << cell->getParam(ID::PRIORITY).as_int() << ");\n"; - dec_indent(); - f << indent << "}\n"; - } - if (cell->getParam(ID::CLK_ENABLE).as_bool()) { - dec_indent(); - f << indent << "}\n"; - } - // Internal cells - } else if (is_internal_cell(cell->type)) { - log_cmd_error("Unsupported internal cell `%s'.\n", cell->type.c_str()); - // User cells - } else { - log_assert(cell->known()); - const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : "."; - for (auto conn : cell->connections()) - if (cell->input(conn.first) && !cell->output(conn.first)) { - f << indent << mangle(cell) << access << mangle_wire_name(conn.first) << " = "; - dump_sigspec_rhs(conn.second); - f << ";\n"; - if (getenv("CXXRTL_VOID_MY_WARRANTY")) { - // Until we have proper clock tree detection, this really awful hack that opportunistically - // propagates prev_* values for clocks can be used to estimate how much faster a design could - // be if only one clock edge was simulated by replacing: - // top.p_clk = value<1>{0u}; top.step(); - // top.p_clk = value<1>{1u}; top.step(); - // with: - // top.prev_p_clk = value<1>{0u}; top.p_clk = value<1>{1u}; top.step(); - // Don't rely on this; it will be removed without warning. - RTLIL::Module *cell_module = cell->module->design->module(cell->type); - if (cell_module != nullptr && cell_module->wire(conn.first) && conn.second.is_wire()) { - RTLIL::Wire *cell_module_wire = cell_module->wire(conn.first); - if (edge_wires[conn.second.as_wire()] && edge_wires[cell_module_wire]) { - f << indent << mangle(cell) << access << "prev_" << mangle(cell_module_wire) << " = "; - f << "prev_" << mangle(conn.second.as_wire()) << ";\n"; - } - } - } - } else if (cell->input(conn.first)) { - f << indent << mangle(cell) << access << mangle_wire_name(conn.first) << ".next = "; - dump_sigspec_rhs(conn.second); - f << ";\n"; - } - auto assign_from_outputs = [&](bool cell_converged) { - for (auto conn : cell->connections()) { - if (cell->output(conn.first)) { - if (conn.second.empty()) - continue; // ignore disconnected ports - if (is_cxxrtl_sync_port(cell, conn.first)) - continue; // fully sync ports are handled in CELL_SYNC nodes - f << indent; - dump_sigspec_lhs(conn.second); - f << " = " << mangle(cell) << access << mangle_wire_name(conn.first); - // Similarly to how there is no purpose to buffering cell inputs, there is also no purpose to buffering - // combinatorial cell outputs in case the cell converges within one cycle. (To convince yourself that - // this optimization is valid, consider that, since the cell converged within one cycle, it would not - // have any buffered wires if they were not output ports. Imagine inlining the cell's eval() function, - // and consider the fate of the localized wires that used to be output ports.) - // - // Unlike cell inputs (which are never buffered), it is not possible to know apriori whether the cell - // (which may be late bound) will converge immediately. Because of this, the choice between using .curr - // (appropriate for buffered outputs) and .next (appropriate for unbuffered outputs) is made at runtime. - if (cell_converged && is_cxxrtl_comb_port(cell, conn.first)) - f << ".next;\n"; - else - f << ".curr;\n"; - } - } - }; - f << indent << "if (" << mangle(cell) << access << "eval()) {\n"; - inc_indent(); - assign_from_outputs(/*cell_converged=*/true); - dec_indent(); - f << indent << "} else {\n"; - inc_indent(); - f << indent << "converged = false;\n"; - assign_from_outputs(/*cell_converged=*/false); - dec_indent(); - f << indent << "}\n"; - } - } - - void dump_assign(const RTLIL::SigSig &sigsig) - { - f << indent; - dump_sigspec_lhs(sigsig.first); - f << " = "; - dump_sigspec_rhs(sigsig.second); - f << ";\n"; - } - - void dump_case_rule(const RTLIL::CaseRule *rule) - { - for (auto action : rule->actions) - dump_assign(action); - for (auto switch_ : rule->switches) - dump_switch_rule(switch_); - } - - void dump_switch_rule(const RTLIL::SwitchRule *rule) - { - // The switch attributes are printed before the switch condition is captured. - dump_attrs(rule); - std::string signal_temp = fresh_temporary(); - f << indent << "const value<" << rule->signal.size() << "> &" << signal_temp << " = "; - dump_sigspec(rule->signal, /*is_lhs=*/false); - f << ";\n"; - - bool first = true; - for (auto case_ : rule->cases) { - // The case attributes (for nested cases) are printed before the if/else if/else statement. - dump_attrs(rule); - f << indent; - if (!first) - f << "} else "; - first = false; - if (!case_->compare.empty()) { - f << "if ("; - bool first = true; - for (auto &compare : case_->compare) { - if (!first) - f << " || "; - first = false; - if (compare.is_fully_def()) { - f << signal_temp << " == "; - dump_sigspec(compare, /*is_lhs=*/false); - } else if (compare.is_fully_const()) { - RTLIL::Const compare_mask, compare_value; - for (auto bit : compare.as_const()) { - switch (bit) { - case RTLIL::S0: - case RTLIL::S1: - compare_mask.bits.push_back(RTLIL::S1); - compare_value.bits.push_back(bit); - break; - - case RTLIL::Sx: - case RTLIL::Sz: - case RTLIL::Sa: - compare_mask.bits.push_back(RTLIL::S0); - compare_value.bits.push_back(RTLIL::S0); - break; - - default: - log_assert(false); - } - } - f << "and_uu<" << compare.size() << ">(" << signal_temp << ", "; - dump_const(compare_mask); - f << ") == "; - dump_const(compare_value); - } else { - log_assert(false); - } - } - f << ") "; - } - f << "{\n"; - inc_indent(); - dump_case_rule(case_); - dec_indent(); - } - f << indent << "}\n"; - } - - void dump_process(const RTLIL::Process *proc) - { - dump_attrs(proc); - f << indent << "// process " << proc->name.str() << "\n"; - // The case attributes (for root case) are always empty. - log_assert(proc->root_case.attributes.empty()); - dump_case_rule(&proc->root_case); - for (auto sync : proc->syncs) { - RTLIL::SigBit sync_bit; - if (!sync->signal.empty()) { - sync_bit = sync->signal[0]; - sync_bit = sigmaps[sync_bit.wire->module](sync_bit); - } - - pool events; - switch (sync->type) { - case RTLIL::STp: - log_assert(sync_bit.wire != nullptr); - events.insert("posedge_" + mangle(sync_bit)); - break; - case RTLIL::STn: - log_assert(sync_bit.wire != nullptr); - events.insert("negedge_" + mangle(sync_bit)); - break; - case RTLIL::STe: - log_assert(sync_bit.wire != nullptr); - events.insert("posedge_" + mangle(sync_bit)); - events.insert("negedge_" + mangle(sync_bit)); - break; - - case RTLIL::STa: - events.insert("true"); - break; - - case RTLIL::ST0: - case RTLIL::ST1: - case RTLIL::STg: - case RTLIL::STi: - log_assert(false); - } - if (!events.empty()) { - f << indent << "if ("; - bool first = true; - for (auto &event : events) { - if (!first) - f << " || "; - first = false; - f << event; - } - f << ") {\n"; - inc_indent(); - for (auto action : sync->actions) - dump_assign(action); - dec_indent(); - f << indent << "}\n"; - } - } - } - - void dump_wire(const RTLIL::Wire *wire, bool is_local_context) - { - if (elided_wires.count(wire)) - return; - - if (localized_wires[wire] && is_local_context) { - dump_attrs(wire); - f << indent << "value<" << wire->width << "> " << mangle(wire) << ";\n"; - } - if (!localized_wires[wire] && !is_local_context) { - std::string width; - if (wire->module->has_attribute(ID(cxxrtl_blackbox)) && wire->has_attribute(ID(cxxrtl_width))) { - width = wire->get_string_attribute(ID(cxxrtl_width)); - } else { - width = std::to_string(wire->width); - } - - dump_attrs(wire); - f << indent; - if (wire->port_input && wire->port_output) - f << "/*inout*/ "; - else if (wire->port_input) - f << "/*input*/ "; - else if (wire->port_output) - f << "/*output*/ "; - f << (unbuffered_wires[wire] ? "value" : "wire") << "<" << width << "> " << mangle(wire); - if (wire->has_attribute(ID::init)) { - f << " "; - dump_const_init(wire->attributes.at(ID::init)); - } - f << ";\n"; - if (edge_wires[wire]) { - if (unbuffered_wires[wire]) { - f << indent << "value<" << width << "> prev_" << mangle(wire); - if (wire->has_attribute(ID::init)) { - f << " "; - dump_const_init(wire->attributes.at(ID::init)); - } - f << ";\n"; - } - for (auto edge_type : edge_types) { - if (edge_type.first.wire == wire) { - std::string prev, next; - if (unbuffered_wires[wire]) { - prev = "prev_" + mangle(edge_type.first.wire); - next = mangle(edge_type.first.wire); - } else { - prev = mangle(edge_type.first.wire) + ".curr"; - next = mangle(edge_type.first.wire) + ".next"; - } - prev += ".slice<" + std::to_string(edge_type.first.offset) + ">().val()"; - next += ".slice<" + std::to_string(edge_type.first.offset) + ">().val()"; - if (edge_type.second != RTLIL::STn) { - f << indent << "bool posedge_" << mangle(edge_type.first) << "() const {\n"; - inc_indent(); - f << indent << "return !" << prev << " && " << next << ";\n"; - dec_indent(); - f << indent << "}\n"; - } - if (edge_type.second != RTLIL::STp) { - f << indent << "bool negedge_" << mangle(edge_type.first) << "() const {\n"; - inc_indent(); - f << indent << "return " << prev << " && !" << next << ";\n"; - dec_indent(); - f << indent << "}\n"; - } - } - } - } - } - } - - void dump_memory(RTLIL::Module *module, const RTLIL::Memory *memory) - { - vector init_cells; - for (auto cell : module->cells()) - if (cell->type == ID($meminit) && cell->getParam(ID::MEMID).decode_string() == memory->name.str()) - init_cells.push_back(cell); - - std::sort(init_cells.begin(), init_cells.end(), [](const RTLIL::Cell *a, const RTLIL::Cell *b) { - int a_addr = a->getPort(ID::ADDR).as_int(), b_addr = b->getPort(ID::ADDR).as_int(); - int a_prio = a->getParam(ID::PRIORITY).as_int(), b_prio = b->getParam(ID::PRIORITY).as_int(); - return a_prio > b_prio || (a_prio == b_prio && a_addr < b_addr); - }); - - dump_attrs(memory); - f << indent << "memory<" << memory->width << "> " << mangle(memory) - << " { " << memory->size << "u"; - if (init_cells.empty()) { - f << " };\n"; - } else { - f << ",\n"; - inc_indent(); - for (auto cell : init_cells) { - dump_attrs(cell); - RTLIL::Const data = cell->getPort(ID::DATA).as_const(); - size_t width = cell->getParam(ID::WIDTH).as_int(); - size_t words = cell->getParam(ID::WORDS).as_int(); - f << indent << "memory<" << memory->width << ">::init<" << words << "> { " - << stringf("%#x", cell->getPort(ID::ADDR).as_int()) << ", {"; - inc_indent(); - for (size_t n = 0; n < words; n++) { - if (n % 4 == 0) - f << "\n" << indent; - else - f << " "; - dump_const(data, width, n * width, /*fixed_width=*/true); - f << ","; - } - dec_indent(); - f << "\n" << indent << "}},\n"; - } - dec_indent(); - f << indent << "};\n"; - } - } - - void dump_eval_method(RTLIL::Module *module) - { - inc_indent(); - f << indent << "bool converged = " << (eval_converges.at(module) ? "true" : "false") << ";\n"; - if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) { - for (auto wire : module->wires()) { - if (edge_wires[wire]) { - for (auto edge_type : edge_types) { - if (edge_type.first.wire == wire) { - if (edge_type.second != RTLIL::STn) { - f << indent << "bool posedge_" << mangle(edge_type.first) << " = "; - f << "this->posedge_" << mangle(edge_type.first) << "();\n"; - } - if (edge_type.second != RTLIL::STp) { - f << indent << "bool negedge_" << mangle(edge_type.first) << " = "; - f << "this->negedge_" << mangle(edge_type.first) << "();\n"; - } - } - } - } - } - for (auto wire : module->wires()) - dump_wire(wire, /*is_local_context=*/true); - for (auto node : schedule[module]) { - switch (node.type) { - case FlowGraph::Node::Type::CONNECT: - dump_connect(node.connect); - break; - case FlowGraph::Node::Type::CELL_SYNC: - dump_cell_sync(node.cell); - break; - case FlowGraph::Node::Type::CELL_EVAL: - dump_cell_eval(node.cell); - break; - case FlowGraph::Node::Type::PROCESS: - dump_process(node.process); - break; - } - } - } - f << indent << "return converged;\n"; - dec_indent(); - } - - void dump_commit_method(RTLIL::Module *module) - { - inc_indent(); - f << indent << "bool changed = false;\n"; - for (auto wire : module->wires()) { - if (elided_wires.count(wire)) - continue; - if (unbuffered_wires[wire]) { - if (edge_wires[wire]) - f << indent << "prev_" << mangle(wire) << " = " << mangle(wire) << ";\n"; - continue; - } - if (!module->get_bool_attribute(ID(cxxrtl_blackbox)) || wire->port_id != 0) - f << indent << "changed |= " << mangle(wire) << ".commit();\n"; - } - if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) { - for (auto memory : module->memories) { - if (!writable_memories[memory.second]) - continue; - f << indent << "changed |= " << mangle(memory.second) << ".commit();\n"; - } - for (auto cell : module->cells()) { - if (is_internal_cell(cell->type)) - continue; - const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : "."; - f << indent << "changed |= " << mangle(cell) << access << "commit();\n"; - } - } - f << indent << "return changed;\n"; - dec_indent(); - } - - void dump_debug_info_method(RTLIL::Module *module) - { - size_t count_public_wires = 0; - size_t count_const_wires = 0; - size_t count_alias_wires = 0; - size_t count_member_wires = 0; - size_t count_skipped_wires = 0; - inc_indent(); - f << indent << "assert(path.empty() || path[path.size() - 1] == ' ');\n"; - for (auto wire : module->wires()) { - if (wire->name[0] != '\\') - continue; - if (module->get_bool_attribute(ID(cxxrtl_blackbox)) && (wire->port_id == 0)) - continue; - count_public_wires++; - if (debug_const_wires.count(wire)) { - // Wire tied to a constant - f << indent << "static const value<" << wire->width << "> const_" << mangle(wire) << " = "; - dump_const(debug_const_wires[wire]); - f << ";\n"; - f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); - f << ", debug_item(const_" << mangle(wire) << ", "; - f << wire->start_offset << "));\n"; - count_const_wires++; - } else if (debug_alias_wires.count(wire)) { - // Alias of a member wire - f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); - f << ", debug_item(debug_alias(), " << mangle(debug_alias_wires[wire]) << ", "; - f << wire->start_offset << "));\n"; - count_alias_wires++; - } else if (!localized_wires.count(wire)) { - // Member wire - f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); - f << ", debug_item(" << mangle(wire) << ", "; - f << wire->start_offset << "));\n"; - count_member_wires++; - } else { - count_skipped_wires++; - } - } - if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) { - for (auto &memory_it : module->memories) { - if (memory_it.first[0] != '\\') - continue; - f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(memory_it.second)); - f << ", debug_item(" << mangle(memory_it.second) << ", "; - f << memory_it.second->start_offset << "));\n"; - } - for (auto cell : module->cells()) { - if (is_internal_cell(cell->type)) - continue; - const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : "."; - f << indent << mangle(cell) << access << "debug_info(items, "; - f << "path + " << escape_cxx_string(get_hdl_name(cell) + ' ') << ");\n"; - } - } - dec_indent(); - - log_debug("Debug information statistics for module `%s':\n", log_id(module)); - log_debug(" Public wires: %zu, of which:\n", count_public_wires); - log_debug(" Const wires: %zu\n", count_const_wires); - log_debug(" Alias wires: %zu\n", count_alias_wires); - log_debug(" Member wires: %zu\n", count_member_wires); - log_debug(" Other wires: %zu (no debug information)\n", count_skipped_wires); - } - - void dump_metadata_map(const dict &metadata_map) - { - if (metadata_map.empty()) { - f << "metadata_map()"; - return; - } - f << "metadata_map({\n"; - inc_indent(); - for (auto metadata_item : metadata_map) { - if (!metadata_item.first.begins_with("\\")) - continue; - f << indent << "{ " << escape_cxx_string(metadata_item.first.str().substr(1)) << ", "; - if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) { - f << std::showpoint << std::stod(metadata_item.second.decode_string()) << std::noshowpoint; - } else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) { - f << escape_cxx_string(metadata_item.second.decode_string()); - } else { - f << metadata_item.second.as_int(/*is_signed=*/metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED); - if (!(metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED)) - f << "u"; - } - f << " },\n"; - } - dec_indent(); - f << indent << "})"; - } - - void dump_module_intf(RTLIL::Module *module) - { - dump_attrs(module); - if (module->get_bool_attribute(ID(cxxrtl_blackbox))) { - if (module->has_attribute(ID(cxxrtl_template))) - f << indent << "template" << template_params(module, /*is_decl=*/true) << "\n"; - f << indent << "struct " << mangle(module) << " : public module {\n"; - inc_indent(); - for (auto wire : module->wires()) { - if (wire->port_id != 0) - dump_wire(wire, /*is_local_context=*/false); - } - f << "\n"; - f << indent << "bool eval() override {\n"; - dump_eval_method(module); - f << indent << "}\n"; - f << "\n"; - f << indent << "bool commit() override {\n"; - dump_commit_method(module); - f << indent << "}\n"; - f << "\n"; - if (debug_info) { - f << indent << "void debug_info(debug_items &items, std::string path = \"\") override {\n"; - dump_debug_info_method(module); - f << indent << "}\n"; - f << "\n"; - } - f << indent << "static std::unique_ptr<" << mangle(module); - f << template_params(module, /*is_decl=*/false) << "> "; - f << "create(std::string name, metadata_map parameters, metadata_map attributes);\n"; - dec_indent(); - f << indent << "}; // struct " << mangle(module) << "\n"; - f << "\n"; - if (blackbox_specializations.count(module)) { - // If templated black boxes are used, the constructor of any module which includes the black box cell - // (which calls the declared but not defined in the generated code `create` function) may only be used - // if (a) the create function is defined in the same translation unit, or (b) the create function has - // a forward-declared explicit specialization. - // - // Option (b) makes it possible to have the generated code and the black box implementation in different - // translation units, which is convenient. Of course, its downside is that black boxes must predefine - // a specialization for every combination of parameters the generated code may use; but since the main - // purpose of templated black boxes is abstracting over datapath width, it is expected that there would - // be very few such combinations anyway. - for (auto specialization : blackbox_specializations[module]) { - f << indent << "template<>\n"; - f << indent << "std::unique_ptr<" << mangle(module) << specialization << "> "; - f << mangle(module) << specialization << "::"; - f << "create(std::string name, metadata_map parameters, metadata_map attributes);\n"; - f << "\n"; - } - } - } else { - f << indent << "struct " << mangle(module) << " : public module {\n"; - inc_indent(); - for (auto wire : module->wires()) - dump_wire(wire, /*is_local_context=*/false); - f << "\n"; - bool has_memories = false; - for (auto memory : module->memories) { - dump_memory(module, memory.second); - has_memories = true; - } - if (has_memories) - f << "\n"; - bool has_cells = false; - for (auto cell : module->cells()) { - if (is_internal_cell(cell->type)) - continue; - dump_attrs(cell); - RTLIL::Module *cell_module = module->design->module(cell->type); - log_assert(cell_module != nullptr); - if (cell_module->get_bool_attribute(ID(cxxrtl_blackbox))) { - f << indent << "std::unique_ptr<" << mangle(cell_module) << template_args(cell) << "> "; - f << mangle(cell) << " = " << mangle(cell_module) << template_args(cell); - f << "::create(" << escape_cxx_string(get_hdl_name(cell)) << ", "; - dump_metadata_map(cell->parameters); - f << ", "; - dump_metadata_map(cell->attributes); - f << ");\n"; - } else { - f << indent << mangle(cell_module) << " " << mangle(cell) << ";\n"; - } - has_cells = true; - } - if (has_cells) - f << "\n"; - f << indent << "bool eval() override;\n"; - f << indent << "bool commit() override;\n"; - if (debug_info) - f << indent << "void debug_info(debug_items &items, std::string path = \"\") override;\n"; - dec_indent(); - f << indent << "}; // struct " << mangle(module) << "\n"; - f << "\n"; - } - } - - void dump_module_impl(RTLIL::Module *module) - { - if (module->get_bool_attribute(ID(cxxrtl_blackbox))) - return; - f << indent << "bool " << mangle(module) << "::eval() {\n"; - dump_eval_method(module); - f << indent << "}\n"; - f << "\n"; - f << indent << "bool " << mangle(module) << "::commit() {\n"; - dump_commit_method(module); - f << indent << "}\n"; - f << "\n"; - if (debug_info) { - f << indent << "void " << mangle(module) << "::debug_info(debug_items &items, std::string path) {\n"; - dump_debug_info_method(module); - f << indent << "}\n"; - f << "\n"; - } - } - - void dump_design(RTLIL::Design *design) - { - RTLIL::Module *top_module = nullptr; - std::vector modules; - TopoSort topo_design; - for (auto module : design->modules()) { - if (!design->selected_module(module)) - continue; - if (module->get_bool_attribute(ID(cxxrtl_blackbox))) - modules.push_back(module); // cxxrtl blackboxes first - if (module->get_blackbox_attribute() || module->get_bool_attribute(ID(cxxrtl_blackbox))) - continue; - if (module->get_bool_attribute(ID::top)) - top_module = module; - - topo_design.node(module); - for (auto cell : module->cells()) { - if (is_internal_cell(cell->type) || is_cxxrtl_blackbox_cell(cell)) - continue; - RTLIL::Module *cell_module = design->module(cell->type); - log_assert(cell_module != nullptr); - topo_design.edge(cell_module, module); - } - } - bool no_loops = topo_design.sort(); - log_assert(no_loops); - modules.insert(modules.end(), topo_design.sorted.begin(), topo_design.sorted.end()); - - if (split_intf) { - // The only thing more depraved than include guards, is mangling filenames to turn them into include guards. - std::string include_guard = design_ns + "_header"; - std::transform(include_guard.begin(), include_guard.end(), include_guard.begin(), ::toupper); - - f << "#ifndef " << include_guard << "\n"; - f << "#define " << include_guard << "\n"; - f << "\n"; - if (top_module != nullptr && debug_info) { - f << "#include \n"; - f << "\n"; - f << "#ifdef __cplusplus\n"; - f << "extern \"C\" {\n"; - f << "#endif\n"; - f << "\n"; - f << "cxxrtl_toplevel " << design_ns << "_create();\n"; - f << "\n"; - f << "#ifdef __cplusplus\n"; - f << "}\n"; - f << "#endif\n"; - f << "\n"; - } else { - f << "// The CXXRTL C API is not available because the design is built without debug information.\n"; - f << "\n"; - } - f << "#ifdef __cplusplus\n"; - f << "\n"; - f << "#include \n"; - f << "\n"; - f << "using namespace cxxrtl;\n"; - f << "\n"; - f << "namespace " << design_ns << " {\n"; - f << "\n"; - for (auto module : modules) - dump_module_intf(module); - f << "} // namespace " << design_ns << "\n"; - f << "\n"; - f << "#endif // __cplusplus\n"; - f << "\n"; - f << "#endif\n"; - *intf_f << f.str(); f.str(""); - } - - if (split_intf) - f << "#include \"" << intf_filename << "\"\n"; - else - f << "#include \n"; - f << "\n"; - f << "#if defined(CXXRTL_INCLUDE_CAPI_IMPL) || \\\n"; - f << " defined(CXXRTL_INCLUDE_VCD_CAPI_IMPL)\n"; - f << "#include \n"; - f << "#endif\n"; - f << "\n"; - f << "#if defined(CXXRTL_INCLUDE_VCD_CAPI_IMPL)\n"; - f << "#include \n"; - f << "#endif\n"; - f << "\n"; - f << "using namespace cxxrtl_yosys;\n"; - f << "\n"; - f << "namespace " << design_ns << " {\n"; - f << "\n"; - for (auto module : modules) { - if (!split_intf) - dump_module_intf(module); - dump_module_impl(module); - } - f << "} // namespace " << design_ns << "\n"; - f << "\n"; - if (top_module != nullptr && debug_info) { - f << "cxxrtl_toplevel " << design_ns << "_create() {\n"; - inc_indent(); - std::string top_type = design_ns + "::" + mangle(top_module); - f << indent << "return new _cxxrtl_toplevel { "; - f << "std::unique_ptr<" << top_type << ">(new " + top_type + ")"; - f << " };\n"; - dec_indent(); - f << "}\n"; - } - - *impl_f << f.str(); f.str(""); - } - - // Edge-type sync rules require us to emit edge detectors, which require coordination between - // eval and commit phases. To do this we need to collect them upfront. - // - // Note that the simulator commit phase operates at wire granularity but edge-type sync rules - // operate at wire bit granularity; it is possible to have code similar to: - // wire [3:0] clocks; - // always @(posedge clocks[0]) ... - // To handle this we track edge sensitivity both for wires and wire bits. - void register_edge_signal(SigMap &sigmap, RTLIL::SigSpec signal, RTLIL::SyncType type) - { - signal = sigmap(signal); - log_assert(signal.is_wire() && signal.is_bit()); - log_assert(type == RTLIL::STp || type == RTLIL::STn || type == RTLIL::STe); - - RTLIL::SigBit sigbit = signal[0]; - if (!edge_types.count(sigbit)) - edge_types[sigbit] = type; - else if (edge_types[sigbit] != type) - edge_types[sigbit] = RTLIL::STe; - edge_wires.insert(signal.as_wire()); - } - - void analyze_design(RTLIL::Design *design) - { - bool has_feedback_arcs = false; - bool has_buffered_comb_wires = false; - - for (auto module : design->modules()) { - if (!design->selected_module(module)) - continue; - - SigMap &sigmap = sigmaps[module]; - sigmap.set(module); - - if (module->get_bool_attribute(ID(cxxrtl_blackbox))) { - for (auto port : module->ports) { - RTLIL::Wire *wire = module->wire(port); - if (wire->port_input && !wire->port_output) - unbuffered_wires.insert(wire); - if (wire->has_attribute(ID(cxxrtl_edge))) { - RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)]; - if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire)) - log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' is not a string with one character per bit.\n", - log_id(module), log_signal(wire)); - - std::string edges = wire->get_string_attribute(ID(cxxrtl_edge)); - for (int i = 0; i < GetSize(wire); i++) { - RTLIL::SigSpec wire_sig = wire; - switch (edges[i]) { - case '-': break; - case 'p': register_edge_signal(sigmap, wire_sig[i], RTLIL::STp); break; - case 'n': register_edge_signal(sigmap, wire_sig[i], RTLIL::STn); break; - case 'a': register_edge_signal(sigmap, wire_sig[i], RTLIL::STe); break; - default: - log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' contains specifiers " - "other than '-', 'p', 'n', or 'a'.\n", - log_id(module), log_signal(wire)); - } - } - } - } - - // Black boxes converge by default, since their implementations are quite unlikely to require - // internal propagation of comb signals. - eval_converges[module] = true; - continue; - } - - FlowGraph flow; - - for (auto conn : module->connections()) - flow.add_node(conn); - - dict memrw_cell_nodes; - dict, - pool> memwr_per_domain; - for (auto cell : module->cells()) { - if (!cell->known()) - log_cmd_error("Unknown cell `%s'.\n", log_id(cell->type)); - - RTLIL::Module *cell_module = design->module(cell->type); - if (cell_module && - cell_module->get_blackbox_attribute() && - !cell_module->get_bool_attribute(ID(cxxrtl_blackbox))) - log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", log_id(cell->type)); - - if (cell_module && - cell_module->get_bool_attribute(ID(cxxrtl_blackbox)) && - cell_module->get_bool_attribute(ID(cxxrtl_template))) - blackbox_specializations[cell_module].insert(template_args(cell)); - - FlowGraph::Node *node = flow.add_node(cell); - - // Various DFF cells are treated like posedge/negedge processes, see above for details. - if (cell->type.in(ID($dff), ID($dffe), ID($adff), ID($adffe), ID($dffsr), ID($dffsre), ID($sdff), ID($sdffe), ID($sdffce))) { - if (cell->getPort(ID::CLK).is_wire()) - register_edge_signal(sigmap, cell->getPort(ID::CLK), - cell->parameters[ID::CLK_POLARITY].as_bool() ? RTLIL::STp : RTLIL::STn); - } - // Similar for memory port cells. - if (cell->type.in(ID($memrd), ID($memwr))) { - if (cell->getParam(ID::CLK_ENABLE).as_bool()) { - if (cell->getPort(ID::CLK).is_wire()) - register_edge_signal(sigmap, cell->getPort(ID::CLK), - cell->parameters[ID::CLK_POLARITY].as_bool() ? RTLIL::STp : RTLIL::STn); - } - memrw_cell_nodes[cell] = node; - } - // Optimize access to read-only memories. - if (cell->type == ID($memwr)) - writable_memories.insert(module->memories[cell->getParam(ID::MEMID).decode_string()]); - // Collect groups of memory write ports in the same domain. - if (cell->type == ID($memwr) && cell->getParam(ID::CLK_ENABLE).as_bool() && cell->getPort(ID::CLK).is_wire()) { - RTLIL::SigBit clk_bit = sigmap(cell->getPort(ID::CLK))[0]; - const RTLIL::Memory *memory = module->memories[cell->getParam(ID::MEMID).decode_string()]; - memwr_per_domain[{clk_bit, memory}].insert(cell); - } - // Handling of packed memories is delegated to the `memory_unpack` pass, so we can rely on the presence - // of RTLIL memory objects and $memrd/$memwr/$meminit cells. - if (cell->type.in(ID($mem))) - log_assert(false); - } - for (auto cell : module->cells()) { - // Collect groups of memory write ports read by every transparent read port. - if (cell->type == ID($memrd) && cell->getParam(ID::CLK_ENABLE).as_bool() && cell->getPort(ID::CLK).is_wire() && - cell->getParam(ID::TRANSPARENT).as_bool()) { - RTLIL::SigBit clk_bit = sigmap(cell->getPort(ID::CLK))[0]; - const RTLIL::Memory *memory = module->memories[cell->getParam(ID::MEMID).decode_string()]; - for (auto memwr_cell : memwr_per_domain[{clk_bit, memory}]) { - transparent_for[cell].insert(memwr_cell); - // Our implementation of transparent $memrd cells reads \EN, \ADDR and \DATA from every $memwr cell - // in the same domain, which isn't directly visible in the netlist. Add these uses explicitly. - flow.add_uses(memrw_cell_nodes[cell], memwr_cell->getPort(ID::EN)); - flow.add_uses(memrw_cell_nodes[cell], memwr_cell->getPort(ID::ADDR)); - flow.add_uses(memrw_cell_nodes[cell], memwr_cell->getPort(ID::DATA)); - } - } - } - - for (auto proc : module->processes) { - flow.add_node(proc.second); - - for (auto sync : proc.second->syncs) - switch (sync->type) { - // Edge-type sync rules require pre-registration. - case RTLIL::STp: - case RTLIL::STn: - case RTLIL::STe: - register_edge_signal(sigmap, sync->signal, sync->type); - break; - - // Level-type sync rules require no special handling. - case RTLIL::ST0: - case RTLIL::ST1: - case RTLIL::STa: - break; - - case RTLIL::STg: - log_cmd_error("Global clock is not supported.\n"); - - // Handling of init-type sync rules is delegated to the `proc_init` pass, so we can use the wire - // attribute regardless of input. - case RTLIL::STi: - log_assert(false); - } - } - - for (auto wire : module->wires()) { - if (!flow.is_elidable(wire)) continue; - if (wire->port_id != 0) continue; - if (wire->get_bool_attribute(ID::keep)) continue; - if (wire->name.begins_with("$") && !elide_internal) continue; - if (wire->name.begins_with("\\") && !elide_public) continue; - if (edge_wires[wire]) continue; - log_assert(flow.wire_comb_defs[wire].size() == 1); - elided_wires[wire] = **flow.wire_comb_defs[wire].begin(); - } - - dict, hash_ptr_ops> node_defs; - for (auto wire_comb_def : flow.wire_comb_defs) - for (auto node : wire_comb_def.second) - node_defs[node].insert(wire_comb_def.first); - - Scheduler scheduler; - dict::Vertex*, hash_ptr_ops> node_map; - for (auto node : flow.nodes) - node_map[node] = scheduler.add(node); - for (auto node_def : node_defs) { - auto vertex = node_map[node_def.first]; - for (auto wire : node_def.second) - for (auto succ_node : flow.wire_uses[wire]) { - auto succ_vertex = node_map[succ_node]; - vertex->succs.insert(succ_vertex); - succ_vertex->preds.insert(vertex); - } - } - - auto eval_order = scheduler.schedule(); - pool evaluated; - pool feedback_wires; - for (auto vertex : eval_order) { - auto node = vertex->data; - schedule[module].push_back(*node); - // Any wire that is an output of node vo and input of node vi where vo is scheduled later than vi - // is a feedback wire. Feedback wires indicate apparent logic loops in the design, which may be - // caused by a true logic loop, but usually are a benign result of dependency tracking that works - // on wire, not bit, level. Nevertheless, feedback wires cannot be localized. - evaluated.insert(node); - for (auto wire : node_defs[node]) - for (auto succ_node : flow.wire_uses[wire]) - if (evaluated[succ_node]) { - feedback_wires.insert(wire); - // Feedback wires may never be elided because feedback requires state, but the point of elision - // (and localization) is to eliminate state. - elided_wires.erase(wire); - } - } - - if (!feedback_wires.empty()) { - has_feedback_arcs = true; - log("Module `%s' contains feedback arcs through wires:\n", log_id(module)); - for (auto wire : feedback_wires) - log(" %s\n", log_id(wire)); - } - - for (auto wire : module->wires()) { - if (feedback_wires[wire]) continue; - if (wire->port_output && !module->get_bool_attribute(ID::top)) continue; - if (wire->name.begins_with("$") && !unbuffer_internal) continue; - if (wire->name.begins_with("\\") && !unbuffer_public) continue; - if (flow.wire_sync_defs.count(wire) > 0) continue; - unbuffered_wires.insert(wire); - if (edge_wires[wire]) continue; - if (wire->get_bool_attribute(ID::keep)) continue; - if (wire->port_input || wire->port_output) continue; - if (wire->name.begins_with("$") && !localize_internal) continue; - if (wire->name.begins_with("\\") && !localize_public) continue; - localized_wires.insert(wire); - } - - // For maximum performance, the state of the simulation (which is the same as the set of its double buffered - // wires, since using a singly buffered wire for any kind of state introduces a race condition) should contain - // no wires attached to combinatorial outputs. Feedback wires, by definition, make that impossible. However, - // it is possible that a design with no feedback arcs would end up with doubly buffered wires in such cases - // as a wire with multiple drivers where one of them is combinatorial and the other is synchronous. Such designs - // also require more than one delta cycle to converge. - pool buffered_comb_wires; - for (auto wire : module->wires()) { - if (flow.wire_comb_defs[wire].size() > 0 && !unbuffered_wires[wire] && !feedback_wires[wire]) - buffered_comb_wires.insert(wire); - } - if (!buffered_comb_wires.empty()) { - has_buffered_comb_wires = true; - log("Module `%s' contains buffered combinatorial wires:\n", log_id(module)); - for (auto wire : buffered_comb_wires) - log(" %s\n", log_id(wire)); - } - - eval_converges[module] = feedback_wires.empty() && buffered_comb_wires.empty(); - - if (debug_info) { - // Find wires that alias other wires or are tied to a constant; debug information can be enriched with these - // at essentially zero additional cost. - // - // Note that the information collected here can't be used for optimizing the netlist: debug information queries - // are pure and run on a design in a stable state, which allows assumptions that do not otherwise hold. - for (auto wire : module->wires()) { - if (wire->name[0] != '\\') - continue; - if (!unbuffered_wires[wire]) - continue; - const RTLIL::Wire *wire_it = wire; - while (1) { - if (!(flow.wire_def_elidable.count(wire_it) && flow.wire_def_elidable[wire_it])) - break; // not an alias: complex def - log_assert(flow.wire_comb_defs[wire_it].size() == 1); - FlowGraph::Node *node = *flow.wire_comb_defs[wire_it].begin(); - if (node->type != FlowGraph::Node::Type::CONNECT) - break; // not an alias: def by cell - RTLIL::SigSpec rhs_sig = node->connect.second; - if (rhs_sig.is_wire()) { - RTLIL::Wire *rhs_wire = rhs_sig.as_wire(); - if (unbuffered_wires[rhs_wire]) { - wire_it = rhs_wire; // maybe an alias - } else { - debug_alias_wires[wire] = rhs_wire; // is an alias - break; - } - } else if (rhs_sig.is_fully_const()) { - debug_const_wires[wire] = rhs_sig.as_const(); // is a const - break; - } else { - break; // not an alias: complex rhs - } - } - } - } - } - if (has_feedback_arcs || has_buffered_comb_wires) { - // Although both non-feedback buffered combinatorial wires and apparent feedback wires may be eliminated - // by optimizing the design, if after `proc; flatten` there are any feedback wires remaining, it is very - // likely that these feedback wires are indicative of a true logic loop, so they get emphasized in the message. - const char *why_pessimistic = nullptr; - if (has_feedback_arcs) - why_pessimistic = "feedback wires"; - else if (has_buffered_comb_wires) - why_pessimistic = "buffered combinatorial wires"; - log_warning("Design contains %s, which require delta cycles during evaluation.\n", why_pessimistic); - if (!run_flatten) - log("Flattening may eliminate %s from the design.\n", why_pessimistic); - if (!run_proc) - log("Converting processes to netlists may eliminate %s from the design.\n", why_pessimistic); - } - } - - void check_design(RTLIL::Design *design, bool &has_sync_init, bool &has_packed_mem) - { - has_sync_init = has_packed_mem = false; - - for (auto module : design->modules()) { - if (module->get_blackbox_attribute() && !module->has_attribute(ID(cxxrtl_blackbox))) - continue; - - if (!design->selected_whole_module(module)) - if (design->selected_module(module)) - log_cmd_error("Can't handle partially selected module `%s'!\n", id2cstr(module->name)); - if (!design->selected_module(module)) - continue; - - for (auto proc : module->processes) - for (auto sync : proc.second->syncs) - if (sync->type == RTLIL::STi) - has_sync_init = true; - - for (auto cell : module->cells()) - if (cell->type == ID($mem)) - has_packed_mem = true; - } - } - - void prepare_design(RTLIL::Design *design) - { - bool did_anything = false; - bool has_sync_init, has_packed_mem; - log_push(); - check_design(design, has_sync_init, has_packed_mem); - if (run_flatten) { - Pass::call(design, "flatten"); - did_anything = true; - } - if (run_proc) { - Pass::call(design, "proc"); - did_anything = true; - } else if (has_sync_init) { - // We're only interested in proc_init, but it depends on proc_prune and proc_clean, so call those - // in case they weren't already. (This allows `yosys foo.v -o foo.cc` to work.) - Pass::call(design, "proc_prune"); - Pass::call(design, "proc_clean"); - Pass::call(design, "proc_init"); - did_anything = true; - } - if (has_packed_mem) { - Pass::call(design, "memory_unpack"); - did_anything = true; - } - // Recheck the design if it was modified. - if (has_sync_init || has_packed_mem) - check_design(design, has_sync_init, has_packed_mem); - log_assert(!(has_sync_init || has_packed_mem)); - log_pop(); - if (did_anything) - log_spacer(); - analyze_design(design); - } -}; - -struct CxxrtlBackend : public Backend { - static const int DEFAULT_OPT_LEVEL = 6; - static const int OPT_LEVEL_DEBUG = 4; - static const int DEFAULT_DEBUG_LEVEL = 1; - - CxxrtlBackend() : Backend("cxxrtl", "convert design to C++ RTL simulation") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" write_cxxrtl [options] [filename]\n"); - log("\n"); - log("Write C++ code that simulates the design. The generated code requires a driver\n"); - log("that instantiates the design, toggles its clock, and interacts with its ports.\n"); - log("\n"); - log("The following driver may be used as an example for a design with a single clock\n"); - log("driving rising edge triggered flip-flops:\n"); - log("\n"); - log(" #include \"top.cc\"\n"); - log("\n"); - log(" int main() {\n"); - log(" cxxrtl_design::p_top top;\n"); - log(" top.step();\n"); - log(" while (1) {\n"); - log(" /* user logic */\n"); - log(" top.p_clk.set(false);\n"); - log(" top.step();\n"); - log(" top.p_clk.set(true);\n"); - log(" top.step();\n"); - log(" }\n"); - log(" }\n"); - log("\n"); - log("Note that CXXRTL simulations, just like the hardware they are simulating, are\n"); - log("subject to race conditions. If, in the example above, the user logic would run\n"); - log("simultaneously with the rising edge of the clock, the design would malfunction.\n"); - log("\n"); - log("This backend supports replacing parts of the design with black boxes implemented\n"); - log("in C++. If a module marked as a CXXRTL black box, its implementation is ignored,\n"); - log("and the generated code consists only of an interface and a factory function.\n"); - log("The driver must implement the factory function that creates an implementation of\n"); - log("the black box, taking into account the parameters it is instantiated with.\n"); - log("\n"); - log("For example, the following Verilog code defines a CXXRTL black box interface for\n"); - log("a synchronous debug sink:\n"); - log("\n"); - log(" (* cxxrtl_blackbox *)\n"); - log(" module debug(...);\n"); - log(" (* cxxrtl_edge = \"p\" *) input clk;\n"); - log(" input en;\n"); - log(" input [7:0] i_data;\n"); - log(" (* cxxrtl_sync *) output [7:0] o_data;\n"); - log(" endmodule\n"); - log("\n"); - log("For this HDL interface, this backend will generate the following C++ interface:\n"); - log("\n"); - log(" struct bb_p_debug : public module {\n"); - log(" value<1> p_clk;\n"); - log(" bool posedge_p_clk() const { /* ... */ }\n"); - log(" value<1> p_en;\n"); - log(" value<8> p_i_data;\n"); - log(" wire<8> p_o_data;\n"); - log("\n"); - log(" bool eval() override;\n"); - log(" bool commit() override;\n"); - log("\n"); - log(" static std::unique_ptr\n"); - log(" create(std::string name, metadata_map parameters, metadata_map attributes);\n"); - log(" };\n"); - log("\n"); - log("The `create' function must be implemented by the driver. For example, it could\n"); - log("always provide an implementation logging the values to standard error stream:\n"); - log("\n"); - log(" namespace cxxrtl_design {\n"); - log("\n"); - log(" struct stderr_debug : public bb_p_debug {\n"); - log(" bool eval() override {\n"); - log(" if (posedge_p_clk() && p_en)\n"); - log(" fprintf(stderr, \"debug: %%02x\\n\", p_i_data.data[0]);\n"); - log(" p_o_data.next = p_i_data;\n"); - log(" return bb_p_debug::eval();\n"); - log(" }\n"); - log(" };\n"); - log("\n"); - log(" std::unique_ptr\n"); - log(" bb_p_debug::create(std::string name, cxxrtl::metadata_map parameters,\n"); - log(" cxxrtl::metadata_map attributes) {\n"); - log(" return std::make_unique();\n"); - log(" }\n"); - log("\n"); - log(" }\n"); - log("\n"); - log("For complex applications of black boxes, it is possible to parameterize their\n"); - log("port widths. For example, the following Verilog code defines a CXXRTL black box\n"); - log("interface for a configurable width debug sink:\n"); - log("\n"); - log(" (* cxxrtl_blackbox, cxxrtl_template = \"WIDTH\" *)\n"); - log(" module debug(...);\n"); - log(" parameter WIDTH = 8;\n"); - log(" (* cxxrtl_edge = \"p\" *) input clk;\n"); - log(" input en;\n"); - log(" (* cxxrtl_width = \"WIDTH\" *) input [WIDTH - 1:0] i_data;\n"); - log(" (* cxxrtl_width = \"WIDTH\" *) output [WIDTH - 1:0] o_data;\n"); - log(" endmodule\n"); - log("\n"); - log("For this parametric HDL interface, this backend will generate the following C++\n"); - log("interface (only the differences are shown):\n"); - log("\n"); - log(" template\n"); - log(" struct bb_p_debug : public module {\n"); - log(" // ...\n"); - log(" value p_i_data;\n"); - log(" wire p_o_data;\n"); - log(" // ...\n"); - log(" static std::unique_ptr>\n"); - log(" create(std::string name, metadata_map parameters, metadata_map attributes);\n"); - log(" };\n"); - log("\n"); - log("The `create' function must be implemented by the driver, specialized for every\n"); - log("possible combination of template parameters. (Specialization is necessary to\n"); - log("enable separate compilation of generated code and black box implementations.)\n"); - log("\n"); - log(" template\n"); - log(" struct stderr_debug : public bb_p_debug {\n"); - log(" // ...\n"); - log(" };\n"); - log("\n"); - log(" template<>\n"); - log(" std::unique_ptr>\n"); - log(" bb_p_debug<8>::create(std::string name, cxxrtl::metadata_map parameters,\n"); - log(" cxxrtl::metadata_map attributes) {\n"); - log(" return std::make_unique>();\n"); - log(" }\n"); - log("\n"); - log("The following attributes are recognized by this backend:\n"); - log("\n"); - log(" cxxrtl_blackbox\n"); - log(" only valid on modules. if specified, the module contents are ignored,\n"); - log(" and the generated code includes only the module interface and a factory\n"); - log(" function, which will be called to instantiate the module.\n"); - log("\n"); - log(" cxxrtl_edge\n"); - log(" only valid on inputs of black boxes. must be one of \"p\", \"n\", \"a\".\n"); - log(" if specified on signal `clk`, the generated code includes edge detectors\n"); - log(" `posedge_p_clk()` (if \"p\"), `negedge_p_clk()` (if \"n\"), or both (if\n"); - log(" \"a\"), simplifying implementation of clocked black boxes.\n"); - log("\n"); - log(" cxxrtl_template\n"); - log(" only valid on black boxes. must contain a space separated sequence of\n"); - log(" identifiers that have a corresponding black box parameters. for each\n"); - log(" of them, the generated code includes a `size_t` template parameter.\n"); - log("\n"); - log(" cxxrtl_width\n"); - log(" only valid on ports of black boxes. must be a constant expression, which\n"); - log(" is directly inserted into generated code.\n"); - log("\n"); - log(" cxxrtl_comb, cxxrtl_sync\n"); - log(" only valid on outputs of black boxes. if specified, indicates that every\n"); - log(" bit of the output port is driven, correspondingly, by combinatorial or\n"); - log(" synchronous logic. this knowledge is used for scheduling optimizations.\n"); - log(" if neither is specified, the output will be pessimistically treated as\n"); - log(" driven by both combinatorial and synchronous logic.\n"); - log("\n"); - log("The following options are supported by this backend:\n"); - log("\n"); - log(" -header\n"); - log(" generate separate interface (.h) and implementation (.cc) files.\n"); - log(" if specified, the backend must be called with a filename, and filename\n"); - log(" of the interface is derived from filename of the implementation.\n"); - log(" otherwise, interface and implementation are generated together.\n"); - log("\n"); - log(" -namespace \n"); - log(" place the generated code into namespace . if not specified,\n"); - log(" \"cxxrtl_design\" is used.\n"); - log("\n"); - log(" -noflatten\n"); - log(" don't flatten the design. fully flattened designs can evaluate within\n"); - log(" one delta cycle if they have no combinatorial feedback.\n"); - log(" note that the debug interface and waveform dumps use full hierarchical\n"); - log(" names for all wires even in flattened designs.\n"); - log("\n"); - log(" -noproc\n"); - log(" don't convert processes to netlists. in most designs, converting\n"); - log(" processes significantly improves evaluation performance at the cost of\n"); - log(" slight increase in compilation time.\n"); - log("\n"); - log(" -O \n"); - log(" set the optimization level. the default is -O%d. higher optimization\n", DEFAULT_OPT_LEVEL); - log(" levels dramatically decrease compile and run time, and highest level\n"); - log(" possible for a design should be used.\n"); - log("\n"); - log(" -O0\n"); - log(" no optimization.\n"); - log("\n"); - log(" -O1\n"); - log(" localize internal wires if possible.\n"); - log("\n"); - log(" -O2\n"); - log(" like -O1, and unbuffer internal wires if possible.\n"); - log("\n"); - log(" -O3\n"); - log(" like -O2, and elide internal wires if possible.\n"); - log("\n"); - log(" -O4\n"); - log(" like -O3, and unbuffer public wires not marked (*keep*) if possible.\n"); - log("\n"); - log(" -O5\n"); - log(" like -O4, and localize public wires not marked (*keep*) if possible.\n"); - log("\n"); - log(" -O6\n"); - log(" like -O5, and elide public wires not marked (*keep*) if possible.\n"); - log("\n"); - log(" -Og\n"); - log(" highest optimization level that provides debug information for all\n"); - log(" public wires. currently, alias for -O%d.\n", OPT_LEVEL_DEBUG); - log("\n"); - log(" -g \n"); - log(" set the debug level. the default is -g%d. higher debug levels provide\n", DEFAULT_DEBUG_LEVEL); - log(" more visibility and generate more code, but do not pessimize evaluation.\n"); - log("\n"); - log(" -g0\n"); - log(" no debug information.\n"); - log("\n"); - log(" -g1\n"); - log(" debug information for non-optimized public wires. this also makes it\n"); - log(" possible to use the C API.\n"); - log("\n"); - } - - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override - { - bool noflatten = false; - bool noproc = false; - int opt_level = DEFAULT_OPT_LEVEL; - int debug_level = DEFAULT_DEBUG_LEVEL; - CxxrtlWorker worker; - - log_header(design, "Executing CXXRTL backend.\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-noflatten") { - noflatten = true; - continue; - } - if (args[argidx] == "-noproc") { - noproc = true; - continue; - } - if (args[argidx] == "-Og") { - opt_level = OPT_LEVEL_DEBUG; - continue; - } - if (args[argidx] == "-O" && argidx+1 < args.size() && args[argidx+1] == "g") { - argidx++; - opt_level = OPT_LEVEL_DEBUG; - continue; - } - if (args[argidx] == "-O" && argidx+1 < args.size()) { - opt_level = std::stoi(args[++argidx]); - continue; - } - if (args[argidx].substr(0, 2) == "-O" && args[argidx].size() == 3 && isdigit(args[argidx][2])) { - opt_level = std::stoi(args[argidx].substr(2)); - continue; - } - if (args[argidx] == "-g" && argidx+1 < args.size()) { - debug_level = std::stoi(args[++argidx]); - continue; - } - if (args[argidx].substr(0, 2) == "-g" && args[argidx].size() == 3 && isdigit(args[argidx][2])) { - debug_level = std::stoi(args[argidx].substr(2)); - continue; - } - if (args[argidx] == "-header") { - worker.split_intf = true; - continue; - } - if (args[argidx] == "-namespace" && argidx+1 < args.size()) { - worker.design_ns = args[++argidx]; - continue; - } - break; - } - extra_args(f, filename, args, argidx); - - worker.run_flatten = !noflatten; - worker.run_proc = !noproc; - switch (opt_level) { - // the highest level here must match DEFAULT_OPT_LEVEL - case 6: - worker.elide_public = true; - YS_FALLTHROUGH - case 5: - worker.localize_public = true; - YS_FALLTHROUGH - case 4: - worker.unbuffer_public = true; - YS_FALLTHROUGH - case 3: - worker.elide_internal = true; - YS_FALLTHROUGH - case 2: - worker.localize_internal = true; - YS_FALLTHROUGH - case 1: - worker.unbuffer_internal = true; - YS_FALLTHROUGH - case 0: - break; - default: - log_cmd_error("Invalid optimization level %d.\n", opt_level); - } - switch (debug_level) { - // the highest level here must match DEFAULT_DEBUG_LEVEL - case 1: - worker.debug_info = true; - YS_FALLTHROUGH - case 0: - break; - default: - log_cmd_error("Invalid debug information level %d.\n", debug_level); - } - - std::ofstream intf_f; - if (worker.split_intf) { - if (filename == "") - log_cmd_error("Option -header must be used with a filename.\n"); - - worker.intf_filename = filename.substr(0, filename.rfind('.')) + ".h"; - intf_f.open(worker.intf_filename, std::ofstream::trunc); - if (intf_f.fail()) - log_cmd_error("Can't open file `%s' for writing: %s\n", - worker.intf_filename.c_str(), strerror(errno)); - - worker.intf_f = &intf_f; - } - worker.impl_f = f; - - worker.prepare_design(design); - worker.dump_design(design); - } -} CxxrtlBackend; - -PRIVATE_NAMESPACE_END diff --git a/backends/cxxrtl/cxxrtl_capi.cc b/backends/cxxrtl/cxxrtl_capi.cc deleted file mode 100644 index e0566e152ae..00000000000 --- a/backends/cxxrtl/cxxrtl_capi.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 whitequark - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted. - * - * 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. - * - */ - -// This file is a part of the CXXRTL C API. It should be used together with `cxxrtl_capi.h`. - -#include -#include - -struct _cxxrtl_handle { - std::unique_ptr module; - cxxrtl::debug_items objects; -}; - -// Private function for use by other units of the C API. -const cxxrtl::debug_items &cxxrtl_debug_items_from_handle(cxxrtl_handle handle) { - return handle->objects; -} - -cxxrtl_handle cxxrtl_create(cxxrtl_toplevel design) { - cxxrtl_handle handle = new _cxxrtl_handle; - handle->module = std::move(design->module); - handle->module->debug_info(handle->objects); - delete design; - return handle; -} - -void cxxrtl_destroy(cxxrtl_handle handle) { - delete handle; -} - -size_t cxxrtl_step(cxxrtl_handle handle) { - return handle->module->step(); -} - -struct cxxrtl_object *cxxrtl_get_parts(cxxrtl_handle handle, const char *name, size_t *parts) { - auto it = handle->objects.table.find(name); - if (it == handle->objects.table.end()) - return nullptr; - *parts = it->second.size(); - return static_cast(&it->second[0]); -} - -void cxxrtl_enum(cxxrtl_handle handle, void *data, - void (*callback)(void *data, const char *name, - cxxrtl_object *object, size_t parts)) { - for (auto &it : handle->objects.table) - callback(data, it.first.c_str(), static_cast(&it.second[0]), it.second.size()); -} diff --git a/backends/cxxrtl/cxxrtl_capi.h b/backends/cxxrtl/cxxrtl_capi.h deleted file mode 100644 index 599284898c0..00000000000 --- a/backends/cxxrtl/cxxrtl_capi.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 whitequark - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted. - * - * 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. - * - */ - -#ifndef CXXRTL_CAPI_H -#define CXXRTL_CAPI_H - -// This file is a part of the CXXRTL C API. It should be used together with `cxxrtl_capi.cc`. -// -// The CXXRTL C API makes it possible to drive CXXRTL designs using C or any other language that -// supports the C ABI, for example, Python. It does not provide a way to implement black boxes. - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// Opaque reference to a design toplevel. -// -// A design toplevel can only be used to create a design handle. -typedef struct _cxxrtl_toplevel *cxxrtl_toplevel; - -// The constructor for a design toplevel is provided as a part of generated code for that design. -// Its prototype matches: -// -// cxxrtl_toplevel _create(); - -// Opaque reference to a design handle. -// -// A design handle is required by all operations in the C API. -typedef struct _cxxrtl_handle *cxxrtl_handle; - -// Create a design handle from a design toplevel. -// -// The `design` is consumed by this operation and cannot be used afterwards. -cxxrtl_handle cxxrtl_create(cxxrtl_toplevel design); - -// Release all resources used by a design and its handle. -void cxxrtl_destroy(cxxrtl_handle handle); - -// Simulate the design to a fixed point. -// -// Returns the number of delta cycles. -size_t cxxrtl_step(cxxrtl_handle handle); - -// Type of a simulated object. -enum cxxrtl_type { - // Values correspond to singly buffered netlist nodes, i.e. nodes driven exclusively by - // combinatorial cells, or toplevel input nodes. - // - // Values can be inspected via the `curr` pointer. If the `next` pointer is NULL, the value is - // driven by a constant and can never be modified. Otherwise, the value can be modified through - // the `next` pointer (which is equal to `curr` if not NULL). Note that changes to the bits - // driven by combinatorial cells will be ignored. - // - // Values always have depth 1. - CXXRTL_VALUE = 0, - - // Wires correspond to doubly buffered netlist nodes, i.e. nodes driven, at least in part, by - // storage cells, or by combinatorial cells that are a part of a feedback path. - // - // Wires can be inspected via the `curr` pointer and modified via the `next` pointer (which are - // distinct for wires). Note that changes to the bits driven by combinatorial cells will be - // ignored. - // - // Wires always have depth 1. - CXXRTL_WIRE = 1, - - // Memories correspond to memory cells. - // - // Memories can be inspected and modified via the `curr` pointer. Due to a limitation of this - // API, memories cannot yet be modified in a guaranteed race-free way, and the `next` pointer is - // always NULL. - CXXRTL_MEMORY = 2, - - // Aliases correspond to netlist nodes driven by another node such that their value is always - // exactly equal, or driven by a constant value. - // - // Aliases can be inspected via the `curr` pointer. They cannot be modified, and the `next` - // pointer is always NULL. - CXXRTL_ALIAS = 3, - - // More object types may be added in the future, but the existing ones will never change. -}; - -// Description of a simulated object. -// -// The `data` array can be accessed directly to inspect and, if applicable, modify the bits -// stored in the object. -struct cxxrtl_object { - // Type of the object. - // - // All objects have the same memory layout determined by `width` and `depth`, but the type - // determines all other properties of the object. - uint32_t type; // actually `enum cxxrtl_type` - - // Width of the object in bits. - size_t width; - - // Index of the least significant bit. - size_t lsb_at; - - // Depth of the object. Only meaningful for memories; for other objects, always 1. - size_t depth; - - // Index of the first word. Only meaningful for memories; for other objects, always 0; - size_t zero_at; - - // Bits stored in the object, as 32-bit chunks, least significant bits first. - // - // The width is rounded up to a multiple of 32; the padding bits are always set to 0 by - // the simulation code, and must be always written as 0 when modified by user code. - // In memories, every element is stored contiguously. Therefore, the total number of chunks - // in any object is `((width + 31) / 32) * depth`. - // - // To allow the simulation to be partitioned into multiple independent units communicating - // through wires, the bits are double buffered. To avoid race conditions, user code should - // always read from `curr` and write to `next`. The `curr` pointer is always valid; for objects - // that cannot be modified, or cannot be modified in a race-free way, `next` is NULL. - uint32_t *curr; - uint32_t *next; - - // More description fields may be added in the future, but the existing ones will never change. -}; - -// Retrieve description of a simulated object. -// -// The `name` is the full hierarchical name of the object in the Yosys notation, where public names -// have a `\` prefix and hierarchy levels are separated by single spaces. For example, if -// the top-level module instantiates a module `foo`, which in turn contains a wire `bar`, the full -// hierarchical name is `\foo \bar`. -// -// The storage of a single abstract object may be split (usually with the `splitnets` pass) into -// many physical parts, all of which correspond to the same hierarchical name. To handle such cases, -// this function returns an array and writes its length to `parts`. The array is sorted by `lsb_at`. -// -// Returns the object parts if it was found, NULL otherwise. The returned parts are valid until -// the design is destroyed. -struct cxxrtl_object *cxxrtl_get_parts(cxxrtl_handle handle, const char *name, size_t *parts); - -// Retrieve description of a single part simulated object. -// -// This function is a shortcut for the most common use of `cxxrtl_get_parts`. It asserts that, -// if the object exists, it consists of a single part. If assertions are disabled, it returns NULL -// for multi-part objects. -inline struct cxxrtl_object *cxxrtl_get(cxxrtl_handle handle, const char *name) { - size_t parts = 0; - struct cxxrtl_object *object = cxxrtl_get_parts(handle, name, &parts); - assert(object == NULL || parts == 1); - if (object == NULL || parts == 1) - return object; - return NULL; -} - -// Enumerate simulated objects. -// -// For every object in the simulation, `callback` is called with the provided `data`, the full -// hierarchical name of the object (see `cxxrtl_get` for details), and the object parts. -// The provided `name` and `object` values are valid until the design is destroyed. -void cxxrtl_enum(cxxrtl_handle handle, void *data, - void (*callback)(void *data, const char *name, - struct cxxrtl_object *object, size_t parts)); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/backends/cxxrtl/cxxrtl_vcd.h b/backends/cxxrtl/cxxrtl_vcd.h deleted file mode 100644 index dbeabbaf2d8..00000000000 --- a/backends/cxxrtl/cxxrtl_vcd.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 whitequark - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted. - * - * 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. - * - */ - -#ifndef CXXRTL_VCD_H -#define CXXRTL_VCD_H - -#include - -namespace cxxrtl { - -class vcd_writer { - struct variable { - size_t ident; - size_t width; - chunk_t *curr; - size_t prev_off; - }; - - std::vector current_scope; - std::vector variables; - std::vector cache; - std::map aliases; - bool streaming = false; - - void emit_timescale(unsigned number, const std::string &unit) { - assert(!streaming); - assert(number == 1 || number == 10 || number == 100); - assert(unit == "s" || unit == "ms" || unit == "us" || - unit == "ns" || unit == "ps" || unit == "fs"); - buffer += "$timescale " + std::to_string(number) + " " + unit + " $end\n"; - } - - void emit_scope(const std::vector &scope) { - assert(!streaming); - while (current_scope.size() > scope.size() || - (current_scope.size() > 0 && - current_scope[current_scope.size() - 1] != scope[current_scope.size() - 1])) { - buffer += "$upscope $end\n"; - current_scope.pop_back(); - } - while (current_scope.size() < scope.size()) { - buffer += "$scope module " + scope[current_scope.size()] + " $end\n"; - current_scope.push_back(scope[current_scope.size()]); - } - } - - void emit_ident(size_t ident) { - do { - buffer += '!' + ident % 94; // "base94" - ident /= 94; - } while (ident != 0); - } - - void emit_var(const variable &var, const std::string &type, const std::string &name, - size_t lsb_at, bool multipart) { - assert(!streaming); - buffer += "$var " + type + " " + std::to_string(var.width) + " "; - emit_ident(var.ident); - buffer += " " + name; - if (multipart || name.back() == ']' || lsb_at != 0) { - if (var.width == 1) - buffer += " [" + std::to_string(lsb_at) + "]"; - else - buffer += " [" + std::to_string(lsb_at + var.width - 1) + ":" + std::to_string(lsb_at) + "]"; - } - buffer += " $end\n"; - } - - void emit_enddefinitions() { - assert(!streaming); - buffer += "$enddefinitions $end\n"; - streaming = true; - } - - void emit_time(uint64_t timestamp) { - assert(streaming); - buffer += "#" + std::to_string(timestamp) + "\n"; - } - - void emit_scalar(const variable &var) { - assert(streaming); - assert(var.width == 1); - buffer += (*var.curr ? '1' : '0'); - emit_ident(var.ident); - buffer += '\n'; - } - - void emit_vector(const variable &var) { - assert(streaming); - buffer += 'b'; - for (size_t bit = var.width - 1; bit != (size_t)-1; bit--) { - bool bit_curr = var.curr[bit / (8 * sizeof(chunk_t))] & (1 << (bit % (8 * sizeof(chunk_t)))); - buffer += (bit_curr ? '1' : '0'); - } - buffer += ' '; - emit_ident(var.ident); - buffer += '\n'; - } - - const variable ®ister_variable(size_t width, chunk_t *curr, bool constant = false) { - if (aliases.count(curr)) { - return variables[aliases[curr]]; - } else { - const size_t chunks = (width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8); - aliases[curr] = variables.size(); - if (constant) { - variables.emplace_back(variable { variables.size(), width, curr, (size_t)-1 }); - } else { - variables.emplace_back(variable { variables.size(), width, curr, cache.size() }); - cache.insert(cache.end(), &curr[0], &curr[chunks]); - } - return variables.back(); - } - } - - bool test_variable(const variable &var) { - if (var.prev_off == (size_t)-1) - return false; // constant - const size_t chunks = (var.width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8); - if (std::equal(&var.curr[0], &var.curr[chunks], &cache[var.prev_off])) { - return false; - } else { - std::copy(&var.curr[0], &var.curr[chunks], &cache[var.prev_off]); - return true; - } - } - - static std::vector split_hierarchy(const std::string &hier_name) { - std::vector hierarchy; - size_t prev = 0; - while (true) { - size_t curr = hier_name.find_first_of(' ', prev); - if (curr == std::string::npos) { - hierarchy.push_back(hier_name.substr(prev)); - break; - } else { - hierarchy.push_back(hier_name.substr(prev, curr - prev)); - prev = curr + 1; - } - } - return hierarchy; - } - -public: - std::string buffer; - - void timescale(unsigned number, const std::string &unit) { - emit_timescale(number, unit); - } - - void add(const std::string &hier_name, const debug_item &item, bool multipart = false) { - std::vector scope = split_hierarchy(hier_name); - std::string name = scope.back(); - scope.pop_back(); - - emit_scope(scope); - switch (item.type) { - // Not the best naming but oh well... - case debug_item::VALUE: - emit_var(register_variable(item.width, item.curr, /*constant=*/item.next == nullptr), - "wire", name, item.lsb_at, multipart); - break; - case debug_item::WIRE: - emit_var(register_variable(item.width, item.curr), - "reg", name, item.lsb_at, multipart); - break; - case debug_item::MEMORY: { - const size_t stride = (item.width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8); - for (size_t index = 0; index < item.depth; index++) { - chunk_t *nth_curr = &item.curr[stride * index]; - std::string nth_name = name + '[' + std::to_string(index) + ']'; - emit_var(register_variable(item.width, nth_curr), - "reg", nth_name, item.lsb_at, multipart); - } - break; - } - case debug_item::ALIAS: - // Like VALUE, but, even though `item.next == nullptr` always holds, the underlying value - // can actually change, and must be tracked. In most cases the VCD identifier will be - // unified with the aliased reg, but we should handle the case where only the alias is - // added to the VCD writer, too. - emit_var(register_variable(item.width, item.curr), - "wire", name, item.lsb_at, multipart); - break; - } - } - - template - void add(const debug_items &items, const Filter &filter) { - // `debug_items` is a map, so the items are already sorted in an order optimal for emitting - // VCD scope sections. - for (auto &it : items.table) - for (auto &part : it.second) - if (filter(it.first, part)) - add(it.first, part, it.second.size() > 1); - } - - void add(const debug_items &items) { - this->template add(items, [](const std::string &, const debug_item &) { - return true; - }); - } - - void add_without_memories(const debug_items &items) { - this->template add(items, [](const std::string &, const debug_item &item) { - return item.type != debug_item::MEMORY; - }); - } - - void sample(uint64_t timestamp) { - bool first_sample = !streaming; - if (first_sample) { - emit_scope({}); - emit_enddefinitions(); - } - emit_time(timestamp); - for (auto var : variables) - if (test_variable(var) || first_sample) { - if (var.width == 1) - emit_scalar(var); - else - emit_vector(var); - } - } -}; - -} - -#endif diff --git a/backends/cxxrtl/cxxrtl_vcd_capi.cc b/backends/cxxrtl/cxxrtl_vcd_capi.cc deleted file mode 100644 index 52a9198b869..00000000000 --- a/backends/cxxrtl/cxxrtl_vcd_capi.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 whitequark - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted. - * - * 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. - * - */ - -// This file is a part of the CXXRTL C API. It should be used together with `cxxrtl_vcd_capi.h`. - -#include -#include - -extern const cxxrtl::debug_items &cxxrtl_debug_items_from_handle(cxxrtl_handle handle); - -struct _cxxrtl_vcd { - cxxrtl::vcd_writer writer; - bool flush = false; -}; - -cxxrtl_vcd cxxrtl_vcd_create() { - return new _cxxrtl_vcd; -} - -void cxxrtl_vcd_destroy(cxxrtl_vcd vcd) { - delete vcd; -} - -void cxxrtl_vcd_timescale(cxxrtl_vcd vcd, int number, const char *unit) { - vcd->writer.timescale(number, unit); -} - -void cxxrtl_vcd_add(cxxrtl_vcd vcd, const char *name, cxxrtl_object *object) { - // Note the copy. We don't know whether `object` came from a design (in which case it is - // an instance of `debug_item`), or from user code (in which case it is an instance of - // `cxxrtl_object`), so casting the pointer wouldn't be safe. - vcd->writer.add(name, cxxrtl::debug_item(*object)); -} - -void cxxrtl_vcd_add_from(cxxrtl_vcd vcd, cxxrtl_handle handle) { - vcd->writer.add(cxxrtl_debug_items_from_handle(handle)); -} - -void cxxrtl_vcd_add_from_if(cxxrtl_vcd vcd, cxxrtl_handle handle, void *data, - int (*filter)(void *data, const char *name, - const cxxrtl_object *object)) { - vcd->writer.add(cxxrtl_debug_items_from_handle(handle), - [=](const std::string &name, const cxxrtl::debug_item &item) { - return filter(data, name.c_str(), static_cast(&item)); - }); -} - -void cxxrtl_vcd_add_from_without_memories(cxxrtl_vcd vcd, cxxrtl_handle handle) { - vcd->writer.add_without_memories(cxxrtl_debug_items_from_handle(handle)); -} - -void cxxrtl_vcd_sample(cxxrtl_vcd vcd, uint64_t time) { - if (vcd->flush) { - vcd->writer.buffer.clear(); - vcd->flush = false; - } - vcd->writer.sample(time); -} - -void cxxrtl_vcd_read(cxxrtl_vcd vcd, const char **data, size_t *size) { - if (vcd->flush) { - vcd->writer.buffer.clear(); - vcd->flush = false; - } - *data = vcd->writer.buffer.c_str(); - *size = vcd->writer.buffer.size(); - vcd->flush = true; -} diff --git a/backends/cxxrtl/cxxrtl_vcd_capi.h b/backends/cxxrtl/cxxrtl_vcd_capi.h deleted file mode 100644 index d55afe2230e..00000000000 --- a/backends/cxxrtl/cxxrtl_vcd_capi.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 whitequark - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted. - * - * 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. - * - */ - -#ifndef CXXRTL_VCD_CAPI_H -#define CXXRTL_VCD_CAPI_H - -// This file is a part of the CXXRTL C API. It should be used together with `cxxrtl_vcd_capi.cc`. -// -// The CXXRTL C API for VCD writing makes it possible to insert virtual probes into designs and -// dump waveforms to Value Change Dump files. - -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// Opaque reference to a VCD writer. -typedef struct _cxxrtl_vcd *cxxrtl_vcd; - -// Create a VCD writer. -cxxrtl_vcd cxxrtl_vcd_create(); - -// Release all resources used by a VCD writer. -void cxxrtl_vcd_destroy(cxxrtl_vcd vcd); - -// Set VCD timescale. -// -// The `number` must be 1, 10, or 100, and the `unit` must be one of `"s"`, `"ms"`, `"us"`, `"ns"`, -// `"ps"`, or `"fs"`. -// -// Timescale can only be set before the first call to `cxxrtl_vcd_sample`. -void cxxrtl_vcd_timescale(cxxrtl_vcd vcd, int number, const char *unit); - -// Schedule a specific CXXRTL object to be sampled. -// -// The `name` is a full hierarchical name as described for `cxxrtl_get`; it does not need to match -// the original name of `object`, if any. The `object` must outlive the VCD writer, but there are -// no other requirements; if desired, it can be provided by user code, rather than come from -// a design. -// -// Objects can only be scheduled before the first call to `cxxrtl_vcd_sample`. -void cxxrtl_vcd_add(cxxrtl_vcd vcd, const char *name, struct cxxrtl_object *object); - -// Schedule all CXXRTL objects in a simulation. -// -// The design `handle` must outlive the VCD writer. -// -// Objects can only be scheduled before the first call to `cxxrtl_vcd_sample`. -void cxxrtl_vcd_add_from(cxxrtl_vcd vcd, cxxrtl_handle handle); - -// Schedule CXXRTL objects in a simulation that match a given predicate. -// -// For every object in the simulation, `filter` is called with the provided `data`, the full -// hierarchical name of the object (see `cxxrtl_get` for details), and the object description. -// The object will be sampled if the predicate returns a non-zero value. -// -// Objects can only be scheduled before the first call to `cxxrtl_vcd_sample`. -void cxxrtl_vcd_add_from_if(cxxrtl_vcd vcd, cxxrtl_handle handle, void *data, - int (*filter)(void *data, const char *name, - const struct cxxrtl_object *object)); - -// Schedule all CXXRTL objects in a simulation except for memories. -// -// The design `handle` must outlive the VCD writer. -// -// Objects can only be scheduled before the first call to `cxxrtl_vcd_sample`. -void cxxrtl_vcd_add_from_without_memories(cxxrtl_vcd vcd, cxxrtl_handle handle); - -// Sample all scheduled objects. -// -// First, `time` is written to the internal buffer. Second, the values of every signal changed since -// the previous call to `cxxrtl_vcd_sample` (all values if this is the first call) are written to -// the internal buffer. The contents of the buffer can be retrieved with `cxxrtl_vcd_read`. -void cxxrtl_vcd_sample(cxxrtl_vcd vcd, uint64_t time); - -// Retrieve buffered VCD data. -// -// The pointer to the start of the next chunk of VCD data is assigned to `*data`, and the length -// of that chunk is assigned to `*size`. The pointer to the data is valid until the next call to -// `cxxrtl_vcd_sample` or `cxxrtl_vcd_read`. Once all of the buffered data has been retrieved, -// this function will always return zero sized chunks. -void cxxrtl_vcd_read(cxxrtl_vcd vcd, const char **data, size_t *size); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 5e6becfd03d..6d9469538eb 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -90,7 +90,7 @@ struct EdifNames struct EdifBackend : public Backend { EdifBackend() : Backend("edif", "write design to EDIF netlist file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -113,9 +113,6 @@ struct EdifBackend : public Backend { log(" -attrprop\n"); log(" create EDIF properties for cell attributes\n"); log("\n"); - log(" -keep\n"); - log(" create extra KEEP nets by allowing a cell to drive multiple nets.\n"); - log("\n"); log(" -pvector {par|bra|ang}\n"); log(" sets the delimiting character for module port rename clauses to\n"); log(" parentheses, square brackets, or angle brackets.\n"); @@ -126,14 +123,14 @@ struct EdifBackend : public Backend { log("is targeted.\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing EDIF backend.\n"); std::string top_module_name; bool port_rename = false; bool attr_properties = false; std::map> lib_cell_ports; - bool nogndvcc = false, gndvccy = false, keepmode = false; + bool nogndvcc = false, gndvccy = false; CellTypes ct(design); EdifNames edif_names; @@ -156,10 +153,6 @@ struct EdifBackend : public Backend { attr_properties = true; continue; } - if (args[argidx] == "-keep") { - keepmode = true; - continue; - } if (args[argidx] == "-pvector" && argidx+1 < args.size()) { std::string parray; port_rename = true; @@ -178,12 +171,13 @@ struct EdifBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto module : design->modules()) - if (module->get_bool_attribute(ID::top)) - top_module_name = module->name.str(); + for (auto & mod_it:design->modules_) + if (mod_it.second->get_bool_attribute("\\top")) + top_module_name = mod_it.first.str(); - for (auto module : design->modules()) + for (auto module_it : design->modules_) { + RTLIL::Module *module = module_it.second; if (module->get_blackbox_attribute()) continue; @@ -191,13 +185,14 @@ struct EdifBackend : public Backend { top_module_name = module->name.str(); if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", log_id(module->name)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name)); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", log_id(module->name)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name)); - for (auto cell : module->cells()) + for (auto cell_it : module->cells_) { - if (design->module(cell->type) == nullptr || design->module(cell->type)->get_blackbox_attribute()) { + RTLIL::Cell *cell = cell_it.second; + if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_blackbox_attribute()) { lib_cell_ports[cell->type]; for (auto p : cell->connections()) lib_cell_ports[cell->type][p.first] = GetSize(p.second); @@ -251,25 +246,19 @@ struct EdifBackend : public Backend { else if (!ct.cell_input(cell_it.first, port_it.first)) dir = "OUTPUT"; } - int width = port_it.second; - int start = 0; - bool upto = false; - auto m = design->module(cell_it.first); - if (m) { - auto w = m->wire(port_it.first); - if (w) { - width = GetSize(w); - start = w->start_offset; - upto = w->upto; - } - } - if (width == 1) + if (port_it.second == 1) *f << stringf(" (port %s (direction %s))\n", EDIF_DEF(port_it.first), dir); else { - int b[2]; - b[upto ? 0 : 1] = start; - b[upto ? 1 : 0] = start+width-1; - *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEFR(port_it.first, port_rename, b[0], b[1]), width, dir); + int b[2] = {port_it.second-1, 0}; + auto m = design->module(cell_it.first); + if (m) { + auto w = m->wire(port_it.first); + if (w) { + b[w->upto ? 0 : 1] = w->start_offset; + b[w->upto ? 1 : 0] = w->start_offset+GetSize(w)-1; + } + } + *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEFR(port_it.first, port_rename, b[0], b[1]), port_it.second, dir); } } *f << stringf(" )\n"); @@ -282,11 +271,11 @@ struct EdifBackend : public Backend { // extract module dependencies std::map> module_deps; - for (auto module : design->modules()) { - module_deps[module] = std::set(); - for (auto cell : module->cells()) - if (design->module(cell->type) != nullptr) - module_deps[module].insert(design->module(cell->type)); + for (auto &mod_it : design->modules_) { + module_deps[mod_it.second] = std::set(); + for (auto &cell_it : mod_it.second->cells_) + if (design->modules_.count(cell_it.second->type) > 0) + module_deps[mod_it.second].insert(design->modules_.at(cell_it.second->type)); } // simple good-enough topological sort @@ -297,12 +286,12 @@ struct EdifBackend : public Backend { for (auto &dep : it.second) if (module_deps.count(dep) > 0) goto not_ready_yet; - // log("Next in topological sort: %s\n", log_id(it.first->name)); + // log("Next in topological sort: %s\n", RTLIL::id2cstr(it.first->name)); sorted_modules.push_back(it.first); not_ready_yet:; } if (sorted_modules_idx == sorted_modules.size()) - log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name)); + log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", RTLIL::id2cstr(module_deps.begin()->first->name)); while (sorted_modules_idx < sorted_modules.size()) module_deps.erase(sorted_modules.at(sorted_modules_idx++)); } @@ -311,105 +300,21 @@ struct EdifBackend : public Backend { *f << stringf(" (library DESIGN\n"); *f << stringf(" (edifLevel 0)\n"); *f << stringf(" (technology (numberDefinition))\n"); - - auto add_prop = [&](IdString name, Const val) { - if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) - *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str()); - else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def()) - *f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int()); - else { - std::string hex_string = ""; - for (size_t i = 0; i < val.bits.size(); i += 4) { - int digit_value = 0; - if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; - if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; - if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; - if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; - char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; - hex_string = std::string(digit_str) + hex_string; - } - *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str()); - } - }; for (auto module : sorted_modules) { if (module->get_blackbox_attribute()) continue; SigMap sigmap(module); - std::map>> net_join_db; + std::map> net_join_db; *f << stringf(" (cell %s\n", EDIF_DEF(module->name)); *f << stringf(" (cellType GENERIC)\n"); *f << stringf(" (view VIEW_NETLIST\n"); *f << stringf(" (viewType NETLIST)\n"); *f << stringf(" (interface\n"); - - for (auto cell : module->cells()) { - for (auto &conn : cell->connections()) - if (cell->output(conn.first)) - sigmap.add(conn.second); - } - - for (auto wire : module->wires()) - for (auto b1 : SigSpec(wire)) - { - auto b2 = sigmap(b1); - - if (b1 == b2 || !b2.wire) - continue; - - log_assert(b1.wire != nullptr); - - Wire *w1 = b1.wire; - Wire *w2 = b2.wire; - - { - int c1 = w1->get_bool_attribute(ID::keep); - int c2 = w2->get_bool_attribute(ID::keep); - - if (c1 > c2) goto promote; - if (c1 < c2) goto nopromote; - } - - { - int c1 = w1->name[0] == '\\'; - int c2 = w2->name[0] == '\\'; - - if (c1 > c2) goto promote; - if (c1 < c2) goto nopromote; - } - - { - auto count_nontrivial_attr = [](Wire *w) { - int count = w->attributes.size(); - count -= w->attributes.count(ID::src); - count -= w->attributes.count(ID::unused_bits); - return count; - }; - - int c1 = count_nontrivial_attr(w1); - int c2 = count_nontrivial_attr(w2); - - if (c1 > c2) goto promote; - if (c1 < c2) goto nopromote; - } - - { - int c1 = w1->port_id ? INT_MAX - w1->port_id : 0; - int c2 = w2->port_id ? INT_MAX - w2->port_id : 0; - - if (c1 > c2) goto promote; - if (c1 < c2) goto nopromote; - } - - nopromote: - if (0) - promote: - sigmap.add(b1); - } - - for (auto wire : module->wires()) { + for (auto &wire_it : module->wires_) { + RTLIL::Wire *wire = wire_it.second; if (wire->port_id == 0) continue; const char *dir = "INOUT"; @@ -418,42 +323,52 @@ struct EdifBackend : public Backend { else if (!wire->port_input) dir = "OUTPUT"; if (wire->width == 1) { - *f << stringf(" (port %s (direction %s)", EDIF_DEF(wire->name), dir); - if (attr_properties) - for (auto &p : wire->attributes) - add_prop(p.first, p.second); - *f << ")\n"; + *f << stringf(" (port %s (direction %s))\n", EDIF_DEF(wire->name), dir); RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire)); - net_join_db[sig].insert(make_pair(stringf("(portRef %s)", EDIF_REF(wire->name)), wire->port_input)); + net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name))); } else { int b[2]; b[wire->upto ? 0 : 1] = wire->start_offset; b[wire->upto ? 1 : 0] = wire->start_offset + GetSize(wire) - 1; - *f << stringf(" (port (array %s %d) (direction %s)", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir); - if (attr_properties) - for (auto &p : wire->attributes) - add_prop(p.first, p.second); - - *f << ")\n"; + *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir); for (int i = 0; i < wire->width; i++) { RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, i)); - net_join_db[sig].insert(make_pair(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), GetSize(wire)-i-1), wire->port_input)); + net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), GetSize(wire)-i-1)); } } } - *f << stringf(" )\n"); *f << stringf(" (contents\n"); - if (!nogndvcc) { *f << stringf(" (instance GND (viewRef VIEW_NETLIST (cellRef GND (libraryRef LIB))))\n"); *f << stringf(" (instance VCC (viewRef VIEW_NETLIST (cellRef VCC (libraryRef LIB))))\n"); } - - for (auto cell : module->cells()) { + for (auto &cell_it : module->cells_) { + RTLIL::Cell *cell = cell_it.second; *f << stringf(" (instance %s\n", EDIF_DEF(cell->name)); *f << stringf(" (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type), lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : ""); + + auto add_prop = [&](IdString name, Const val) { + if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) + *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str()); + else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def()) + *f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int()); + else { + std::string hex_string = ""; + for (size_t i = 0; i < val.bits.size(); i += 4) { + int digit_value = 0; + if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; + if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; + if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; + if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; + char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; + hex_string = std::string(digit_str) + hex_string; + } + *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str()); + } + }; + for (auto &p : cell->parameters) add_prop(p.first, p.second); if (attr_properties) @@ -467,39 +382,31 @@ struct EdifBackend : public Backend { if (sig[i].wire == NULL && sig[i] != RTLIL::State::S0 && sig[i] != RTLIL::State::S1) log_warning("Bit %d of cell port %s.%s.%s driven by %s will be left unconnected in EDIF output.\n", i, log_id(module), log_id(cell), log_id(p.first), log_signal(sig[i])); + else if (sig.size() == 1) + net_join_db[sig[i]].insert(stringf("(portRef %s (instanceRef %s))", EDIF_REF(p.first), EDIF_REF(cell->name))); else { int member_idx = GetSize(sig)-i-1; auto m = design->module(cell->type); - int width = sig.size(); if (m) { auto w = m->wire(p.first); - if (w) { + if (w) member_idx = GetSize(w)-i-1; - width = GetSize(w); - } - } - if (width == 1) - net_join_db[sig[i]].insert(make_pair(stringf("(portRef %s (instanceRef %s))", EDIF_REF(p.first), EDIF_REF(cell->name)), cell->output(p.first))); - else { - net_join_db[sig[i]].insert(make_pair(stringf("(portRef (member %s %d) (instanceRef %s))", - EDIF_REF(p.first), member_idx, EDIF_REF(cell->name)), cell->output(p.first))); } + net_join_db[sig[i]].insert(stringf("(portRef (member %s %d) (instanceRef %s))", + EDIF_REF(p.first), member_idx, EDIF_REF(cell->name))); } } } - for (auto &it : net_join_db) { RTLIL::SigBit sig = it.first; if (sig.wire == NULL && sig != RTLIL::State::S0 && sig != RTLIL::State::S1) { if (sig == RTLIL::State::Sx) { for (auto &ref : it.second) - log_warning("Exporting x-bit on %s as zero bit.\n", ref.first.c_str()); + log_warning("Exporting x-bit on %s as zero bit.\n", ref.c_str()); sig = RTLIL::State::S0; - } else if (sig == RTLIL::State::Sz) { - continue; } else { for (auto &ref : it.second) - log_error("Don't know how to handle %s on %s.\n", log_signal(sig), ref.first.c_str()); + log_error("Don't know how to handle %s on %s.\n", log_signal(sig), ref.c_str()); log_abort(); } } @@ -516,7 +423,7 @@ struct EdifBackend : public Backend { } *f << stringf(" (net %s (joined\n", EDIF_DEF(netname)); for (auto &ref : it.second) - *f << stringf(" %s\n", ref.first.c_str()); + *f << stringf(" %s\n", ref.c_str()); if (sig.wire == NULL) { if (nogndvcc) log_error("Design contains constant nodes (map with \"hilomap\" first).\n"); @@ -524,55 +431,9 @@ struct EdifBackend : public Backend { *f << stringf(" (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G'); if (sig == RTLIL::State::S1) *f << stringf(" (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P'); - } - *f << stringf(" )"); - if (attr_properties && sig.wire != NULL) - for (auto &p : sig.wire->attributes) - add_prop(p.first, p.second); - *f << stringf("\n )\n"); - } - - for (auto wire : module->wires()) - { - if (!wire->get_bool_attribute(ID::keep)) - continue; - - for(int i = 0; i < wire->width; i++) - { - SigBit raw_sig = RTLIL::SigSpec(wire, i); - SigBit mapped_sig = sigmap(raw_sig); - - if (raw_sig == mapped_sig || net_join_db.count(mapped_sig) == 0) - continue; - - std::string netname = log_signal(raw_sig); - for (size_t i = 0; i < netname.size(); i++) - if (netname[i] == ' ' || netname[i] == '\\') - netname.erase(netname.begin() + i--); - - if (keepmode) - { - *f << stringf(" (net %s (joined\n", EDIF_DEF(netname)); - - auto &refs = net_join_db.at(mapped_sig); - for (auto &ref : refs) - if (ref.second) - *f << stringf(" %s\n", ref.first.c_str()); - *f << stringf(" )"); - - if (attr_properties && raw_sig.wire != NULL) - for (auto &p : raw_sig.wire->attributes) - add_prop(p.first, p.second); - - *f << stringf("\n )\n"); - } - else - { - log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF(netname)); - } } + *f << stringf(" ))\n"); } - *f << stringf(" )\n"); *f << stringf(" )\n"); *f << stringf(" )\n"); diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 9739a7a9ff5..87db0edf780 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -25,6 +25,7 @@ #include "kernel/log.h" #include #include +#include #include #include @@ -42,13 +43,6 @@ static const FDirection FD_OUT = 0x2; static const FDirection FD_INOUT = 0x3; static const int FIRRTL_MAX_DSH_WIDTH_ERROR = 20; // For historic reasons, this is actually one greater than the maximum allowed shift width -std::string getFileinfo(const RTLIL::AttrObject *design_entity) -{ - std::string src(design_entity->get_src_attribute()); - std::string fileinfo_str = src.empty() ? "" : "@[" + src + "]"; - return fileinfo_str; -} - // Get a port direction with respect to a specific module. FDirection getPortFDirection(IdString id, Module *module) { @@ -199,15 +193,14 @@ struct FirrtlWorker if (this->width == 0) { log_error("Memory %s has zero width%s\n", this->name.c_str(), this->atLine()); } - } - + } // We need a default constructor for the dict insert. - memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} + memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} const char *atLine() { if (srcLine == "") { if (pCell) { - auto p = pCell->attributes.find(ID::src); + auto p = pCell->attributes.find("\\src"); srcLine = " at " + p->second.decode_string(); } } @@ -306,8 +299,17 @@ struct FirrtlWorker // If this is a parameterized module, its parent module is encoded in the cell type if (cell->type.begins_with("$paramod")) { - log_assert(cell->has_attribute(ID::hdlname)); - instanceOf = cell->get_string_attribute(ID::hdlname); + std::string::iterator it; + for (it = cell_type.begin(); it < cell_type.end(); it++) + { + switch (*it) { + case '\\': /* FALL_THROUGH */ + case '=': /* FALL_THROUGH */ + case '\'': /* FALL_THROUGH */ + case '$': instanceOf.append("_"); break; + default: instanceOf.append(1, *it); break; + } + } } else { @@ -328,8 +330,7 @@ struct FirrtlWorker log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str()); return; } - std::string cellFileinfo = getFileinfo(cell); - wire_exprs.push_back(stringf("%s" "inst %s%s of %s %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str(), cellFileinfo.c_str())); + wire_exprs.push_back(stringf("%s" "inst %s%s of %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str())); for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { if (it->second.size() > 0) { @@ -343,7 +344,7 @@ struct FirrtlWorker switch (dir) { case FD_INOUT: log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); - YS_FALLTHROUGH + /* FALLTHRU */ case FD_OUT: sourceExpr = firstName; sinkExpr = secondExpr; @@ -351,7 +352,7 @@ struct FirrtlWorker break; case FD_NODIRECTION: log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); - YS_FALLTHROUGH + /* FALLTHRU */ case FD_IN: sourceExpr = secondExpr; sinkExpr = firstName; @@ -370,7 +371,7 @@ struct FirrtlWorker // as part of the coalesced subfield assignments for this wire. register_reverse_wire_map(sourceExpr, *sinkSig); } else { - wire_exprs.push_back(stringf("\n%s%s <= %s %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str(), cellFileinfo.c_str())); + wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str())); } } } @@ -392,60 +393,30 @@ struct FirrtlWorker return result; } - void emit_extmodule() - { - std::string moduleFileinfo = getFileinfo(module); - f << stringf(" extmodule %s: %s\n", make_id(module->name), moduleFileinfo.c_str()); - vector port_decls; - - for (auto wire : module->wires()) - { - const auto wireName = make_id(wire->name); - std::string wireFileinfo = getFileinfo(wire); - - if (wire->port_input && wire->port_output) - { - log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); - } - port_decls.push_back(stringf(" %s %s: UInt<%d> %s\n", wire->port_input ? "input" : "output", - wireName, wire->width, wireFileinfo.c_str())); - } - - for (auto &str : port_decls) - { - f << str; - } - - f << stringf("\n"); - } - - void emit_module() + void run() { - std::string moduleFileinfo = getFileinfo(module); - f << stringf(" module %s: %s\n", make_id(module->name), moduleFileinfo.c_str()); + f << stringf(" module %s:\n", make_id(module->name)); vector port_decls, wire_decls, cell_exprs, wire_exprs; for (auto wire : module->wires()) { const auto wireName = make_id(wire->name); - std::string wireFileinfo = getFileinfo(wire); - // If a wire has initial data, issue a warning since FIRRTL doesn't currently support it. - if (wire->attributes.count(ID::init)) { + if (wire->attributes.count("\\init")) { log_warning("Initial value (%s) for (%s.%s) not supported\n", - wire->attributes.at(ID::init).as_string().c_str(), + wire->attributes.at("\\init").as_string().c_str(), log_id(module), log_id(wire)); } if (wire->port_id) { if (wire->port_input && wire->port_output) log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); - port_decls.push_back(stringf(" %s %s: UInt<%d> %s\n", wire->port_input ? "input" : "output", - wireName, wire->width, wireFileinfo.c_str())); + port_decls.push_back(stringf(" %s %s: UInt<%d>\n", wire->port_input ? "input" : "output", + wireName, wire->width)); } else { - wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", wireName, wire->width, wireFileinfo.c_str())); + wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", wireName, wire->width)); } } @@ -453,7 +424,7 @@ struct FirrtlWorker { static Const ndef(0, 0); - // Is this cell is a module instance? + // Is this cell is a module instance? if (cell->type[0] != '$') { process_instance(cell, wire_exprs); @@ -461,51 +432,50 @@ struct FirrtlWorker } // 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(ID::A_WIDTH, ndef).as_int(); // The width of "A" - int b_width = cell->parameters.at(ID::B_WIDTH, ndef).as_int(); // The width of "A" - const int y_width = cell->parameters.at(ID::Y_WIDTH, ndef).as_int(); // The width of the result - const bool a_signed = cell->parameters.at(ID::A_SIGNED, ndef).as_bool(); - const bool b_signed = cell->parameters.at(ID::B_SIGNED, ndef).as_bool(); + 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); - std::string cellFileinfo = getFileinfo(cell); - if (cell->type.in(ID($not), ID($logic_not), ID($_NOT_), ID($neg), ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_bool), ID($reduce_xnor))) + if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor")) { - string a_expr = make_expr(cell->getPort(ID::A)); - wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str())); + string a_expr = make_expr(cell->getPort("\\A")); + wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); if (a_signed) { a_expr = "asSInt(" + a_expr + ")"; } // Don't use the results of logical operations (a single bit) to control padding - if (!(cell->type.in(ID($eq), ID($eqx), ID($gt), ID($ge), ID($lt), ID($le), ID($ne), ID($nex), ID($reduce_bool), ID($logic_not)) && y_width == 1) ) { + if (!(cell->type.in("$eq", "$eqx", "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$reduce_bool", "$logic_not") && y_width == 1) ) { a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); } // Assume the FIRRTL width is a single bit. firrtl_width = 1; - if (cell->type.in(ID($not), ID($_NOT_))) primop = "not"; - else if (cell->type == ID($neg)) { + if (cell->type == "$not") primop = "not"; + else if (cell->type == "$neg") { primop = "neg"; firrtl_is_signed = true; // Result of "neg" is signed (an SInt). firrtl_width = a_width; - } else if (cell->type == ID($logic_not)) { - primop = "eq"; - a_expr = stringf("%s, UInt(0)", a_expr.c_str()); - } - else if (cell->type == ID($reduce_and)) primop = "andr"; - else if (cell->type == ID($reduce_or)) primop = "orr"; - else if (cell->type == ID($reduce_xor)) primop = "xorr"; - else if (cell->type == ID($reduce_xnor)) { - primop = "not"; - a_expr = stringf("xorr(%s)", a_expr.c_str()); - } - else if (cell->type == ID($reduce_bool)) { + } else if (cell->type == "$logic_not") { + primop = "eq"; + a_expr = stringf("%s, UInt(0)", a_expr.c_str()); + } + else if (cell->type == "$reduce_and") primop = "andr"; + else if (cell->type == "$reduce_or") primop = "orr"; + else if (cell->type == "$reduce_xor") primop = "xorr"; + else if (cell->type == "$reduce_xnor") { + primop = "not"; + a_expr = stringf("xorr(%s)", a_expr.c_str()); + } + else if (cell->type == "$reduce_bool") { primop = "neq"; // Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand. a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width); @@ -516,19 +486,18 @@ struct FirrtlWorker if ((firrtl_is_signed && !always_uint)) expr = stringf("asUInt(%s)", expr.c_str()); - cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); - register_reverse_wire_map(y_id, cell->getPort(ID::Y)); + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; } - if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($xor), ID($_XOR_), ID($xnor), ID($and), ID($_AND_), ID($or), ID($_OR_), ID($eq), ID($eqx), - ID($gt), ID($ge), ID($lt), ID($le), ID($ne), ID($nex), ID($shr), ID($sshr), ID($sshl), ID($shl), - ID($logic_and), ID($logic_or), ID($pow))) + if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or", "$eq", "$eqx", + "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl", + "$logic_and", "$logic_or", "$pow")) { - string a_expr = make_expr(cell->getPort(ID::A)); - string b_expr = make_expr(cell->getPort(ID::B)); - std::string cellFileinfo = getFileinfo(cell); - wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str())); + string a_expr = make_expr(cell->getPort("\\A")); + string b_expr = make_expr(cell->getPort("\\B")); + wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); if (a_signed) { a_expr = "asSInt(" + a_expr + ")"; @@ -540,7 +509,7 @@ struct FirrtlWorker } // Shift amount is always unsigned, and needn't be padded to result width, // otherwise, we need to cast the b_expr appropriately - if (b_signed && !cell->type.in(ID($shr), ID($sshr), ID($shl), ID($sshl), ID($pow))) { + if (b_signed && !cell->type.in("$shr", "$sshr", "$shl", "$sshl", "$pow")) { b_expr = "asSInt(" + b_expr + ")"; // Expand the "B" operand to the result width if (b_width < y_width) { @@ -551,7 +520,7 @@ struct FirrtlWorker // 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(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($xor), ID($_XOR_), ID($xnor), ID($and), ID($_AND_), ID($or), ID($_OR_))) + 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); @@ -564,86 +533,85 @@ struct FirrtlWorker } // Assume the FIRRTL width is the width of "A" firrtl_width = a_width; - auto a_sig = cell->getPort(ID::A); + auto a_sig = cell->getPort("\\A"); - if (cell->type == ID($add)) { + if (cell->type == "$add") { primop = "add"; firrtl_is_signed = a_signed | b_signed; firrtl_width = max(a_width, b_width); - } else if (cell->type == ID($sub)) { + } else if (cell->type == "$sub") { primop = "sub"; firrtl_is_signed = true; int a_widthInc = (!a_signed && b_signed) ? 2 : (a_signed && !b_signed) ? 1 : 0; int b_widthInc = (a_signed && !b_signed) ? 2 : (!a_signed && b_signed) ? 1 : 0; firrtl_width = max(a_width + a_widthInc, b_width + b_widthInc); - } else if (cell->type == ID($mul)) { + } else if (cell->type == "$mul") { primop = "mul"; firrtl_is_signed = a_signed | b_signed; firrtl_width = a_width + b_width; - } else if (cell->type == ID($div)) { + } else if (cell->type == "$div") { primop = "div"; firrtl_is_signed = a_signed | b_signed; firrtl_width = a_width; - } else if (cell->type == ID($mod)) { - // "rem" = truncating modulo + } else if (cell->type == "$mod") { primop = "rem"; firrtl_width = min(a_width, b_width); - } else if (cell->type.in(ID($and), ID($_AND_))) { + } else if (cell->type == "$and") { primop = "and"; always_uint = true; firrtl_width = max(a_width, b_width); } - else if (cell->type.in(ID($or), ID($_OR_))) { + else if (cell->type == "$or" ) { primop = "or"; always_uint = true; firrtl_width = max(a_width, b_width); } - else if (cell->type.in(ID($xor), ID($_XOR_))) { + else if (cell->type == "$xor") { primop = "xor"; always_uint = true; firrtl_width = max(a_width, b_width); } - else if (cell->type == ID($xnor)) { + else if (cell->type == "$xnor") { primop = "xnor"; always_uint = true; firrtl_width = max(a_width, b_width); } - else if ((cell->type == ID($eq)) | (cell->type == ID($eqx))) { + else if ((cell->type == "$eq") | (cell->type == "$eqx")) { primop = "eq"; always_uint = true; firrtl_width = 1; - } - else if ((cell->type == ID($ne)) | (cell->type == ID($nex))) { + } + else if ((cell->type == "$ne") | (cell->type == "$nex")) { primop = "neq"; always_uint = true; firrtl_width = 1; } - else if (cell->type == ID($gt)) { + else if (cell->type == "$gt") { primop = "gt"; always_uint = true; firrtl_width = 1; } - else if (cell->type == ID($ge)) { + else if (cell->type == "$ge") { primop = "geq"; always_uint = true; firrtl_width = 1; } - else if (cell->type == ID($lt)) { + else if (cell->type == "$lt") { primop = "lt"; always_uint = true; firrtl_width = 1; } - else if (cell->type == ID($le)) { + else if (cell->type == "$le") { primop = "leq"; always_uint = true; firrtl_width = 1; } - else if ((cell->type == ID($shl)) | (cell->type == ID($sshl))) { + else if ((cell->type == "$shl") | (cell->type == "$sshl")) { // FIRRTL will widen the result (y) by the amount of the shift. // We'll need to offset this by extracting the un-widened portion as Verilog would do. extract_y_bits = true; // Is the shift amount constant? - auto b_sig = cell->getPort(ID::B); + auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shl"; int shift_amount = b_sig.as_int(); @@ -656,11 +624,11 @@ struct FirrtlWorker firrtl_width = a_width + (1 << b_width) - 1; } } - else if ((cell->type == ID($shr)) | (cell->type == ID($sshr))) { + else if ((cell->type == "$shr") | (cell->type == "$sshr")) { // We don't need to extract a specific range of bits. extract_y_bits = false; // Is the shift amount constant? - auto b_sig = cell->getPort(ID::B); + auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shr"; int shift_amount = b_sig.as_int(); @@ -673,26 +641,26 @@ struct FirrtlWorker // 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 == ID($shr)) { + if (cell->type == "$shr") { a_expr = "asUInt(" + a_expr + ")"; } } } - else if ((cell->type == ID($logic_and))) { + else if ((cell->type == "$logic_and")) { primop = "and"; a_expr = "neq(" + a_expr + ", UInt(0))"; b_expr = "neq(" + b_expr + ", UInt(0))"; always_uint = true; firrtl_width = 1; } - else if ((cell->type == ID($logic_or))) { + else if ((cell->type == "$logic_or")) { primop = "or"; a_expr = "neq(" + a_expr + ", UInt(0))"; b_expr = "neq(" + b_expr + ", UInt(0))"; always_uint = true; firrtl_width = 1; } - else if ((cell->type == ID($pow))) { + 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. @@ -702,7 +670,7 @@ struct FirrtlWorker a_expr = firrtl_is_signed ? "SInt(1)" : "UInt(1)"; extract_y_bits = true; // Is the shift amount constant? - auto b_sig = cell->getPort(ID::B); + auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shl"; int shiftAmount = b_sig.as_int(); @@ -722,8 +690,7 @@ struct FirrtlWorker } } - auto it = cell->parameters.find(ID::B_SIGNED); - if (it == cell->parameters.end() || !it->second.as_bool()) { + if (!cell->parameters.at("\\B_SIGNED").as_bool()) { b_expr = "asUInt(" + b_expr + ")"; } @@ -746,49 +713,48 @@ struct FirrtlWorker if ((firrtl_is_signed && !always_uint)) expr = stringf("asUInt(%s)", expr.c_str()); - cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); - register_reverse_wire_map(y_id, cell->getPort(ID::Y)); + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; } - if (cell->type.in(ID($mux), ID($_MUX_))) + if (cell->type.in("$mux")) { - auto it = cell->parameters.find(ID::WIDTH); - int width = it == cell->parameters.end()? 1 : it->second.as_int(); - string a_expr = make_expr(cell->getPort(ID::A)); - string b_expr = make_expr(cell->getPort(ID::B)); - string s_expr = make_expr(cell->getPort(ID::S)); - wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), width, cellFileinfo.c_str())); + int width = cell->parameters.at("\\WIDTH").as_int(); + string a_expr = make_expr(cell->getPort("\\A")); + string b_expr = make_expr(cell->getPort("\\B")); + string s_expr = make_expr(cell->getPort("\\S")); + wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), width)); string expr = stringf("mux(%s, %s, %s)", s_expr.c_str(), b_expr.c_str(), a_expr.c_str()); - cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); - register_reverse_wire_map(y_id, cell->getPort(ID::Y)); + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; } - if (cell->type.in(ID($mem))) + if (cell->type.in("$mem")) { string mem_id = make_id(cell->name); - int abits = cell->parameters.at(ID::ABITS).as_int(); - int width = cell->parameters.at(ID::WIDTH).as_int(); - int size = cell->parameters.at(ID::SIZE).as_int(); + int abits = cell->parameters.at("\\ABITS").as_int(); + int width = cell->parameters.at("\\WIDTH").as_int(); + int size = cell->parameters.at("\\SIZE").as_int(); memory m(cell, mem_id, abits, size, width); - int rd_ports = cell->parameters.at(ID::RD_PORTS).as_int(); - int wr_ports = cell->parameters.at(ID::WR_PORTS).as_int(); + int rd_ports = cell->parameters.at("\\RD_PORTS").as_int(); + int wr_ports = cell->parameters.at("\\WR_PORTS").as_int(); - Const initdata = cell->parameters.at(ID::INIT); + Const initdata = cell->parameters.at("\\INIT"); for (State bit : initdata.bits) if (bit != State::Sx) log_error("Memory with initialization data: %s.%s\n", log_id(module), log_id(cell)); - Const rd_clk_enable = cell->parameters.at(ID::RD_CLK_ENABLE); - Const wr_clk_enable = cell->parameters.at(ID::WR_CLK_ENABLE); - Const wr_clk_polarity = cell->parameters.at(ID::WR_CLK_POLARITY); + Const rd_clk_enable = cell->parameters.at("\\RD_CLK_ENABLE"); + Const wr_clk_enable = cell->parameters.at("\\WR_CLK_ENABLE"); + Const wr_clk_polarity = cell->parameters.at("\\WR_CLK_POLARITY"); - int offset = cell->parameters.at(ID::OFFSET).as_int(); + int offset = cell->parameters.at("\\OFFSET").as_int(); if (offset != 0) log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(cell)); @@ -797,8 +763,8 @@ struct FirrtlWorker if (rd_clk_enable[i] != State::S0) log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(cell)); - SigSpec addr_sig = cell->getPort(ID::RD_ADDR).extract(i*abits, abits); - SigSpec data_sig = cell->getPort(ID::RD_DATA).extract(i*width, width); + SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(i*abits, abits); + SigSpec data_sig = cell->getPort("\\RD_DATA").extract(i*width, width); string addr_expr = make_expr(addr_sig); string name(stringf("%s.r%d", m.name.c_str(), i)); bool clk_enable = false; @@ -824,14 +790,14 @@ struct FirrtlWorker bool clk_enable = true; bool clk_parity = true; bool transparency = false; - SigSpec addr_sig =cell->getPort(ID::WR_ADDR).extract(i*abits, abits); + SigSpec addr_sig =cell->getPort("\\WR_ADDR").extract(i*abits, abits); string addr_expr = make_expr(addr_sig); - SigSpec data_sig =cell->getPort(ID::WR_DATA).extract(i*width, width); + SigSpec data_sig =cell->getPort("\\WR_DATA").extract(i*width, width); string data_expr = make_expr(data_sig); - SigSpec clk_sig = cell->getPort(ID::WR_CLK).extract(i); + SigSpec clk_sig = cell->getPort("\\WR_CLK").extract(i); string clk_expr = make_expr(clk_sig); - SigSpec wen_sig = cell->getPort(ID::WR_EN).extract(i*width, width); + SigSpec wen_sig = cell->getPort("\\WR_EN").extract(i*width, width); string wen_expr = make_expr(wen_sig[0]); for (int i = 1; i < GetSize(wen_sig); i++) @@ -848,23 +814,23 @@ struct FirrtlWorker continue; } - if (cell->type.in(ID($memwr), ID($memrd), ID($meminit))) + if (cell->type.in("$memwr", "$memrd", "$meminit")) { std::string cell_type = fid(cell->type); - std::string mem_id = make_id(cell->parameters[ID::MEMID].decode_string()); - int abits = cell->parameters.at(ID::ABITS).as_int(); - int width = cell->parameters.at(ID::WIDTH).as_int(); + std::string mem_id = make_id(cell->parameters["\\MEMID"].decode_string()); + int abits = cell->parameters.at("\\ABITS").as_int(); + int width = cell->parameters.at("\\WIDTH").as_int(); memory *mp = nullptr; - if (cell->type == ID($meminit) ) { + if (cell->type == "$meminit" ) { log_error("$meminit (%s.%s.%s) currently unsupported\n", log_id(module), log_id(cell), mem_id.c_str()); } else { // It's a $memwr or $memrd. Remember the read/write port parameters for the eventual FIRRTL memory definition. - auto addrSig = cell->getPort(ID::ADDR); - auto dataSig = cell->getPort(ID::DATA); - auto enableSig = cell->getPort(ID::EN); - auto clockSig = cell->getPort(ID::CLK); - Const clk_enable = cell->parameters.at(ID::CLK_ENABLE); - Const clk_polarity = cell->parameters.at(ID::CLK_POLARITY); + auto addrSig = cell->getPort("\\ADDR"); + auto dataSig = cell->getPort("\\DATA"); + auto enableSig = cell->getPort("\\EN"); + auto clockSig = cell->getPort("\\CLK"); + Const clk_enable = cell->parameters.at("\\CLK_ENABLE"); + Const clk_polarity = cell->parameters.at("\\CLK_POLARITY"); // Do we already have an entry for this memory? if (memories.count(mem_id) == 0) { @@ -875,13 +841,13 @@ struct FirrtlWorker int portNum = 0; bool transparency = false; string data_expr = make_expr(dataSig); - if (cell->type.in(ID($memwr))) { + if (cell->type.in("$memwr")) { portNum = (int) mp->write_ports.size(); write_port wp(stringf("%s.w%d", mem_id.c_str(), portNum), clk_enable.as_bool(), clk_polarity.as_bool(), transparency, clockSig, enableSig, addrSig, dataSig); mp->add_memory_write_port(wp); cell_exprs.push_back(stringf("%s%s.data <= %s\n", indent.c_str(), wp.name.c_str(), data_expr.c_str())); cell_exprs.push_back(wp.gen_write(indent.c_str())); - } else if (cell->type.in(ID($memrd))) { + } else if (cell->type.in("$memrd")) { portNum = (int) mp->read_ports.size(); read_port rp(stringf("%s.r%d", mem_id.c_str(), portNum), clk_enable.as_bool(), clk_polarity.as_bool(), transparency, clockSig, enableSig, addrSig); mp->add_memory_read_port(rp); @@ -892,20 +858,20 @@ struct FirrtlWorker continue; } - if (cell->type.in(ID($dff))) + if (cell->type.in("$dff")) { - bool clkpol = cell->parameters.at(ID::CLK_POLARITY).as_bool(); + bool clkpol = cell->parameters.at("\\CLK_POLARITY").as_bool(); if (clkpol == false) log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell)); - int width = cell->parameters.at(ID::WIDTH).as_int(); - string expr = make_expr(cell->getPort(ID::D)); - string clk_expr = "asClock(" + make_expr(cell->getPort(ID::CLK)) + ")"; + int width = cell->parameters.at("\\WIDTH").as_int(); + string expr = make_expr(cell->getPort("\\D")); + string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")"; - wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s %s\n", y_id.c_str(), width, clk_expr.c_str(), cellFileinfo.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 %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); - register_reverse_wire_map(y_id, cell->getPort(ID::Q)); + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Q")); continue; } @@ -916,38 +882,38 @@ struct FirrtlWorker process_instance(cell, wire_exprs); continue; } - if (cell->type == ID($shiftx)) { + if (cell->type == "$shiftx") { // assign y = a[b +: y_width]; // We'll extract the correct bits as part of the primop. - string a_expr = make_expr(cell->getPort(ID::A)); + string a_expr = make_expr(cell->getPort("\\A")); // Get the initial bit selector - string b_expr = make_expr(cell->getPort(ID::B)); + string b_expr = make_expr(cell->getPort("\\B")); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); - if (cell->getParam(ID::B_SIGNED).as_bool()) { + if (cell->getParam("\\B_SIGNED").as_bool()) { // Use validif to constrain the selection (test the sign bit) auto b_string = b_expr.c_str(); - int b_sign = cell->parameters.at(ID::B_WIDTH).as_int() - 1; + int b_sign = cell->parameters.at("\\B_WIDTH").as_int() - 1; b_expr = stringf("validif(not(bits(%s, %d, %d)), %s)", b_string, b_sign, b_sign, b_string); } string expr = stringf("dshr(%s, %s)", a_expr.c_str(), b_expr.c_str()); cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); - register_reverse_wire_map(y_id, cell->getPort(ID::Y)); + register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; } - if (cell->type == ID($shift)) { + if (cell->type == "$shift") { // assign y = a >> b; // where b may be negative - string a_expr = make_expr(cell->getPort(ID::A)); - string b_expr = make_expr(cell->getPort(ID::B)); + string a_expr = make_expr(cell->getPort("\\A")); + string b_expr = make_expr(cell->getPort("\\B")); auto b_string = b_expr.c_str(); string expr; wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); - if (cell->getParam(ID::B_SIGNED).as_bool()) { + if (cell->getParam("\\B_SIGNED").as_bool()) { // We generate a left or right shift based on the sign of b. std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_width).c_str(), y_width); std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string); @@ -960,13 +926,13 @@ struct FirrtlWorker expr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string); } cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); - register_reverse_wire_map(y_id, cell->getPort(ID::Y)); + register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; } - if (cell->type == ID($pos)) { + if (cell->type == "$pos") { // assign y = a; // printCell(cell); - string a_expr = make_expr(cell->getPort(ID::A)); + 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) { @@ -974,7 +940,7 @@ struct FirrtlWorker } 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(ID::Y)); + 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)); @@ -994,7 +960,6 @@ struct FirrtlWorker for (auto wire : module->wires()) { string expr; - std::string wireFileinfo = getFileinfo(wire); if (wire->port_input) continue; @@ -1053,20 +1018,14 @@ struct FirrtlWorker if (is_valid) { if (make_unconn_id) { - wire_decls.push_back(stringf(" wire %s: UInt<1> %s\n", unconn_id.c_str(), wireFileinfo.c_str())); - // `invalid` is a firrtl construction for simulation so we will not - // tag it with a @[fileinfo] tag as it doesn't directly correspond to - // a specific line of verilog code. + wire_decls.push_back(stringf(" wire %s: UInt<1>\n", unconn_id.c_str())); wire_decls.push_back(stringf(" %s is invalid\n", unconn_id.c_str())); } - wire_exprs.push_back(stringf(" %s <= %s %s\n", make_id(wire->name), expr.c_str(), wireFileinfo.c_str())); + wire_exprs.push_back(stringf(" %s <= %s\n", make_id(wire->name), expr.c_str())); } else { if (make_unconn_id) { unconn_id.clear(); } - // `invalid` is a firrtl construction for simulation so we will not - // tag it with a @[fileinfo] tag as it doesn't directly correspond to - // a specific line of verilog code. wire_decls.push_back(stringf(" %s is invalid\n", make_id(wire->name))); } } @@ -1106,24 +1065,12 @@ struct FirrtlWorker for (auto str : wire_exprs) f << str; - - f << stringf("\n"); - } - - void run() - { - // Blackboxes should be emitted as `extmodule`s in firrtl. Only ports are - // emitted in such a case. - if (module->get_blackbox_attribute()) - emit_extmodule(); - else - emit_module(); } }; struct FirrtlBackend : public Backend { FirrtlBackend() : Backend("firrtl", "write design to a FIRRTL file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1134,7 +1081,7 @@ struct FirrtlBackend : public Backend { log(" pmuxtree\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx = args.size(); // We aren't expecting any arguments. @@ -1166,7 +1113,7 @@ struct FirrtlBackend : public Backend { for (auto module : design->modules()) { make_id(module->name); last = module; - if (top == nullptr && module->get_bool_attribute(ID::top)) { + if (top == nullptr && module->get_bool_attribute("\\top")) { top = module; } for (auto wire : module->wires()) @@ -1177,8 +1124,7 @@ struct FirrtlBackend : public Backend { if (top == nullptr) top = last; - std::string circuitFileinfo = getFileinfo(top); - *f << stringf("circuit %s: %s\n", make_id(top->name), circuitFileinfo.c_str()); + *f << stringf("circuit %s:\n", make_id(top->name)); for (auto module : design->modules()) { diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index aa5a175ca29..e067862209b 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -131,8 +131,6 @@ void ILANG_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL:: f << stringf("output %d ", wire->port_id); if (wire->port_input && wire->port_output) f << stringf("inout %d ", wire->port_id); - if (wire->is_signed) - f << stringf("signed "); f << stringf("%s\n", wire->name.c_str()); } @@ -292,16 +290,8 @@ void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu if (!module->avail_parameters.empty()) { if (only_selected) f << stringf("\n"); - for (const auto &p : module->avail_parameters) { - const auto &it = module->parameter_default_values.find(p); - if (it == module->parameter_default_values.end()) { - f << stringf("%s" " parameter %s\n", indent.c_str(), p.c_str()); - } else { - f << stringf("%s" " parameter %s ", indent.c_str(), p.c_str()); - dump_const(f, it->second); - f << stringf("\n"); - } - } + for (auto &p : module->avail_parameters) + f << stringf("%s" " parameter %s\n", indent.c_str(), p.c_str()); } } @@ -362,14 +352,16 @@ void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) { +#ifndef NDEBUG int init_autoidx = autoidx; +#endif if (!flag_m) { int count_selected_mods = 0; - for (auto module : design->modules()) { - if (design->selected_whole_module(module->name)) + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { + if (design->selected_whole_module(it->first)) flag_m = true; - if (design->selected(module)) + if (design->selected(it->second)) count_selected_mods++; } if (count_selected_mods > 1) @@ -382,11 +374,11 @@ void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl f << stringf("autoidx %d\n", autoidx); } - for (auto module : design->modules()) { - if (!only_selected || design->selected(module)) { + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { + if (!only_selected || design->selected(it->second)) { if (only_selected) f << stringf("\n"); - dump_module(f, "", module, design, only_selected, flag_m, flag_n); + dump_module(f, "", it->second, design, only_selected, flag_m, flag_n); } } @@ -398,7 +390,7 @@ PRIVATE_NAMESPACE_BEGIN struct IlangBackend : public Backend { IlangBackend() : Backend("ilang", "write design to ilang file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -411,7 +403,7 @@ struct IlangBackend : public Backend { log(" only write selected parts of the design.\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool selected = false; @@ -438,7 +430,7 @@ struct IlangBackend : public Backend { struct DumpPass : public Pass { DumpPass() : Pass("dump", "print parts of the design in ilang format") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -461,7 +453,7 @@ struct DumpPass : public Pass { log(" like -outfile but append instead of overwrite\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string filename; bool flag_m = false, flag_n = false, append = false; diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index 98a14173b10..809a0fa09a8 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -46,7 +46,7 @@ static std::string netname(std::set &conntypes_code, std::set args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing INTERSYNTH backend.\n"); log_push(); @@ -122,67 +122,70 @@ struct IntersynthBackend : public Backend { for (auto lib : libs) ct.setup_design(lib); - for (auto module : design->modules()) + for (auto module_it : design->modules_) { + RTLIL::Module *module = module_it.second; SigMap sigmap(module); if (module->get_blackbox_attribute()) continue; - if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells().size() == 0) + if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells_.size() == 0) continue; if (selected && !design->selected_whole_module(module->name)) { if (design->selected_module(module->name)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name)); + log_cmd_error("Can't handle partially selected module %s!\n", RTLIL::id2cstr(module->name)); continue; } - log("Generating netlist %s.\n", log_id(module->name)); + log("Generating netlist %s.\n", RTLIL::id2cstr(module->name)); if (module->memories.size() != 0 || module->processes.size() != 0) log_error("Can't generate a netlist for a module with unprocessed memories or processes!\n"); std::set constcells_code; - netlists_code += stringf("# Netlist of module %s\n", log_id(module->name)); - netlists_code += stringf("netlist %s\n", log_id(module->name)); + netlists_code += stringf("# Netlist of module %s\n", RTLIL::id2cstr(module->name)); + netlists_code += stringf("netlist %s\n", RTLIL::id2cstr(module->name)); // Module Ports: "std::set celltypes_code" prevents duplicate top level ports - for (auto wire : module->wires()) { + for (auto wire_it : module->wires_) { + RTLIL::Wire *wire = wire_it.second; if (wire->port_input || wire->port_output) { celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n", - log_id(wire->name), wire->width, wire->port_input ? "*" : "", - wire->port_input ? "input" : "output", log_id(wire->name), wire->width, log_id(wire->name))); - netlists_code += stringf("node %s %s PORT %s\n", log_id(wire->name), log_id(wire->name), + RTLIL::id2cstr(wire->name), wire->width, wire->port_input ? "*" : "", + wire->port_input ? "input" : "output", RTLIL::id2cstr(wire->name), wire->width, RTLIL::id2cstr(wire->name))); + netlists_code += stringf("node %s %s PORT %s\n", RTLIL::id2cstr(wire->name), RTLIL::id2cstr(wire->name), netname(conntypes_code, celltypes_code, constcells_code, sigmap(wire)).c_str()); } } // Submodules: "std::set celltypes_code" prevents duplicate cell types - for (auto cell : module->cells()) + for (auto cell_it : module->cells_) { + RTLIL::Cell *cell = cell_it.second; std::string celltype_code, node_code; if (!ct.cell_known(cell->type)) - log_error("Found unknown cell type %s in module!\n", log_id(cell->type)); + log_error("Found unknown cell type %s in module!\n", RTLIL::id2cstr(cell->type)); - celltype_code = stringf("celltype %s", log_id(cell->type)); - node_code = stringf("node %s %s", log_id(cell->name), log_id(cell->type)); + celltype_code = stringf("celltype %s", RTLIL::id2cstr(cell->type)); + node_code = stringf("node %s %s", RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); for (auto &port : cell->connections()) { RTLIL::SigSpec sig = sigmap(port.second); if (sig.size() != 0) { conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size())); - celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", log_id(port.first)); - node_code += stringf(" %s %s", log_id(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig).c_str()); + celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", RTLIL::id2cstr(port.first)); + node_code += stringf(" %s %s", RTLIL::id2cstr(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig).c_str()); } } for (auto ¶m : cell->parameters) { - celltype_code += stringf(" cfg:%d %s", int(param.second.bits.size()), log_id(param.first)); + celltype_code += stringf(" cfg:%d %s", int(param.second.bits.size()), RTLIL::id2cstr(param.first)); if (param.second.bits.size() != 32) { - node_code += stringf(" %s '", log_id(param.first)); + node_code += stringf(" %s '", RTLIL::id2cstr(param.first)); for (int i = param.second.bits.size()-1; i >= 0; i--) node_code += param.second.bits[i] == State::S1 ? "1" : "0"; } else - node_code += stringf(" %s 0x%x", log_id(param.first), param.second.as_int()); + node_code += stringf(" %s 0x%x", RTLIL::id2cstr(param.first), param.second.as_int()); } celltypes_code.insert(celltype_code + "\n"); diff --git a/backends/json/json.cc b/backends/json/json.cc index eeadc1b8903..107009ee4e8 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -33,7 +33,6 @@ struct JsonWriter std::ostream &f; bool use_selection; bool aig_mode; - bool compat_int_mode; Design *design; Module *module; @@ -43,9 +42,8 @@ struct JsonWriter dict sigids; pool aig_models; - JsonWriter(std::ostream &f, bool use_selection, bool aig_mode, bool compat_int_mode) : - f(f), use_selection(use_selection), aig_mode(aig_mode), - compat_int_mode(compat_int_mode) { } + JsonWriter(std::ostream &f, bool use_selection, bool aig_mode) : + f(f), use_selection(use_selection), aig_mode(aig_mode) { } string get_string(string str) { @@ -104,7 +102,8 @@ struct JsonWriter if (state < 2) str += " "; f << get_string(str); - } else if (compat_int_mode && GetSize(value) <= 32 && value.is_fully_def()) { + } 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 @@ -141,12 +140,6 @@ struct JsonWriter write_parameters(module->attributes, /*for_module=*/true); f << stringf("\n },\n"); - if (module->parameter_default_values.size()) { - f << stringf(" \"parameter_default_values\": {"); - write_parameters(module->parameter_default_values, /*for_module=*/true); - f << stringf("\n },\n"); - } - f << stringf(" \"ports\": {"); bool first = true; for (auto n : module->ports) { @@ -160,8 +153,6 @@ struct JsonWriter f << stringf(" \"offset\": %d,\n", w->start_offset); if (w->upto) f << stringf(" \"upto\": 1,\n"); - if (w->is_signed) - f << stringf(" \"signed\": %d,\n", w->is_signed); f << stringf(" \"bits\": %s\n", get_bits(w).c_str()); f << stringf(" }"); first = false; @@ -229,8 +220,6 @@ struct JsonWriter f << stringf(" \"offset\": %d,\n", w->start_offset); if (w->upto) f << stringf(" \"upto\": 1,\n"); - if (w->is_signed) - f << stringf(" \"signed\": %d,\n", w->is_signed); f << stringf(" \"attributes\": {"); write_parameters(w->attributes); f << stringf("\n }\n"); @@ -294,7 +283,7 @@ struct JsonWriter struct JsonBackend : public Backend { JsonBackend() : Backend("json", "write design to a JSON file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -305,25 +294,12 @@ struct JsonBackend : public Backend { log(" -aig\n"); log(" include AIG models for the different gate types\n"); log("\n"); - log(" -compat-int\n"); - log(" emit 32-bit or smaller fully-defined parameter values directly\n"); - log(" as JSON numbers (for compatibility with old parsers)\n"); - log("\n"); log("\n"); log("The general syntax of the JSON output created by this command is as follows:\n"); log("\n"); log(" {\n"); - log(" \"creator\": \"Yosys \",\n"); log(" \"modules\": {\n"); log(" : {\n"); - log(" \"attributes\": {\n"); - log(" : ,\n"); - log(" ...\n"); - log(" },\n"); - log(" \"parameter_default_values\": {\n"); - log(" : ,\n"); - log(" ...\n"); - log(" },\n"); log(" \"ports\": {\n"); log(" : ,\n"); log(" ...\n"); @@ -348,19 +324,13 @@ struct JsonBackend : public Backend { log(" {\n"); log(" \"direction\": <\"input\" | \"output\" | \"inout\">,\n"); log(" \"bits\": \n"); - log(" \"offset\": \n"); - log(" \"upto\": <1 if the port bit indexing is MSB-first>\n"); log(" }\n"); log("\n"); - log("The \"offset\" and \"upto\" fields are skipped if their value would be 0."); - log("They don't affect connection semantics, and are only used to preserve original"); - log("HDL bit indexing."); log("And is:\n"); log("\n"); log(" {\n"); log(" \"hide_name\": <1 | 0>,\n"); log(" \"type\": ,\n"); - log(" \"model\": ,\n"); log(" \"parameters\": {\n"); log(" : ,\n"); log(" ...\n"); @@ -384,8 +354,6 @@ struct JsonBackend : public Backend { log(" {\n"); log(" \"hide_name\": <1 | 0>,\n"); log(" \"bits\": \n"); - log(" \"offset\": \n"); - log(" \"upto\": <1 if the port bit indexing is MSB-first>\n"); log(" }\n"); log("\n"); log("The \"hide_name\" fields are set to 1 when the name of this cell or net is\n"); @@ -400,9 +368,10 @@ struct JsonBackend : public Backend { log("connected to a constant driver are denoted as string \"0\", \"1\", \"x\", or\n"); log("\"z\" instead of a number.\n"); log("\n"); - log("Bit vectors (including integers) are written as string holding the binary"); - log("representation of the value. Strings are written as strings, with an appended"); - log("blank in cases of strings of the form /[01xz]* */.\n"); + log("Numeric 32-bit parameter and attribute values are written as decimal values.\n"); + log("Bit verctors of different sizes, or ones containing 'x' or 'z' bits, are written\n"); + log("as string holding the binary representation of the value. Strings are written\n"); + log("as strings, with an appended blank in cases of strings of the form /[01xz]* */.\n"); log("\n"); log("For example the following Verilog code:\n"); log("\n"); @@ -413,15 +382,9 @@ struct JsonBackend : public Backend { log("\n"); log("Translates to the following JSON output:\n"); log("\n"); - log(" {\n"); - log(" \"creator\": \"Yosys 0.9+2406 (git sha1 fb1168d8, clang 9.0.1 -fPIC -Os)\",\n"); log(" \"modules\": {\n"); log(" \"test\": {\n"); - log(" \"attributes\": {\n"); - log(" \"cells_not_processed\": \"00000000000000000000000000000001\",\n"); - log(" \"src\": \"test.v:1.1-4.10\"\n"); - log(" },\n"); log(" \"ports\": {\n"); log(" \"x\": {\n"); log(" \"direction\": \"input\",\n"); @@ -437,34 +400,33 @@ struct JsonBackend : public Backend { log(" \"hide_name\": 0,\n"); log(" \"type\": \"foo\",\n"); log(" \"parameters\": {\n"); - log(" \"P\": \"00000000000000000000000000101010\",\n"); - log(" \"Q\": \"00000000000000000000010100111001\"\n"); + log(" \"Q\": 1337,\n"); + log(" \"P\": 42\n"); log(" },\n"); log(" \"attributes\": {\n"); - log(" \"keep\": \"00000000000000000000000000000001\",\n"); - log(" \"module_not_derived\": \"00000000000000000000000000000001\",\n"); - log(" \"src\": \"test.v:3.1-3.55\"\n"); + log(" \"keep\": 1,\n"); + log(" \"src\": \"test.v:2\"\n"); log(" },\n"); log(" \"connections\": {\n"); - log(" \"A\": [ 3, 2 ],\n"); + log(" \"C\": [ 2, 2, 2, 2, \"0\", \"1\", \"0\", \"1\" ],\n"); log(" \"B\": [ 2, 3 ],\n"); - log(" \"C\": [ 2, 2, 2, 2, \"0\", \"1\", \"0\", \"1\" ]\n"); + log(" \"A\": [ 3, 2 ]\n"); log(" }\n"); log(" }\n"); log(" },\n"); log(" \"netnames\": {\n"); - log(" \"x\": {\n"); + log(" \"y\": {\n"); log(" \"hide_name\": 0,\n"); - log(" \"bits\": [ 2 ],\n"); + log(" \"bits\": [ 3 ],\n"); log(" \"attributes\": {\n"); - log(" \"src\": \"test.v:1.19-1.20\"\n"); + log(" \"src\": \"test.v:1\"\n"); log(" }\n"); log(" },\n"); - log(" \"y\": {\n"); + log(" \"x\": {\n"); log(" \"hide_name\": 0,\n"); - log(" \"bits\": [ 3 ],\n"); + log(" \"bits\": [ 2 ],\n"); log(" \"attributes\": {\n"); - log(" \"src\": \"test.v:1.22-1.23\"\n"); + log(" \"src\": \"test.v:1\"\n"); log(" }\n"); log(" }\n"); log(" }\n"); @@ -530,10 +492,9 @@ struct JsonBackend : public Backend { log("format. A program processing this format must ignore all unknown fields.\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool aig_mode = false; - bool compat_int_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -542,24 +503,20 @@ struct JsonBackend : public Backend { aig_mode = true; continue; } - if (args[argidx] == "-compat-int") { - compat_int_mode = true; - continue; - } break; } extra_args(f, filename, args, argidx); log_header(design, "Executing JSON backend.\n"); - JsonWriter json_writer(*f, false, aig_mode, compat_int_mode); + JsonWriter json_writer(*f, false, aig_mode); json_writer.write_design(design); } } JsonBackend; struct JsonPass : public Pass { JsonPass() : Pass("json", "write design in JSON format") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -573,18 +530,13 @@ struct JsonPass : public Pass { log(" -aig\n"); log(" also include AIG models for the different gate types\n"); log("\n"); - log(" -compat-int\n"); - log(" emit 32-bit or smaller fully-defined parameter values directly\n"); - log(" as JSON numbers (for compatibility with old parsers)\n"); - log("\n"); log("See 'help write_json' for a description of the JSON format used.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string filename; bool aig_mode = false; - bool compat_int_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -597,10 +549,6 @@ struct JsonPass : public Pass { aig_mode = true; continue; } - if (args[argidx] == "-compat-int") { - compat_int_mode = true; - continue; - } break; } extra_args(args, argidx, design); @@ -621,7 +569,7 @@ struct JsonPass : public Pass { f = &buf; } - JsonWriter json_writer(*f, true, aig_mode, compat_int_mode); + JsonWriter json_writer(*f, true, aig_mode); json_writer.write_design(design); if (!filename.empty()) { diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc index f6623a38268..6716861732e 100644 --- a/backends/protobuf/protobuf.cc +++ b/backends/protobuf/protobuf.cc @@ -231,7 +231,7 @@ struct ProtobufDesignSerializer struct ProtobufBackend : public Backend { ProtobufBackend(): Backend("protobuf", "write design to a Protocol Buffer file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -249,7 +249,7 @@ struct ProtobufBackend : public Backend { log("Yosys source code distribution.\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool aig_mode = false; bool text_mode = false; @@ -286,7 +286,7 @@ struct ProtobufBackend : public Backend { struct ProtobufPass : public Pass { ProtobufPass() : Pass("protobuf", "write design in Protobuf format") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -307,7 +307,7 @@ struct ProtobufPass : public Pass { log("Yosys source code distribution.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string filename; bool aig_mode = false; diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index 3adeaa6c02b..54dbb84afcf 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -378,16 +378,16 @@ struct SimplecWorker void eval_cell(HierDirtyFlags *work, Cell *cell) { - if (cell->type.in(ID($_BUF_), ID($_NOT_))) + if (cell->type.in("$_BUF_", "$_NOT_")) { - SigBit a = sigmaps.at(work->module)(cell->getPort(ID::A)); - SigBit y = sigmaps.at(work->module)(cell->getPort(ID::Y)); + SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); + SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; string expr; - if (cell->type == ID($_BUF_)) expr = a_expr; - if (cell->type == ID($_NOT_)) expr = "!" + a_expr; + if (cell->type == "$_BUF_") expr = a_expr; + if (cell->type == "$_NOT_") expr = "!" + a_expr; log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + @@ -397,24 +397,24 @@ struct SimplecWorker return; } - if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_))) + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) { - SigBit a = sigmaps.at(work->module)(cell->getPort(ID::A)); - SigBit b = sigmaps.at(work->module)(cell->getPort(ID::B)); - SigBit y = sigmaps.at(work->module)(cell->getPort(ID::Y)); + SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); + SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); + SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; string expr; - if (cell->type == ID($_AND_)) expr = stringf("%s & %s", a_expr.c_str(), b_expr.c_str()); - if (cell->type == ID($_NAND_)) expr = stringf("!(%s & %s)", a_expr.c_str(), b_expr.c_str()); - if (cell->type == ID($_OR_)) expr = stringf("%s | %s", a_expr.c_str(), b_expr.c_str()); - if (cell->type == ID($_NOR_)) expr = stringf("!(%s | %s)", a_expr.c_str(), b_expr.c_str()); - if (cell->type == ID($_XOR_)) expr = stringf("%s ^ %s", a_expr.c_str(), b_expr.c_str()); - if (cell->type == ID($_XNOR_)) expr = stringf("!(%s ^ %s)", a_expr.c_str(), b_expr.c_str()); - if (cell->type == ID($_ANDNOT_)) expr = stringf("%s & (!%s)", a_expr.c_str(), b_expr.c_str()); - if (cell->type == ID($_ORNOT_)) expr = stringf("%s | (!%s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_AND_") expr = stringf("%s & %s", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_NAND_") expr = stringf("!(%s & %s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_OR_") expr = stringf("%s | %s", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_NOR_") expr = stringf("!(%s | %s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_XOR_") expr = stringf("%s ^ %s", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_XNOR_") expr = stringf("!(%s ^ %s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_ANDNOT_") expr = stringf("%s & (!%s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_ORNOT_") expr = stringf("%s | (!%s)", a_expr.c_str(), b_expr.c_str()); log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + @@ -424,20 +424,20 @@ struct SimplecWorker return; } - if (cell->type.in(ID($_AOI3_), ID($_OAI3_))) + if (cell->type.in("$_AOI3_", "$_OAI3_")) { - SigBit a = sigmaps.at(work->module)(cell->getPort(ID::A)); - SigBit b = sigmaps.at(work->module)(cell->getPort(ID::B)); - SigBit c = sigmaps.at(work->module)(cell->getPort(ID::C)); - SigBit y = sigmaps.at(work->module)(cell->getPort(ID::Y)); + SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); + SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); + SigBit c = sigmaps.at(work->module)(cell->getPort("\\C")); + SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; string c_expr = c.wire ? util_get_bit(work->prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0"; string expr; - if (cell->type == ID($_AOI3_)) expr = stringf("!((%s & %s) | %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str()); - if (cell->type == ID($_OAI3_)) expr = stringf("!((%s | %s) & %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str()); + if (cell->type == "$_AOI3_") expr = stringf("!((%s & %s) | %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str()); + if (cell->type == "$_OAI3_") expr = stringf("!((%s | %s) & %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str()); log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + @@ -447,13 +447,13 @@ struct SimplecWorker return; } - if (cell->type.in(ID($_AOI4_), ID($_OAI4_))) + if (cell->type.in("$_AOI4_", "$_OAI4_")) { - SigBit a = sigmaps.at(work->module)(cell->getPort(ID::A)); - SigBit b = sigmaps.at(work->module)(cell->getPort(ID::B)); - SigBit c = sigmaps.at(work->module)(cell->getPort(ID::C)); - SigBit d = sigmaps.at(work->module)(cell->getPort(ID::D)); - SigBit y = sigmaps.at(work->module)(cell->getPort(ID::Y)); + SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); + SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); + SigBit c = sigmaps.at(work->module)(cell->getPort("\\C")); + SigBit d = sigmaps.at(work->module)(cell->getPort("\\D")); + SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; @@ -461,8 +461,8 @@ struct SimplecWorker string d_expr = d.wire ? util_get_bit(work->prefix + cid(d.wire->name), d.wire->width, d.offset) : d.data ? "1" : "0"; string expr; - if (cell->type == ID($_AOI4_)) expr = stringf("!((%s & %s) | (%s & %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str()); - if (cell->type == ID($_OAI4_)) expr = stringf("!((%s | %s) & (%s | %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str()); + if (cell->type == "$_AOI4_") expr = stringf("!((%s & %s) | (%s & %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str()); + if (cell->type == "$_OAI4_") expr = stringf("!((%s | %s) & (%s | %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str()); log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + @@ -472,12 +472,12 @@ struct SimplecWorker return; } - if (cell->type.in(ID($_MUX_), ID($_NMUX_))) + if (cell->type.in("$_MUX_", "$_NMUX_")) { - SigBit a = sigmaps.at(work->module)(cell->getPort(ID::A)); - SigBit b = sigmaps.at(work->module)(cell->getPort(ID::B)); - SigBit s = sigmaps.at(work->module)(cell->getPort(ID::S)); - SigBit y = sigmaps.at(work->module)(cell->getPort(ID::Y)); + SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); + SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); + SigBit s = sigmaps.at(work->module)(cell->getPort("\\S")); + SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y")); string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0"; string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; @@ -485,8 +485,8 @@ struct SimplecWorker // casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933) string expr = stringf("%s ? %s(bool)%s : %s(bool)%s", s_expr.c_str(), - cell->type == ID($_NMUX_) ? "!" : "", b_expr.c_str(), - cell->type == ID($_NMUX_) ? "!" : "", a_expr.c_str()); + cell->type == "$_NMUX_" ? "!" : "", b_expr.c_str(), + cell->type == "$_NMUX_" ? "!" : "", a_expr.c_str()); log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + @@ -653,10 +653,10 @@ struct SimplecWorker for (Wire *w : module->wires()) { - if (w->attributes.count(ID::init)) + if (w->attributes.count("\\init")) { SigSpec sig = sigmaps.at(module)(w); - Const val = w->attributes.at(ID::init); + Const val = w->attributes.at("\\init"); val.bits.resize(GetSize(sig), State::Sx); for (int i = 0; i < GetSize(sig); i++) @@ -744,7 +744,7 @@ struct SimplecWorker struct SimplecBackend : public Backend { SimplecBackend() : Backend("simplec", "convert design to simple C code") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -763,7 +763,7 @@ struct SimplecBackend : public Backend { log("THIS COMMAND IS UNDER CONSTRUCTION\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { reserved_cids.clear(); id2cid.clear(); diff --git a/backends/smt2/Makefile.inc b/backends/smt2/Makefile.inc index fb01308bd8a..68394a90987 100644 --- a/backends/smt2/Makefile.inc +++ b/backends/smt2/Makefile.inc @@ -6,23 +6,23 @@ ifneq ($(CONFIG),emcc) # MSYS targets support yosys-smtbmc, but require a launcher script ifeq ($(CONFIG),$(filter $(CONFIG),msys2 msys2-64)) -TARGETS += $(PROGRAM_PREFIX)yosys-smtbmc.exe $(PROGRAM_PREFIX)yosys-smtbmc-script.py +TARGETS += yosys-smtbmc.exe yosys-smtbmc-script.py # Needed to find the Python interpreter for yosys-smtbmc scripts. # Override if necessary, it is only used for msys2 targets. PYTHON := $(shell cygpath -w -m $(PREFIX)/bin/python3) -$(PROGRAM_PREFIX)yosys-smtbmc-script.py: backends/smt2/smtbmc.py - $(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' \ +yosys-smtbmc-script.py: backends/smt2/smtbmc.py + $(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' \ -e "s|#!/usr/bin/env python3|#!$(PYTHON)|" < $< > $@ -$(PROGRAM_PREFIX)yosys-smtbmc.exe: misc/launcher.c $(PROGRAM_PREFIX)yosys-smtbmc-script.py +yosys-smtbmc.exe: misc/launcher.c yosys-smtbmc-script.py $(P) $(CXX) -DGUI=0 -O -s -o $@ $< # Other targets else -TARGETS += $(PROGRAM_PREFIX)yosys-smtbmc +TARGETS += yosys-smtbmc -$(PROGRAM_PREFIX)yosys-smtbmc: backends/smt2/smtbmc.py - $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' < $< > $@.new +yosys-smtbmc: backends/smt2/smtbmc.py + $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new $(Q) chmod +x $@.new $(Q) mv $@.new $@ endif diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 526b36352cb..081dcda999a 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -135,7 +135,7 @@ struct Smt2Worker log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n", log_id(conn.first), log_id(module), log_id(cell), log_id(cell->type)); - if (cell->type.in(ID($mem)) && conn.first.in(ID::RD_CLK, ID::WR_CLK)) + if (cell->type.in("$mem") && conn.first.in("\\RD_CLK", "\\WR_CLK")) { SigSpec clk = sigmap(conn.second); for (int i = 0; i < GetSize(clk); i++) @@ -143,19 +143,19 @@ struct Smt2Worker if (clk[i].wire == nullptr) continue; - if (cell->getParam(conn.first == ID::RD_CLK ? ID::RD_CLK_ENABLE : ID::WR_CLK_ENABLE)[i] != State::S1) + if (cell->getParam(conn.first == "\\RD_CLK" ? "\\RD_CLK_ENABLE" : "\\WR_CLK_ENABLE")[i] != State::S1) continue; - if (cell->getParam(conn.first == ID::RD_CLK ? ID::RD_CLK_POLARITY : ID::WR_CLK_POLARITY)[i] == State::S1) + if (cell->getParam(conn.first == "\\RD_CLK" ? "\\RD_CLK_POLARITY" : "\\WR_CLK_POLARITY")[i] == State::S1) clock_posedge.insert(clk[i]); else clock_negedge.insert(clk[i]); } } else - if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_)) && conn.first.in(ID::CLK, ID::C)) + if (cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_") && conn.first.in("\\CLK", "\\C")) { - bool posedge = (cell->type == ID($_DFF_N_)) || (cell->type == ID($dff) && cell->getParam(ID::CLK_POLARITY).as_bool()); + bool posedge = (cell->type == "$_DFF_N_") || (cell->type == "$dff" && cell->getParam("\\CLK_POLARITY").as_bool()); for (auto bit : sigmap(conn.second)) { if (posedge) clock_posedge.insert(bit); @@ -367,15 +367,15 @@ struct Smt2Worker void export_gate(RTLIL::Cell *cell, std::string expr) { - RTLIL::SigBit bit = sigmap(cell->getPort(ID::Y).as_bit()); + RTLIL::SigBit bit = sigmap(cell->getPort("\\Y").as_bit()); std::string processed_expr; for (char ch : expr) { - if (ch == 'A') processed_expr += get_bool(cell->getPort(ID::A)); - else if (ch == 'B') processed_expr += get_bool(cell->getPort(ID::B)); - else if (ch == 'C') processed_expr += get_bool(cell->getPort(ID::C)); - else if (ch == 'D') processed_expr += get_bool(cell->getPort(ID::D)); - else if (ch == 'S') processed_expr += get_bool(cell->getPort(ID::S)); + if (ch == 'A') processed_expr += get_bool(cell->getPort("\\A")); + else if (ch == 'B') processed_expr += get_bool(cell->getPort("\\B")); + else if (ch == 'C') processed_expr += get_bool(cell->getPort("\\C")); + else if (ch == 'D') processed_expr += get_bool(cell->getPort("\\D")); + else if (ch == 'S') processed_expr += get_bool(cell->getPort("\\S")); else processed_expr += ch; } @@ -391,23 +391,23 @@ struct Smt2Worker void export_bvop(RTLIL::Cell *cell, std::string expr, char type = 0) { RTLIL::SigSpec sig_a, sig_b; - RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID::Y)); - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); + RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y")); + bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); int width = GetSize(sig_y); if (type == 's' || type == 'd' || type == 'b') { - width = max(width, GetSize(cell->getPort(ID::A))); - if (cell->hasPort(ID::B)) - width = max(width, GetSize(cell->getPort(ID::B))); + width = max(width, GetSize(cell->getPort("\\A"))); + if (cell->hasPort("\\B")) + width = max(width, GetSize(cell->getPort("\\B"))); } - if (cell->hasPort(ID::A)) { - sig_a = cell->getPort(ID::A); + if (cell->hasPort("\\A")) { + sig_a = cell->getPort("\\A"); sig_a.extend_u0(width, is_signed); } - if (cell->hasPort(ID::B)) { - sig_b = cell->getPort(ID::B); + if (cell->hasPort("\\B")) { + sig_b = cell->getPort("\\B"); sig_b.extend_u0(width, is_signed && !(type == 's')); } @@ -416,7 +416,7 @@ struct Smt2Worker for (char ch : expr) { if (ch == 'A') processed_expr += get_bv(sig_a); else if (ch == 'B') processed_expr += get_bv(sig_b); - else if (ch == 'P') processed_expr += get_bv(cell->getPort(ID::B)); + else if (ch == 'P') processed_expr += get_bv(cell->getPort("\\B")); else if (ch == 'L') processed_expr += is_signed ? "a" : "l"; else if (ch == 'U') processed_expr += is_signed ? "s" : "u"; else processed_expr += ch; @@ -443,7 +443,7 @@ struct Smt2Worker void export_reduce(RTLIL::Cell *cell, std::string expr, bool identity_val) { - RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID::Y)); + RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y")); std::string processed_expr; for (char ch : expr) @@ -480,9 +480,9 @@ struct Smt2Worker exported_cells.insert(cell); recursive_cells.insert(cell); - if (cell->type == ID($initstate)) + if (cell->type == "$initstate") { - SigBit bit = sigmap(cell->getPort(ID::Y).as_bit()); + SigBit bit = sigmap(cell->getPort("\\Y").as_bit()); decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool (|%s_is| state)) ; %s\n", get_id(module), idcounter, get_id(module), get_id(module), log_signal(bit))); register_bool(bit, idcounter++); @@ -490,142 +490,124 @@ struct Smt2Worker return; } - if (cell->type.in(ID($_FF_), ID($_DFF_P_), ID($_DFF_N_))) + if (cell->type.in("$_FF_", "$_DFF_P_", "$_DFF_N_")) { registers.insert(cell); - makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(cell->getPort(ID::Q))); - register_bool(cell->getPort(ID::Q), idcounter++); + makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(cell->getPort("\\Q"))); + register_bool(cell->getPort("\\Q"), idcounter++); recursive_cells.erase(cell); return; } - if (cell->type == ID($_BUF_)) return export_gate(cell, "A"); - if (cell->type == ID($_NOT_)) return export_gate(cell, "(not A)"); - if (cell->type == ID($_AND_)) return export_gate(cell, "(and A B)"); - if (cell->type == ID($_NAND_)) return export_gate(cell, "(not (and A B))"); - if (cell->type == ID($_OR_)) return export_gate(cell, "(or A B)"); - if (cell->type == ID($_NOR_)) return export_gate(cell, "(not (or A B))"); - if (cell->type == ID($_XOR_)) return export_gate(cell, "(xor A B)"); - if (cell->type == ID($_XNOR_)) return export_gate(cell, "(not (xor A B))"); - if (cell->type == ID($_ANDNOT_)) return export_gate(cell, "(and A (not B))"); - if (cell->type == ID($_ORNOT_)) return export_gate(cell, "(or A (not B))"); - if (cell->type == ID($_MUX_)) return export_gate(cell, "(ite S B A)"); - if (cell->type == ID($_NMUX_)) return export_gate(cell, "(not (ite S B A))"); - if (cell->type == ID($_AOI3_)) return export_gate(cell, "(not (or (and A B) C))"); - if (cell->type == ID($_OAI3_)) return export_gate(cell, "(not (and (or A B) C))"); - if (cell->type == ID($_AOI4_)) return export_gate(cell, "(not (or (and A B) (and C D)))"); - if (cell->type == ID($_OAI4_)) return export_gate(cell, "(not (and (or A B) (or C D)))"); + if (cell->type == "$_BUF_") return export_gate(cell, "A"); + if (cell->type == "$_NOT_") return export_gate(cell, "(not A)"); + if (cell->type == "$_AND_") return export_gate(cell, "(and A B)"); + if (cell->type == "$_NAND_") return export_gate(cell, "(not (and A B))"); + if (cell->type == "$_OR_") return export_gate(cell, "(or A B)"); + if (cell->type == "$_NOR_") return export_gate(cell, "(not (or A B))"); + if (cell->type == "$_XOR_") return export_gate(cell, "(xor A B)"); + if (cell->type == "$_XNOR_") return export_gate(cell, "(not (xor A 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 == "$_MUX_") return export_gate(cell, "(ite S B A)"); + if (cell->type == "$_NMUX_") return export_gate(cell, "(not (ite S B A))"); + if (cell->type == "$_AOI3_") return export_gate(cell, "(not (or (and A B) C))"); + if (cell->type == "$_OAI3_") return export_gate(cell, "(not (and (or A B) C))"); + if (cell->type == "$_AOI4_") return export_gate(cell, "(not (or (and A B) (and C D)))"); + if (cell->type == "$_OAI4_") return export_gate(cell, "(not (and (or A B) (or C D)))"); // FIXME: $lut if (bvmode) { - if (cell->type.in(ID($ff), ID($dff))) + if (cell->type.in("$ff", "$dff")) { registers.insert(cell); - makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(cell->getPort(ID::Q)), log_signal(cell->getPort(ID::Q))); - register_bv(cell->getPort(ID::Q), idcounter++); + makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q"))); + register_bv(cell->getPort("\\Q"), idcounter++); recursive_cells.erase(cell); return; } - if (cell->type.in(ID($anyconst), ID($anyseq), ID($allconst), ID($allseq))) + if (cell->type.in("$anyconst", "$anyseq", "$allconst", "$allseq")) { registers.insert(cell); - string infostr = cell->attributes.count(ID::src) ? cell->attributes.at(ID::src).decode_string().c_str() : get_id(cell); - if (cell->attributes.count(ID::reg)) - infostr += " " + cell->attributes.at(ID::reg).decode_string(); - decls.push_back(stringf("; yosys-smt2-%s %s#%d %d %s\n", cell->type.c_str() + 1, get_id(module), idcounter, GetSize(cell->getPort(ID::Y)), infostr.c_str())); - if (cell->getPort(ID::Y).is_wire() && cell->getPort(ID::Y).as_wire()->get_bool_attribute(ID::maximize)){ - decls.push_back(stringf("; yosys-smt2-maximize %s#%d\n", get_id(module), idcounter)); - log("Wire %s is maximized\n", cell->getPort(ID::Y).as_wire()->name.str().c_str()); - } - else if (cell->getPort(ID::Y).is_wire() && cell->getPort(ID::Y).as_wire()->get_bool_attribute(ID::minimize)){ - decls.push_back(stringf("; yosys-smt2-minimize %s#%d\n", get_id(module), idcounter)); - log("Wire %s is minimized\n", cell->getPort(ID::Y).as_wire()->name.str().c_str()); - } - makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(cell->getPort(ID::Y)), log_signal(cell->getPort(ID::Y))); - if (cell->type == ID($anyseq)) + string infostr = cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell); + if (cell->attributes.count("\\reg")) + infostr += " " + cell->attributes.at("\\reg").decode_string(); + decls.push_back(stringf("; yosys-smt2-%s %s#%d %d %s\n", cell->type.c_str() + 1, get_id(module), idcounter, GetSize(cell->getPort("\\Y")), infostr.c_str())); + makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(cell->getPort("\\Y")), log_signal(cell->getPort("\\Y"))); + if (cell->type == "$anyseq") ex_input_eq.push_back(stringf(" (= (|%s#%d| state) (|%s#%d| other_state))", get_id(module), idcounter, get_id(module), idcounter)); - register_bv(cell->getPort(ID::Y), idcounter++); + register_bv(cell->getPort("\\Y"), idcounter++); recursive_cells.erase(cell); return; } - if (cell->type == ID($and)) return export_bvop(cell, "(bvand A B)"); - if (cell->type == ID($or)) return export_bvop(cell, "(bvor A B)"); - if (cell->type == ID($xor)) return export_bvop(cell, "(bvxor A B)"); - if (cell->type == ID($xnor)) return export_bvop(cell, "(bvxnor A B)"); + if (cell->type == "$and") return export_bvop(cell, "(bvand A B)"); + if (cell->type == "$or") return export_bvop(cell, "(bvor A B)"); + if (cell->type == "$xor") return export_bvop(cell, "(bvxor A B)"); + if (cell->type == "$xnor") return export_bvop(cell, "(bvxnor A B)"); - if (cell->type == ID($shl)) return export_bvop(cell, "(bvshl A B)", 's'); - if (cell->type == ID($shr)) return export_bvop(cell, "(bvlshr A B)", 's'); - if (cell->type == ID($sshl)) return export_bvop(cell, "(bvshl A B)", 's'); - if (cell->type == ID($sshr)) return export_bvop(cell, "(bvLshr A B)", 's'); + if (cell->type == "$shl") return export_bvop(cell, "(bvshl A B)", 's'); + if (cell->type == "$shr") return export_bvop(cell, "(bvlshr A B)", 's'); + if (cell->type == "$sshl") return export_bvop(cell, "(bvshl A B)", 's'); + if (cell->type == "$sshr") return export_bvop(cell, "(bvLshr A B)", 's'); - if (cell->type.in(ID($shift), ID($shiftx))) { - if (cell->getParam(ID::B_SIGNED).as_bool()) { + if (cell->type.in("$shift", "$shiftx")) { + if (cell->getParam("\\B_SIGNED").as_bool()) { return export_bvop(cell, stringf("(ite (bvsge P #b%0*d) " "(bvlshr A B) (bvlshr A (bvneg B)))", - GetSize(cell->getPort(ID::B)), 0), 's'); + GetSize(cell->getPort("\\B")), 0), 's'); } else { return export_bvop(cell, "(bvlshr A B)", 's'); } } - if (cell->type == ID($lt)) return export_bvop(cell, "(bvUlt A B)", 'b'); - if (cell->type == ID($le)) return export_bvop(cell, "(bvUle A B)", 'b'); - if (cell->type == ID($ge)) return export_bvop(cell, "(bvUge A B)", 'b'); - if (cell->type == ID($gt)) return export_bvop(cell, "(bvUgt A B)", 'b'); - - if (cell->type == ID($ne)) return export_bvop(cell, "(distinct A B)", 'b'); - if (cell->type == ID($nex)) return export_bvop(cell, "(distinct A B)", 'b'); - if (cell->type == ID($eq)) return export_bvop(cell, "(= A B)", 'b'); - if (cell->type == ID($eqx)) return export_bvop(cell, "(= A B)", 'b'); - - if (cell->type == ID($not)) return export_bvop(cell, "(bvnot A)"); - if (cell->type == ID($pos)) return export_bvop(cell, "A"); - if (cell->type == ID($neg)) return export_bvop(cell, "(bvneg A)"); - - if (cell->type == ID($add)) return export_bvop(cell, "(bvadd A B)"); - if (cell->type == ID($sub)) return export_bvop(cell, "(bvsub A B)"); - if (cell->type == ID($mul)) return export_bvop(cell, "(bvmul A B)"); - if (cell->type == ID($div)) return export_bvop(cell, "(bvUdiv A B)", 'd'); - // "rem" = truncating modulo - if (cell->type == ID($mod)) return export_bvop(cell, "(bvUrem A B)", 'd'); - // "mod" = flooring modulo - if (cell->type == ID($modfloor)) { - // bvumod doesn't exist because it's the same as bvurem - if (cell->getParam(ID::A_SIGNED).as_bool()) { - return export_bvop(cell, "(bvsmod A B)", 'd'); - } else { - return export_bvop(cell, "(bvurem A B)", 'd'); - } - } - - if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool)) && - 2*GetSize(cell->getPort(ID::A).chunks()) < GetSize(cell->getPort(ID::A))) { - bool is_and = cell->type == ID($reduce_and); - string bits(GetSize(cell->getPort(ID::A)), is_and ? '1' : '0'); + if (cell->type == "$lt") return export_bvop(cell, "(bvUlt A B)", 'b'); + if (cell->type == "$le") return export_bvop(cell, "(bvUle A B)", 'b'); + if (cell->type == "$ge") return export_bvop(cell, "(bvUge A B)", 'b'); + if (cell->type == "$gt") return export_bvop(cell, "(bvUgt A B)", 'b'); + + if (cell->type == "$ne") return export_bvop(cell, "(distinct A B)", 'b'); + if (cell->type == "$nex") return export_bvop(cell, "(distinct A B)", 'b'); + if (cell->type == "$eq") return export_bvop(cell, "(= A B)", 'b'); + if (cell->type == "$eqx") return export_bvop(cell, "(= A B)", 'b'); + + if (cell->type == "$not") return export_bvop(cell, "(bvnot A)"); + if (cell->type == "$pos") return export_bvop(cell, "A"); + if (cell->type == "$neg") return export_bvop(cell, "(bvneg A)"); + + if (cell->type == "$add") return export_bvop(cell, "(bvadd A B)"); + if (cell->type == "$sub") return export_bvop(cell, "(bvsub A B)"); + if (cell->type == "$mul") return export_bvop(cell, "(bvmul A B)"); + if (cell->type == "$div") return export_bvop(cell, "(bvUdiv A B)", 'd'); + if (cell->type == "$mod") return export_bvop(cell, "(bvUrem A B)", 'd'); + + if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool") && + 2*GetSize(cell->getPort("\\A").chunks()) < GetSize(cell->getPort("\\A"))) { + bool is_and = cell->type == "$reduce_and"; + string bits(GetSize(cell->getPort("\\A")), is_and ? '1' : '0'); return export_bvop(cell, stringf("(%s A #b%s)", is_and ? "=" : "distinct", bits.c_str()), 'b'); } - if (cell->type == ID($reduce_and)) return export_reduce(cell, "(and A)", true); - if (cell->type == ID($reduce_or)) return export_reduce(cell, "(or A)", false); - if (cell->type == ID($reduce_xor)) return export_reduce(cell, "(xor A)", false); - if (cell->type == ID($reduce_xnor)) return export_reduce(cell, "(not (xor A))", false); - if (cell->type == ID($reduce_bool)) return export_reduce(cell, "(or A)", false); + if (cell->type == "$reduce_and") return export_reduce(cell, "(and A)", true); + if (cell->type == "$reduce_or") return export_reduce(cell, "(or A)", false); + if (cell->type == "$reduce_xor") return export_reduce(cell, "(xor A)", false); + if (cell->type == "$reduce_xnor") return export_reduce(cell, "(not (xor A))", false); + if (cell->type == "$reduce_bool") return export_reduce(cell, "(or A)", false); - if (cell->type == ID($logic_not)) return export_reduce(cell, "(not (or A))", false); - if (cell->type == ID($logic_and)) return export_reduce(cell, "(and (or A) (or B))", false); - if (cell->type == ID($logic_or)) return export_reduce(cell, "(or A B)", false); + if (cell->type == "$logic_not") return export_reduce(cell, "(not (or A))", 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.in(ID($mux), ID($pmux))) + if (cell->type.in("$mux", "$pmux")) { - int width = GetSize(cell->getPort(ID::Y)); - std::string processed_expr = get_bv(cell->getPort(ID::A)); + int width = GetSize(cell->getPort("\\Y")); + std::string processed_expr = get_bv(cell->getPort("\\A")); - RTLIL::SigSpec sig_b = cell->getPort(ID::B); - RTLIL::SigSpec sig_s = cell->getPort(ID::S); + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + RTLIL::SigSpec sig_s = cell->getPort("\\S"); get_bv(sig_b); get_bv(sig_s); @@ -636,7 +618,7 @@ struct Smt2Worker if (verbose) log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell)); - RTLIL::SigSpec sig = sigmap(cell->getPort(ID::Y)); + RTLIL::SigSpec sig = sigmap(cell->getPort("\\Y")); decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", get_id(module), idcounter, get_id(module), width, processed_expr.c_str(), log_signal(sig))); register_bv(sig, idcounter++); @@ -647,19 +629,19 @@ struct Smt2Worker // FIXME: $slice $concat } - if (memmode && cell->type == ID($mem)) + if (memmode && cell->type == "$mem") { int arrayid = idcounter++; memarrays[cell] = arrayid; - int abits = cell->getParam(ID::ABITS).as_int(); - int width = cell->getParam(ID::WIDTH).as_int(); - int rd_ports = cell->getParam(ID::RD_PORTS).as_int(); - int wr_ports = cell->getParam(ID::WR_PORTS).as_int(); + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); + int rd_ports = cell->getParam("\\RD_PORTS").as_int(); + int wr_ports = cell->getParam("\\WR_PORTS").as_int(); bool async_read = false; - if (!cell->getParam(ID::WR_CLK_ENABLE).is_fully_ones()) { - if (!cell->getParam(ID::WR_CLK_ENABLE).is_fully_zero()) + if (!cell->getParam("\\WR_CLK_ENABLE").is_fully_ones()) { + if (!cell->getParam("\\WR_CLK_ENABLE").is_fully_zero()) log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module)); async_read = true; } @@ -675,8 +657,8 @@ struct Smt2Worker if (statebv) { - int mem_size = cell->getParam(ID::SIZE).as_int(); - int mem_offset = cell->getParam(ID::OFFSET).as_int(); + int mem_size = cell->getParam("\\SIZE").as_int(); + int mem_offset = cell->getParam("\\OFFSET").as_int(); makebits(memstate, width*mem_size, get_id(cell)); decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (_ BitVec %d) (|%s| state))\n", @@ -684,11 +666,11 @@ struct Smt2Worker for (int i = 0; i < rd_ports; i++) { - SigSpec addr_sig = cell->getPort(ID::RD_ADDR).extract(abits*i, abits); - SigSpec data_sig = cell->getPort(ID::RD_DATA).extract(width*i, width); + SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(abits*i, abits); + SigSpec data_sig = cell->getPort("\\RD_DATA").extract(width*i, width); std::string addr = get_bv(addr_sig); - if (cell->getParam(ID::RD_CLK_ENABLE).extract(i).as_bool()) + if (cell->getParam("\\RD_CLK_ENABLE").extract(i).as_bool()) log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module)); @@ -727,11 +709,11 @@ struct Smt2Worker for (int i = 0; i < rd_ports; i++) { - SigSpec addr_sig = cell->getPort(ID::RD_ADDR).extract(abits*i, abits); - SigSpec data_sig = cell->getPort(ID::RD_DATA).extract(width*i, width); + SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(abits*i, abits); + SigSpec data_sig = cell->getPort("\\RD_DATA").extract(width*i, width); std::string addr = get_bv(addr_sig); - if (cell->getParam(ID::RD_CLK_ENABLE).extract(i).as_bool()) + if (cell->getParam("\\RD_CLK_ENABLE").extract(i).as_bool()) log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module)); @@ -811,9 +793,9 @@ struct Smt2Worker pool reg_bits; for (auto cell : module->cells()) - if (cell->type.in(ID($ff), ID($dff), ID($_FF_), ID($_DFF_P_), ID($_DFF_N_))) { + if (cell->type.in("$ff", "$dff", "$_FF_", "$_DFF_P_", "$_DFF_N_")) { // not using sigmap -- we want the net directly at the dff output - for (auto bit : cell->getPort(ID::Q)) + for (auto bit : cell->getPort("\\Q")) reg_bits.insert(bit); } @@ -822,7 +804,7 @@ struct Smt2Worker for (auto bit : SigSpec(wire)) if (reg_bits.count(bit)) is_register = true; - if (wire->port_id || is_register || wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name[0] == '\\')) { + if (wire->port_id || is_register || wire->get_bool_attribute("\\keep") || (wiresmode && wire->name[0] == '\\')) { RTLIL::SigSpec sig = sigmap(wire); if (wire->port_input) decls.push_back(stringf("; yosys-smt2-input %s %d\n", get_id(wire), wire->width)); @@ -830,7 +812,7 @@ struct Smt2Worker decls.push_back(stringf("; yosys-smt2-output %s %d\n", get_id(wire), wire->width)); if (is_register) decls.push_back(stringf("; yosys-smt2-register %s %d\n", get_id(wire), wire->width)); - if (wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name[0] == '\\')) + if (wire->get_bool_attribute("\\keep") || (wiresmode && wire->name[0] == '\\')) decls.push_back(stringf("; yosys-smt2-wire %s %d\n", get_id(wire), wire->width)); if (GetSize(wire) == 1 && (clock_posedge.count(sig) || clock_negedge.count(sig))) decls.push_back(stringf("; yosys-smt2-clock %s%s%s\n", get_id(wire), @@ -864,9 +846,9 @@ struct Smt2Worker vector init_list; for (auto wire : module->wires()) - if (wire->attributes.count(ID::init)) { + if (wire->attributes.count("\\init")) { RTLIL::SigSpec sig = sigmap(wire); - Const val = wire->attributes.at(ID::init); + Const val = wire->attributes.at("\\init"); val.bits.resize(GetSize(sig), State::Sx); if (bvmode && GetSize(sig) > 1) { Const mask(State::S1, GetSize(sig)); @@ -895,31 +877,31 @@ struct Smt2Worker for (auto cell : module->cells()) { - if (cell->type.in(ID($assert), ID($assume), ID($cover))) + if (cell->type.in("$assert", "$assume", "$cover")) { - int &id = cell->type == ID($assert) ? assert_id : - cell->type == ID($assume) ? assume_id : - cell->type == ID($cover) ? cover_id : *(int*)nullptr; + int &id = cell->type == "$assert" ? assert_id : + cell->type == "$assume" ? assume_id : + cell->type == "$cover" ? cover_id : *(int*)nullptr; - char postfix = cell->type == ID($assert) ? 'a' : - cell->type == ID($assume) ? 'u' : - cell->type == ID($cover) ? 'c' : 0; + char postfix = cell->type == "$assert" ? 'a' : + cell->type == "$assume" ? 'u' : + cell->type == "$cover" ? 'c' : 0; - string name_a = get_bool(cell->getPort(ID::A)); - string name_en = get_bool(cell->getPort(ID::EN)); - string infostr = (cell->name[0] == '$' && cell->attributes.count(ID::src)) ? cell->attributes.at(ID::src).decode_string() : get_id(cell); + string name_a = get_bool(cell->getPort("\\A")); + string name_en = get_bool(cell->getPort("\\EN")); + string infostr = (cell->name[0] == '$' && cell->attributes.count("\\src")) ? cell->attributes.at("\\src").decode_string() : get_id(cell); decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, infostr.c_str())); - if (cell->type == ID($cover)) + if (cell->type == "$cover") decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (and %s %s)) ; %s\n", get_id(module), postfix, id, get_id(module), name_a.c_str(), name_en.c_str(), get_id(cell))); else decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (or %s (not %s))) ; %s\n", get_id(module), postfix, id, get_id(module), name_a.c_str(), name_en.c_str(), get_id(cell))); - if (cell->type == ID($assert)) + if (cell->type == "$assert") assert_list.push_back(stringf("(|%s_a %d| state)", get_id(module), id)); - else if (cell->type == ID($assume)) + else if (cell->type == "$assume") assume_list.push_back(stringf("(|%s_u %d| state)", get_id(module), id)); id++; @@ -975,44 +957,44 @@ struct Smt2Worker for (auto cell : this_regs) { - if (cell->type.in(ID($_FF_), ID($_DFF_P_), ID($_DFF_N_))) + if (cell->type.in("$_FF_", "$_DFF_P_", "$_DFF_N_")) { - std::string expr_d = get_bool(cell->getPort(ID::D)); - std::string expr_q = get_bool(cell->getPort(ID::Q), "next_state"); - trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort(ID::Q)))); - ex_state_eq.push_back(stringf("(= %s %s)", get_bool(cell->getPort(ID::Q)).c_str(), get_bool(cell->getPort(ID::Q), "other_state").c_str())); + std::string expr_d = get_bool(cell->getPort("\\D")); + std::string expr_q = get_bool(cell->getPort("\\Q"), "next_state"); + trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort("\\Q")))); + ex_state_eq.push_back(stringf("(= %s %s)", get_bool(cell->getPort("\\Q")).c_str(), get_bool(cell->getPort("\\Q"), "other_state").c_str())); } - if (cell->type.in(ID($ff), ID($dff))) + if (cell->type.in("$ff", "$dff")) { - std::string expr_d = get_bv(cell->getPort(ID::D)); - std::string expr_q = get_bv(cell->getPort(ID::Q), "next_state"); - trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort(ID::Q)))); - ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort(ID::Q)).c_str(), get_bv(cell->getPort(ID::Q), "other_state").c_str())); + std::string expr_d = get_bv(cell->getPort("\\D")); + std::string expr_q = get_bv(cell->getPort("\\Q"), "next_state"); + trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort("\\Q")))); + ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort("\\Q")).c_str(), get_bv(cell->getPort("\\Q"), "other_state").c_str())); } - if (cell->type.in(ID($anyconst), ID($allconst))) + if (cell->type.in("$anyconst", "$allconst")) { - std::string expr_d = get_bv(cell->getPort(ID::Y)); - std::string expr_q = get_bv(cell->getPort(ID::Y), "next_state"); - trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort(ID::Y)))); - if (cell->type == ID($anyconst)) - ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort(ID::Y)).c_str(), get_bv(cell->getPort(ID::Y), "other_state").c_str())); + std::string expr_d = get_bv(cell->getPort("\\Y")); + std::string expr_q = get_bv(cell->getPort("\\Y"), "next_state"); + trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort("\\Y")))); + if (cell->type == "$anyconst") + ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort("\\Y")).c_str(), get_bv(cell->getPort("\\Y"), "other_state").c_str())); } - if (cell->type == ID($mem)) + if (cell->type == "$mem") { int arrayid = memarrays.at(cell); - int abits = cell->getParam(ID::ABITS).as_int(); - int width = cell->getParam(ID::WIDTH).as_int(); - int wr_ports = cell->getParam(ID::WR_PORTS).as_int(); + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); + int wr_ports = cell->getParam("\\WR_PORTS").as_int(); bool async_read = false; string initial_memstate, final_memstate; - if (!cell->getParam(ID::WR_CLK_ENABLE).is_fully_ones()) { - log_assert(cell->getParam(ID::WR_CLK_ENABLE).is_fully_zero()); + if (!cell->getParam("\\WR_CLK_ENABLE").is_fully_ones()) { + log_assert(cell->getParam("\\WR_CLK_ENABLE").is_fully_zero()); async_read = true; initial_memstate = stringf("%s#%d#0", get_id(module), arrayid); final_memstate = stringf("%s#%d#final", get_id(module), arrayid); @@ -1020,8 +1002,8 @@ struct Smt2Worker if (statebv) { - int mem_size = cell->getParam(ID::SIZE).as_int(); - int mem_offset = cell->getParam(ID::OFFSET).as_int(); + int mem_size = cell->getParam("\\SIZE").as_int(); + int mem_offset = cell->getParam("\\OFFSET").as_int(); if (async_read) { makebits(final_memstate, width*mem_size, get_id(cell)); @@ -1029,9 +1011,9 @@ struct Smt2Worker for (int i = 0; i < wr_ports; i++) { - SigSpec addr_sig = cell->getPort(ID::WR_ADDR).extract(abits*i, abits); - SigSpec data_sig = cell->getPort(ID::WR_DATA).extract(width*i, width); - SigSpec mask_sig = cell->getPort(ID::WR_EN).extract(width*i, width); + SigSpec addr_sig = cell->getPort("\\WR_ADDR").extract(abits*i, abits); + SigSpec data_sig = cell->getPort("\\WR_DATA").extract(width*i, width); + SigSpec mask_sig = cell->getPort("\\WR_EN").extract(width*i, width); std::string addr = get_bv(addr_sig); std::string data = get_bv(data_sig); @@ -1076,9 +1058,9 @@ struct Smt2Worker for (int i = 0; i < wr_ports; i++) { - SigSpec addr_sig = cell->getPort(ID::WR_ADDR).extract(abits*i, abits); - SigSpec data_sig = cell->getPort(ID::WR_DATA).extract(width*i, width); - SigSpec mask_sig = cell->getPort(ID::WR_EN).extract(width*i, width); + SigSpec addr_sig = cell->getPort("\\WR_ADDR").extract(abits*i, abits); + SigSpec data_sig = cell->getPort("\\WR_DATA").extract(width*i, width); + SigSpec mask_sig = cell->getPort("\\WR_EN").extract(width*i, width); std::string addr = get_bv(addr_sig); std::string data = get_bv(data_sig); @@ -1114,8 +1096,8 @@ struct Smt2Worker if (async_read) hier.push_back(stringf(" (= %s (|%s| state)) ; %s\n", expr_d.c_str(), final_memstate.c_str(), get_id(cell))); - Const init_data = cell->getParam(ID::INIT); - int memsize = cell->getParam(ID::SIZE).as_int(); + Const init_data = cell->getParam("\\INIT"); + int memsize = cell->getParam("\\SIZE").as_int(); for (int i = 0; i < memsize; i++) { @@ -1280,7 +1262,7 @@ struct Smt2Worker struct Smt2Backend : public Backend { Smt2Backend() : Backend("smt2", "write design to SMT-LIBv2 file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1404,7 +1386,7 @@ struct Smt2Backend : public Backend { log("\n"); log("For this proof we create the following template (test.tpl).\n"); log("\n"); - log(" ; we need QF_UFBV for this proof\n"); + log(" ; we need QF_UFBV for this poof\n"); log(" (set-logic QF_UFBV)\n"); log("\n"); log(" ; insert the auto-generated code here\n"); @@ -1436,7 +1418,7 @@ struct Smt2Backend : public Backend { log("from non-zero to zero in the test design.\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::ifstream template_f; bool bvmode = true, memmode = true, wiresmode = false, verbose = false, statebv = false, statedt = false; @@ -1518,11 +1500,11 @@ struct Smt2Backend : public Backend { // extract module dependencies std::map> module_deps; - for (auto mod : design->modules()) { - module_deps[mod] = std::set(); - for (auto cell : mod->cells()) - if (design->has(cell->type)) - module_deps[mod].insert(design->module(cell->type)); + for (auto &mod_it : design->modules_) { + module_deps[mod_it.second] = std::set(); + for (auto &cell_it : mod_it.second->cells_) + if (design->modules_.count(cell_it.second->type) > 0) + module_deps[mod_it.second].insert(design->modules_.at(cell_it.second->type)); } // simple good-enough topological sort @@ -1533,12 +1515,12 @@ struct Smt2Backend : public Backend { for (auto &dep : it.second) if (module_deps.count(dep) > 0) goto not_ready_yet; - // log("Next in topological sort: %s\n", log_id(it.first->name)); + // log("Next in topological sort: %s\n", RTLIL::id2cstr(it.first->name)); sorted_modules.push_back(it.first); not_ready_yet:; } if (sorted_modules_idx == sorted_modules.size()) - log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name)); + log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", RTLIL::id2cstr(module_deps.begin()->first->name)); while (sorted_modules_idx < sorted_modules.size()) module_deps.erase(sorted_modules.at(sorted_modules_idx++)); } @@ -1550,7 +1532,7 @@ struct Smt2Backend : public Backend { for (auto module : sorted_modules) for (auto cell : module->cells()) - if (cell->type.in(ID($allconst), ID($allseq))) + if (cell->type.in("$allconst", "$allseq")) goto found_forall; if (0) { found_forall: diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index 03f001bfd09..3d6d3e1b39d 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -49,12 +49,12 @@ smtcinit = False smtctop = None noinit = False -binarymode = False so = SmtOpts() def usage(): - print(os.path.basename(sys.argv[0]) + """ [options] + print(""" +yosys-smtbmc [options] -t -t : @@ -150,9 +150,6 @@ def usage(): add time steps at the end of the trace when creating a counter example (this additional time steps will still be constrained by assumptions) - - --binary - dump anyconst values as raw bit strings """ + so.helpmsg()) sys.exit(1) @@ -161,7 +158,7 @@ def usage(): opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:igcm:", so.longopts + ["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "btorwit=", "presat", "dump-vcd=", "dump-vlogtb=", "vlogtb-top=", "dump-smtc=", "dump-all", "noinfo", "append=", - "smtc-init", "smtc-top=", "noinit", "binary"]) + "smtc-init", "smtc-top=", "noinit"]) except: usage() @@ -232,8 +229,6 @@ def usage(): covermode = True elif o == "-m": topmod = a - elif o == "--binary": - binarymode = True elif so.handle(o, a): pass else: @@ -1094,15 +1089,9 @@ def print_anyconsts_worker(mod, state, path): for fun, info in smt.modinfo[mod].anyconsts.items(): if info[1] is None: - if not binarymode: - print_msg("Value for anyconst in %s (%s): %d" % (path, info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state))))) - else: - print_msg("Value for anyconst in %s (%s): %s" % (path, info[0], smt.bv2bin(smt.get("(|%s| %s)" % (fun, state))))) + print_msg("Value for anyconst in %s (%s): %d" % (path, info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state))))) else: - if not binarymode: - print_msg("Value for anyconst %s.%s (%s): %d" % (path, info[1], info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state))))) - else: - print_msg("Value for anyconst %s.%s (%s): %s" % (path, info[1], info[0], smt.bv2bin(smt.get("(|%s| %s)" % (fun, state))))) + print_msg("Value for anyconst %s.%s (%s): %d" % (path, info[1], info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state))))) def print_anyconsts(state): @@ -1169,8 +1158,6 @@ def smt_forall_assert(): global asserts_cache_dirty asserts_cache_dirty = False - assert (len(smt.modinfo[topmod].maximize) + len(smt.modinfo[topmod].minimize) <= 1) - def make_assert_expr(asserts_cache): expr = list() for lst in asserts_cache: @@ -1249,18 +1236,6 @@ def make_new_expr(new_expr, expr): smt.write("".join(assert_expr)) - if len(smt.modinfo[topmod].maximize) > 0: - for s in states: - if s in used_states_db: - smt.write("(maximize (|%s| %s))\n" % (smt.modinfo[topmod].maximize.copy().pop(), s)) - break - - if len(smt.modinfo[topmod].minimize) > 0: - for s in states: - if s in used_states_db: - smt.write("(minimize (|%s| %s))\n" % (smt.modinfo[topmod].minimize.copy().pop(), s)) - break - def smt_push(): global asserts_cache_dirty asserts_cache_dirty = True @@ -1511,7 +1486,7 @@ def smt_check_sat(): smt_assert_consequent(get_constr_expr(constr_assumes, i)) print_msg("Re-solving with appended steps..") if smt_check_sat() == "unsat": - print("%s Cannot append steps without violating assumptions!" % smt.timestamp()) + print("%s Cannot appended steps without violating assumptions!" % smt.timestamp()) retstatus = "FAILED" break print_anyconsts(step) @@ -1548,7 +1523,7 @@ def smt_check_sat(): break smt_pop() - if retstatus == "FAILED" or retstatus == "PREUNSAT": + if not retstatus: break else: # gentrace @@ -1557,9 +1532,8 @@ def smt_check_sat(): smt_assert(get_constr_expr(constr_asserts, i)) print_msg("Solving for step %d.." % (last_check_step)) - status = smt_check_sat() - if status != "sat": - print("%s No solution found! (%s)" % (smt.timestamp(), status)) + if smt_check_sat() != "sat": + print("%s No solution found!" % smt.timestamp()) retstatus = "FAILED" break @@ -1569,7 +1543,7 @@ def smt_check_sat(): step += step_size - if gentrace and retstatus == "PASSED": + if gentrace and retstatus: print_anyconsts(0) write_trace(0, num_steps, '%') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 72ab39d396f..1df996aa7b8 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -39,7 +39,7 @@ smtio_stacksize = 128 * 1024 * 1024 if os.uname().sysname == "Darwin": # MacOS has rather conservative stack limits - smtio_stacksize = 8 * 1024 * 1024 + smtio_stacksize = 16 * 1024 * 1024 if current_rlimit_stack[1] != resource.RLIM_INFINITY: smtio_stacksize = min(smtio_stacksize, current_rlimit_stack[1]) if current_rlimit_stack[0] < smtio_stacksize: @@ -101,8 +101,6 @@ def __init__(self): self.cells = dict() self.asserts = dict() self.covers = dict() - self.maximize = set() - self.minimize = set() self.anyconsts = dict() self.anyseqs = dict() self.allconsts = dict() @@ -121,7 +119,6 @@ def __init__(self, opts=None): self.logic_bv = True self.logic_dt = False self.forall = False - self.timeout = 0 self.produce_models = True self.smt2cache = [list()] self.p = None @@ -136,7 +133,6 @@ def __init__(self, opts=None): self.debug_file = opts.debug_file self.dummy_file = opts.dummy_file self.timeinfo = opts.timeinfo - self.timeout = opts.timeout self.unroll = opts.unroll self.noincr = opts.noincr self.info_stmts = opts.info_stmts @@ -149,7 +145,6 @@ def __init__(self, opts=None): self.debug_file = None self.dummy_file = None self.timeinfo = os.name != "nt" - self.timeout = 0 self.unroll = False self.noincr = False self.info_stmts = list() @@ -175,32 +170,22 @@ def setup(self): self.unroll = False if self.solver == "yices": - if self.noincr or self.forall: + if self.noincr: self.popen_vargs = ['yices-smt2'] + self.solver_opts else: self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts - if self.timeout != 0: - self.popen_vargs.append('-t') - self.popen_vargs.append('%d' % self.timeout); if self.solver == "z3": self.popen_vargs = ['z3', '-smt2', '-in'] + self.solver_opts - if self.timeout != 0: - self.popen_vargs.append('-T:%d' % self.timeout); if self.solver == "cvc4": if self.noincr: self.popen_vargs = ['cvc4', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts else: self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts - if self.timeout != 0: - self.popen_vargs.append('--tlimit=%d000' % self.timeout); if self.solver == "mathsat": self.popen_vargs = ['mathsat'] + self.solver_opts - if self.timeout != 0: - print('timeout option is not supported for mathsat.') - sys.exit(1) if self.solver == "boolector": if self.noincr: @@ -208,9 +193,6 @@ def setup(self): else: self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts self.unroll = True - if self.timeout != 0: - print('timeout option is not supported for boolector.') - sys.exit(1) if self.solver == "abc": if len(self.solver_opts) > 0: @@ -220,9 +202,6 @@ def setup(self): self.logic_ax = False self.unroll = True self.noincr = True - if self.timeout != 0: - print('timeout option is not supported for abc.') - sys.exit(1) if self.solver == "dummy": assert self.dummy_file is not None @@ -251,16 +230,12 @@ def setup(self): if self.logic_uf: self.logic += "UF" if self.logic_bv: self.logic += "BV" if self.logic_dt: self.logic = "ALL" - if self.solver == "yices" and self.forall: self.logic = "BV" self.setup_done = True for stmt in self.info_stmts: self.write(stmt) - if self.forall and self.solver == "yices": - self.write("(set-option :yices-ef-max-iters 1000000000)") - if self.produce_models: self.write("(set-option :produce-models true)") @@ -329,11 +304,7 @@ def p_thread_main(self): def p_open(self): assert self.p is None - try: - self.p = subprocess.Popen(self.popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - except FileNotFoundError: - print("%s SMT Solver '%s' not found in path." % (self.timestamp(), self.popen_vargs[0]), flush=True) - sys.exit(1) + self.p = subprocess.Popen(self.popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) running_solvers[self.p_index] = self.p self.p_running = True self.p_next = None @@ -527,12 +498,6 @@ def info(self, stmt): if fields[1] == "yosys-smt2-cover": self.modinfo[self.curmod].covers["%s_c %s" % (self.curmod, fields[2])] = fields[3] - if fields[1] == "yosys-smt2-maximize": - self.modinfo[self.curmod].maximize.add(fields[2]) - - if fields[1] == "yosys-smt2-minimize": - self.modinfo[self.curmod].minimize.add(fields[2]) - if fields[1] == "yosys-smt2-anyconst": self.modinfo[self.curmod].anyconsts[fields[2]] = (fields[4], None if len(fields) <= 5 else fields[5]) self.modinfo[self.curmod].asize[fields[2]] = int(fields[3]) @@ -727,20 +692,14 @@ def check_sat(self): if msg is not None: print("%s waiting for solver (%s)" % (self.timestamp(), msg), flush=True) - if self.forall: - result = self.read() - while result not in ["sat", "unsat", "unknown", "timeout", "interrupted", ""]: - print("%s %s: %s" % (self.timestamp(), self.solver, result)) - result = self.read() - else: - result = self.read() + result = self.read() if self.debug_file: print("(set-info :status %s)" % result, file=self.debug_file) print("(check-sat)", file=self.debug_file) self.debug_file.flush() - if result not in ["sat", "unsat", "unknown", "timeout", "interrupted"]: + if result not in ["sat", "unsat"]: if result == "": print("%s Unexpected EOF response from solver." % (self.timestamp()), flush=True) else: @@ -950,7 +909,7 @@ def wait(self): class SmtOpts: def __init__(self): self.shortopts = "s:S:v" - self.longopts = ["unroll", "noincr", "noprogress", "timeout=", "dump-smt2=", "logic=", "dummy=", "info=", "nocomments"] + self.longopts = ["unroll", "noincr", "noprogress", "dump-smt2=", "logic=", "dummy=", "info=", "nocomments"] self.solver = "yices" self.solver_opts = list() self.debug_print = False @@ -959,7 +918,6 @@ def __init__(self): self.unroll = False self.noincr = False self.timeinfo = os.name != "nt" - self.timeout = 0 self.logic = None self.info_stmts = list() self.nocomments = False @@ -969,8 +927,6 @@ def handle(self, o, a): self.solver = a elif o == "-S": self.solver_opts.append(a) - elif o == "--timeout": - self.timeout = int(a) elif o == "-v": self.debug_print = True elif o == "--unroll": @@ -1002,9 +958,6 @@ def helpmsg(self): -S pass as command line argument to the solver - --timeout - set the solver timeout to the specified value (in seconds). - --logic use the specified SMT2 logic (e.g. QF_AUFBV) diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index 4e5c6050db6..f755307bf6d 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -219,30 +219,30 @@ struct SmvWorker if (wire->port_input) inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, log_id(wire))); - if (wire->attributes.count(ID::init)) - assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at(ID::init)))); + if (wire->attributes.count("\\init")) + assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at("\\init")))); } for (auto cell : module->cells()) { // FIXME: $slice, $concat, $mem - if (cell->type.in(ID($assert))) + if (cell->type.in("$assert")) { - SigSpec sig_a = cell->getPort(ID::A); - SigSpec sig_en = cell->getPort(ID::EN); + SigSpec sig_a = cell->getPort("\\A"); + SigSpec sig_en = cell->getPort("\\EN"); invarspecs.push_back(stringf("!bool(%s) | bool(%s);", rvalue(sig_en), rvalue(sig_a))); continue; } - if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) + if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) { - SigSpec sig_a = cell->getPort(ID::A); - SigSpec sig_b = cell->getPort(ID::B); + SigSpec sig_a = cell->getPort("\\A"); + SigSpec sig_b = cell->getPort("\\B"); - int width_y = GetSize(cell->getPort(ID::Y)); + int width_y = GetSize(cell->getPort("\\Y")); int shift_b_width = GetSize(sig_b); int width_ay = max(GetSize(sig_a), width_y); int width = width_ay; @@ -254,12 +254,12 @@ struct SmvWorker break; } - bool signed_a = cell->getParam(ID::A_SIGNED).as_bool(); - bool signed_b = cell->getParam(ID::B_SIGNED).as_bool(); - string op = cell->type.in(ID($shl), ID($sshl)) ? "<<" : ">>"; + bool signed_a = cell->getParam("\\A_SIGNED").as_bool(); + bool signed_b = cell->getParam("\\B_SIGNED").as_bool(); + string op = cell->type.in("$shl", "$sshl") ? "<<" : ">>"; string expr, expr_a; - if (cell->type == ID($sshr) && signed_a) + if (cell->type == "$sshr" && signed_a) { expr_a = rvalue_s(sig_a, width); expr = stringf("resize(unsigned(%s %s %s), %d)", expr_a.c_str(), op.c_str(), rvalue(sig_b.extract(0, shift_b_width)), width_y); @@ -268,7 +268,7 @@ struct SmvWorker rvalue(sig_b.extract(shift_b_width, GetSize(sig_b) - shift_b_width)), GetSize(sig_b) - shift_b_width, rvalue(sig_a[GetSize(sig_a)-1]), width_y, width_y, expr.c_str()); } - else if (cell->type.in(ID($shift), ID($shiftx)) && signed_b) + else if (cell->type.in("$shift", "$shiftx") && signed_b) { expr_a = rvalue_u(sig_a, width); @@ -292,7 +292,7 @@ struct SmvWorker } else { - if (cell->type.in(ID($shift), ID($shiftx)) || !signed_a) + if (cell->type.in("$shift", "$shiftx") || !signed_a) expr_a = rvalue_u(sig_a, width); else expr_a = stringf("resize(unsigned(%s), %d)", rvalue_s(sig_a, width_ay), width); @@ -303,273 +303,272 @@ struct SmvWorker GetSize(sig_b)-shift_b_width, width_y, expr.c_str()); } - definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort(ID::Y)), expr.c_str())); + definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); continue; } - if (cell->type.in(ID($not), ID($pos), ID($neg))) + if (cell->type.in("$not", "$pos", "$neg")) { - int width = GetSize(cell->getPort(ID::Y)); + int width = GetSize(cell->getPort("\\Y")); string expr_a, op; - if (cell->type == ID($not)) op = "!"; - if (cell->type == ID($pos)) op = ""; - if (cell->type == ID($neg)) op = "-"; + if (cell->type == "$not") op = "!"; + if (cell->type == "$pos") op = ""; + if (cell->type == "$neg") op = "-"; - if (cell->getParam(ID::A_SIGNED).as_bool()) + if (cell->getParam("\\A_SIGNED").as_bool()) { - definitions.push_back(stringf("%s := unsigned(%s%s);", lvalue(cell->getPort(ID::Y)), - op.c_str(), rvalue_s(cell->getPort(ID::A), width))); + definitions.push_back(stringf("%s := unsigned(%s%s);", lvalue(cell->getPort("\\Y")), + op.c_str(), rvalue_s(cell->getPort("\\A"), width))); } else { - definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort(ID::Y)), - op.c_str(), rvalue_u(cell->getPort(ID::A), width))); + definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), + op.c_str(), rvalue_u(cell->getPort("\\A"), width))); } continue; } - if (cell->type.in(ID($add), ID($sub), ID($mul), ID($and), ID($or), ID($xor), ID($xnor))) + if (cell->type.in("$add", "$sub", "$mul", "$and", "$or", "$xor", "$xnor")) { - int width = GetSize(cell->getPort(ID::Y)); + int width = GetSize(cell->getPort("\\Y")); string expr_a, expr_b, op; - if (cell->type == ID($add)) op = "+"; - if (cell->type == ID($sub)) op = "-"; - if (cell->type == ID($mul)) op = "*"; - if (cell->type == ID($and)) op = "&"; - if (cell->type == ID($or)) op = "|"; - if (cell->type == ID($xor)) op = "xor"; - if (cell->type == ID($xnor)) op = "xnor"; + if (cell->type == "$add") op = "+"; + if (cell->type == "$sub") op = "-"; + if (cell->type == "$mul") op = "*"; + if (cell->type == "$and") op = "&"; + if (cell->type == "$or") op = "|"; + if (cell->type == "$xor") op = "xor"; + if (cell->type == "$xnor") op = "xnor"; - if (cell->getParam(ID::A_SIGNED).as_bool()) + if (cell->getParam("\\A_SIGNED").as_bool()) { - definitions.push_back(stringf("%s := unsigned(%s %s %s);", lvalue(cell->getPort(ID::Y)), - rvalue_s(cell->getPort(ID::A), width), op.c_str(), rvalue_s(cell->getPort(ID::B), width))); + definitions.push_back(stringf("%s := unsigned(%s %s %s);", lvalue(cell->getPort("\\Y")), + rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width))); } else { - definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort(ID::Y)), - rvalue_u(cell->getPort(ID::A), width), op.c_str(), rvalue_u(cell->getPort(ID::B), width))); + definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), + rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width))); } continue; } - // SMV has a "mod" operator, but its semantics don't seem to be well-defined - to be safe, don't generate it at all - if (cell->type.in(ID($div)/*, ID($mod), ID($modfloor)*/)) + if (cell->type.in("$div", "$mod")) { - int width_y = GetSize(cell->getPort(ID::Y)); - int width = max(width_y, GetSize(cell->getPort(ID::A))); - width = max(width, GetSize(cell->getPort(ID::B))); + int width_y = GetSize(cell->getPort("\\Y")); + int width = max(width_y, GetSize(cell->getPort("\\A"))); + width = max(width, GetSize(cell->getPort("\\B"))); string expr_a, expr_b, op; - if (cell->type == ID($div)) op = "/"; - //if (cell->type == ID($mod)) op = "mod"; + if (cell->type == "$div") op = "/"; + if (cell->type == "$mod") op = "mod"; - if (cell->getParam(ID::A_SIGNED).as_bool()) + if (cell->getParam("\\A_SIGNED").as_bool()) { - definitions.push_back(stringf("%s := resize(unsigned(%s %s %s), %d);", lvalue(cell->getPort(ID::Y)), - rvalue_s(cell->getPort(ID::A), width), op.c_str(), rvalue_s(cell->getPort(ID::B), width), width_y)); + definitions.push_back(stringf("%s := resize(unsigned(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), + rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width), width_y)); } else { - definitions.push_back(stringf("%s := resize(%s %s %s, %d);", lvalue(cell->getPort(ID::Y)), - rvalue_u(cell->getPort(ID::A), width), op.c_str(), rvalue_u(cell->getPort(ID::B), width), width_y)); + definitions.push_back(stringf("%s := resize(%s %s %s, %d);", lvalue(cell->getPort("\\Y")), + rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width), width_y)); } continue; } - if (cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex), ID($lt), ID($le), ID($ge), ID($gt))) + if (cell->type.in("$eq", "$ne", "$eqx", "$nex", "$lt", "$le", "$ge", "$gt")) { - int width = max(GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::B))); + int width = max(GetSize(cell->getPort("\\A")), GetSize(cell->getPort("\\B"))); string expr_a, expr_b, op; - if (cell->type == ID($eq)) op = "="; - if (cell->type == ID($ne)) op = "!="; - if (cell->type == ID($eqx)) op = "="; - if (cell->type == ID($nex)) op = "!="; - if (cell->type == ID($lt)) op = "<"; - if (cell->type == ID($le)) op = "<="; - if (cell->type == ID($ge)) op = ">="; - if (cell->type == ID($gt)) op = ">"; + if (cell->type == "$eq") op = "="; + if (cell->type == "$ne") op = "!="; + if (cell->type == "$eqx") op = "="; + if (cell->type == "$nex") op = "!="; + if (cell->type == "$lt") op = "<"; + if (cell->type == "$le") op = "<="; + if (cell->type == "$ge") op = ">="; + if (cell->type == "$gt") op = ">"; - if (cell->getParam(ID::A_SIGNED).as_bool()) + if (cell->getParam("\\A_SIGNED").as_bool()) { - expr_a = stringf("resize(signed(%s), %d)", rvalue(cell->getPort(ID::A)), width); - expr_b = stringf("resize(signed(%s), %d)", rvalue(cell->getPort(ID::B)), width); + expr_a = stringf("resize(signed(%s), %d)", rvalue(cell->getPort("\\A")), width); + expr_b = stringf("resize(signed(%s), %d)", rvalue(cell->getPort("\\B")), width); } else { - expr_a = stringf("resize(%s, %d)", rvalue(cell->getPort(ID::A)), width); - expr_b = stringf("resize(%s, %d)", rvalue(cell->getPort(ID::B)), width); + expr_a = stringf("resize(%s, %d)", rvalue(cell->getPort("\\A")), width); + expr_b = stringf("resize(%s, %d)", rvalue(cell->getPort("\\B")), width); } - definitions.push_back(stringf("%s := resize(word1(%s %s %s), %d);", lvalue(cell->getPort(ID::Y)), - expr_a.c_str(), op.c_str(), expr_b.c_str(), GetSize(cell->getPort(ID::Y)))); + definitions.push_back(stringf("%s := resize(word1(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), + expr_a.c_str(), op.c_str(), expr_b.c_str(), GetSize(cell->getPort("\\Y")))); continue; } - if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) + if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool")) { - int width_a = GetSize(cell->getPort(ID::A)); - int width_y = GetSize(cell->getPort(ID::Y)); - const char *expr_a = rvalue(cell->getPort(ID::A)); - const char *expr_y = lvalue(cell->getPort(ID::Y)); + int width_a = GetSize(cell->getPort("\\A")); + int width_y = GetSize(cell->getPort("\\Y")); + const char *expr_a = rvalue(cell->getPort("\\A")); + const char *expr_y = lvalue(cell->getPort("\\Y")); string expr; - if (cell->type == ID($reduce_and)) expr = stringf("%s = !0ub%d_0", expr_a, width_a); - if (cell->type == ID($reduce_or)) expr = stringf("%s != 0ub%d_0", expr_a, width_a); - if (cell->type == ID($reduce_bool)) expr = stringf("%s != 0ub%d_0", expr_a, width_a); + if (cell->type == "$reduce_and") expr = stringf("%s = !0ub%d_0", expr_a, width_a); + if (cell->type == "$reduce_or") expr = stringf("%s != 0ub%d_0", expr_a, width_a); + if (cell->type == "$reduce_bool") expr = stringf("%s != 0ub%d_0", expr_a, width_a); definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); continue; } - if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) + if (cell->type.in("$reduce_xor", "$reduce_xnor")) { - int width_y = GetSize(cell->getPort(ID::Y)); - const char *expr_y = lvalue(cell->getPort(ID::Y)); + int width_y = GetSize(cell->getPort("\\Y")); + const char *expr_y = lvalue(cell->getPort("\\Y")); string expr; - for (auto bit : cell->getPort(ID::A)) { + for (auto bit : cell->getPort("\\A")) { if (!expr.empty()) expr += " xor "; expr += rvalue(bit); } - if (cell->type == ID($reduce_xnor)) + if (cell->type == "$reduce_xnor") expr = "!(" + expr + ")"; definitions.push_back(stringf("%s := resize(%s, %d);", expr_y, expr.c_str(), width_y)); continue; } - if (cell->type.in(ID($logic_and), ID($logic_or))) + if (cell->type.in("$logic_and", "$logic_or")) { - int width_a = GetSize(cell->getPort(ID::A)); - int width_b = GetSize(cell->getPort(ID::B)); - int width_y = GetSize(cell->getPort(ID::Y)); + int width_a = GetSize(cell->getPort("\\A")); + int width_b = GetSize(cell->getPort("\\B")); + int width_y = GetSize(cell->getPort("\\Y")); - string expr_a = stringf("(%s != 0ub%d_0)", rvalue(cell->getPort(ID::A)), width_a); - string expr_b = stringf("(%s != 0ub%d_0)", rvalue(cell->getPort(ID::B)), width_b); - const char *expr_y = lvalue(cell->getPort(ID::Y)); + string expr_a = stringf("(%s != 0ub%d_0)", rvalue(cell->getPort("\\A")), width_a); + string expr_b = stringf("(%s != 0ub%d_0)", rvalue(cell->getPort("\\B")), width_b); + const char *expr_y = lvalue(cell->getPort("\\Y")); string expr; - if (cell->type == ID($logic_and)) expr = expr_a + " & " + expr_b; - if (cell->type == ID($logic_or)) expr = expr_a + " | " + expr_b; + if (cell->type == "$logic_and") expr = expr_a + " & " + expr_b; + if (cell->type == "$logic_or") expr = expr_a + " | " + expr_b; definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); continue; } - if (cell->type.in(ID($logic_not))) + if (cell->type.in("$logic_not")) { - int width_a = GetSize(cell->getPort(ID::A)); - int width_y = GetSize(cell->getPort(ID::Y)); + int width_a = GetSize(cell->getPort("\\A")); + int width_y = GetSize(cell->getPort("\\Y")); - string expr_a = stringf("(%s = 0ub%d_0)", rvalue(cell->getPort(ID::A)), width_a); - const char *expr_y = lvalue(cell->getPort(ID::Y)); + string expr_a = stringf("(%s = 0ub%d_0)", rvalue(cell->getPort("\\A")), width_a); + const char *expr_y = lvalue(cell->getPort("\\Y")); definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a.c_str(), width_y)); continue; } - if (cell->type.in(ID($mux), ID($pmux))) + if (cell->type.in("$mux", "$pmux")) { - int width = GetSize(cell->getPort(ID::Y)); - SigSpec sig_a = cell->getPort(ID::A); - SigSpec sig_b = cell->getPort(ID::B); - SigSpec sig_s = cell->getPort(ID::S); + int width = GetSize(cell->getPort("\\Y")); + SigSpec sig_a = cell->getPort("\\A"); + SigSpec sig_b = cell->getPort("\\B"); + SigSpec sig_s = cell->getPort("\\S"); string expr; for (int i = 0; i < GetSize(sig_s); i++) expr += stringf("bool(%s) ? %s : ", rvalue(sig_s[i]), rvalue(sig_b.extract(i*width, width))); expr += rvalue(sig_a); - definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort(ID::Y)), expr.c_str())); + definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); continue; } - if (cell->type == ID($dff)) + if (cell->type == "$dff") { - vars.push_back(stringf("%s : unsigned word[%d]; -- %s", lvalue(cell->getPort(ID::Q)), GetSize(cell->getPort(ID::Q)), log_signal(cell->getPort(ID::Q)))); - assignments.push_back(stringf("next(%s) := %s;", lvalue(cell->getPort(ID::Q)), rvalue(cell->getPort(ID::D)))); + vars.push_back(stringf("%s : unsigned word[%d]; -- %s", lvalue(cell->getPort("\\Q")), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q")))); + assignments.push_back(stringf("next(%s) := %s;", lvalue(cell->getPort("\\Q")), rvalue(cell->getPort("\\D")))); continue; } - if (cell->type.in(ID($_BUF_), ID($_NOT_))) + if (cell->type.in("$_BUF_", "$_NOT_")) { - string op = cell->type == ID($_NOT_) ? "!" : ""; - definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort(ID::Y)), op.c_str(), rvalue(cell->getPort(ID::A)))); + string op = cell->type == "$_NOT_" ? "!" : ""; + definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue(cell->getPort("\\A")))); continue; } - if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_))) + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) { string op; - if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_ANDNOT_))) op = "&"; - if (cell->type.in(ID($_OR_), ID($_NOR_), ID($_ORNOT_))) op = "|"; - if (cell->type.in(ID($_XOR_))) op = "xor"; - if (cell->type.in(ID($_XNOR_))) op = "xnor"; + if (cell->type.in("$_AND_", "$_NAND_", "$_ANDNOT_")) op = "&"; + if (cell->type.in("$_OR_", "$_NOR_", "$_ORNOT_")) op = "|"; + if (cell->type.in("$_XOR_")) op = "xor"; + if (cell->type.in("$_XNOR_")) op = "xnor"; - if (cell->type.in(ID($_ANDNOT_), ID($_ORNOT_))) - definitions.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort(ID::Y)), - rvalue(cell->getPort(ID::A)), op.c_str(), rvalue(cell->getPort(ID::B)))); + if (cell->type.in("$_ANDNOT_", "$_ORNOT_")) + definitions.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")), + rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); else - if (cell->type.in(ID($_NAND_), ID($_NOR_))) - definitions.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort(ID::Y)), - rvalue(cell->getPort(ID::A)), op.c_str(), rvalue(cell->getPort(ID::B)))); + if (cell->type.in("$_NAND_", "$_NOR_")) + definitions.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")), + rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); else - definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort(ID::Y)), - rvalue(cell->getPort(ID::A)), op.c_str(), rvalue(cell->getPort(ID::B)))); + definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), + rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); continue; } - if (cell->type == ID($_MUX_)) + if (cell->type == "$_MUX_") { - definitions.push_back(stringf("%s := bool(%s) ? %s : %s;", lvalue(cell->getPort(ID::Y)), - rvalue(cell->getPort(ID::S)), rvalue(cell->getPort(ID::B)), rvalue(cell->getPort(ID::A)))); + 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 == ID($_NMUX_)) + if (cell->type == "$_NMUX_") { - definitions.push_back(stringf("%s := !(bool(%s) ? %s : %s);", lvalue(cell->getPort(ID::Y)), - rvalue(cell->getPort(ID::S)), rvalue(cell->getPort(ID::B)), rvalue(cell->getPort(ID::A)))); + 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 == ID($_AOI3_)) + if (cell->type == "$_AOI3_") { - definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort(ID::Y)), - rvalue(cell->getPort(ID::A)), rvalue(cell->getPort(ID::B)), rvalue(cell->getPort(ID::C)))); + definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), + rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")))); continue; } - if (cell->type == ID($_OAI3_)) + if (cell->type == "$_OAI3_") { - definitions.push_back(stringf("%s := !((%s | %s) & %s);", lvalue(cell->getPort(ID::Y)), - rvalue(cell->getPort(ID::A)), rvalue(cell->getPort(ID::B)), rvalue(cell->getPort(ID::C)))); + definitions.push_back(stringf("%s := !((%s | %s) & %s);", lvalue(cell->getPort("\\Y")), + rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")))); continue; } - if (cell->type == ID($_AOI4_)) + if (cell->type == "$_AOI4_") { - definitions.push_back(stringf("%s := !((%s & %s) | (%s & %s));", lvalue(cell->getPort(ID::Y)), - rvalue(cell->getPort(ID::A)), rvalue(cell->getPort(ID::B)), rvalue(cell->getPort(ID::C)), rvalue(cell->getPort(ID::D)))); + definitions.push_back(stringf("%s := !((%s & %s) | (%s & %s));", lvalue(cell->getPort("\\Y")), + rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D")))); continue; } - if (cell->type == ID($_OAI4_)) + if (cell->type == "$_OAI4_") { - definitions.push_back(stringf("%s := !((%s | %s) & (%s | %s));", lvalue(cell->getPort(ID::Y)), - rvalue(cell->getPort(ID::A)), rvalue(cell->getPort(ID::B)), rvalue(cell->getPort(ID::C)), rvalue(cell->getPort(ID::D)))); + definitions.push_back(stringf("%s := !((%s | %s) & (%s | %s));", lvalue(cell->getPort("\\Y")), + rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D")))); continue; } @@ -702,7 +701,7 @@ struct SmvWorker struct SmvBackend : public Backend { SmvBackend() : Backend("smv", "write design to SMV file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -720,7 +719,7 @@ struct SmvBackend : public Backend { log("THIS COMMAND IS UNDER CONSTRUCTION\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::ifstream template_f; bool verbose = false; diff --git a/backends/smv/test_cells.sh b/backends/smv/test_cells.sh index 145b9c33b92..63de465c05c 100644 --- a/backends/smv/test_cells.sh +++ b/backends/smv/test_cells.sh @@ -7,8 +7,8 @@ mkdir -p test_cells.tmp cd test_cells.tmp # don't test $mul to reduce runtime -# don't test $div/$mod/$divfloor/$modfloor to reduce runtime and avoid "div by zero" message -../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$macc /$mul /$div /$mod /$divfloor /$modfloor' +# don't test $div and $mod to reduce runtime and avoid "div by zero" message +../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$macc /$mul /$div /$mod' cat > template.txt << "EOT" %module main diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index aa20f106aee..6738a4bbd6c 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -70,13 +70,14 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De idict inums; int cell_counter = 0, conn_counter = 0, nc_counter = 0; - for (auto cell : module->cells()) + for (auto &cell_it : module->cells_) { + RTLIL::Cell *cell = cell_it.second; f << stringf("X%d", cell_counter++); std::vector port_sigs; - if (design->module(cell->type) == nullptr) + if (design->modules_.count(cell->type) == 0) { log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n", log_id(cell->type), log_id(module), log_id(cell)); @@ -87,10 +88,11 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De } else { - RTLIL::Module *mod = design->module(cell->type); + RTLIL::Module *mod = design->modules_.at(cell->type); std::vector ports; - for (auto wire : mod->wires()) { + for (auto wire_it : mod->wires_) { + RTLIL::Wire *wire = wire_it.second; if (wire->port_id == 0) continue; while (int(ports.size()) < wire->port_id) @@ -130,7 +132,7 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De struct SpiceBackend : public Backend { SpiceBackend() : Backend("spice", "write design to SPICE netlist file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -159,7 +161,7 @@ struct SpiceBackend : public Backend { log(" set the specified module as design top module\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string top_module_name; RTLIL::Module *top_module = NULL; @@ -200,15 +202,16 @@ struct SpiceBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto module : design->modules()) - if (module->get_bool_attribute(ID::top)) - top_module_name = module->name.str(); + for (auto & mod_it:design->modules_) + if (mod_it.second->get_bool_attribute("\\top")) + top_module_name = mod_it.first.str(); *f << stringf("* SPICE netlist generated by %s\n", yosys_version_str); *f << stringf("\n"); - for (auto module : design->modules()) + for (auto module_it : design->modules_) { + RTLIL::Module *module = module_it.second; if (module->get_blackbox_attribute()) continue; @@ -223,7 +226,8 @@ struct SpiceBackend : public Backend { } std::vector ports; - for (auto wire : module->wires()) { + for (auto wire_it : module->wires_) { + RTLIL::Wire *wire = wire_it.second; if (wire->port_id == 0) continue; while (int(ports.size()) < wire->port_id) diff --git a/backends/table/table.cc b/backends/table/table.cc index 77642ccbdf2..796f18059ff 100644 --- a/backends/table/table.cc +++ b/backends/table/table.cc @@ -29,7 +29,7 @@ PRIVATE_NAMESPACE_BEGIN struct TableBackend : public Backend { TableBackend() : Backend("table", "write design as connectivity table") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -48,7 +48,7 @@ struct TableBackend : public Backend { log("module inputs and outputs are output using cell type and port '-' and with\n"); log("'pi' (primary input) or 'po' (primary output) or 'pio' as direction.\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing TABLE backend.\n"); diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index cef1dd9df48..54d0f61486b 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -73,12 +73,12 @@ void reset_auto_counter(RTLIL::Module *module) reset_auto_counter_id(module->name, false); - for (auto w : module->wires()) - reset_auto_counter_id(w->name, true); + for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) + reset_auto_counter_id(it->second->name, true); - for (auto cell : module->cells()) { - reset_auto_counter_id(cell->name, true); - reset_auto_counter_id(cell->type, false); + for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) { + reset_auto_counter_id(it->second->name, true); + reset_auto_counter_id(it->second->type, false); } for (auto it = module->processes.begin(); it != module->processes.end(); ++it) @@ -378,7 +378,7 @@ void dump_attributes(std::ostream &f, std::string indent, dictfirst == ID::init && regattr) continue; + if (it->first == "\\init" && regattr) continue; f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str()); f << stringf(" = "); if (modattr && (it->second == State::S0 || it->second == Const(0))) @@ -423,9 +423,9 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire) f << stringf("%s" "inout%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); if (reg_wires.count(wire->name)) { f << stringf("%s" "reg%s %s", indent.c_str(), range.c_str(), id(wire->name).c_str()); - if (wire->attributes.count(ID::init)) { + if (wire->attributes.count("\\init")) { f << stringf(" = "); - dump_const(f, wire->attributes.at(ID::init)); + dump_const(f, wire->attributes.at("\\init")); } f << stringf(";\n"); } else if (!wire->port_input && !wire->port_output) @@ -451,9 +451,9 @@ void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, b std::string cellname(RTLIL::Cell *cell) { - if (!norename && cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort(ID::Q)) + if (!norename && cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { - RTLIL::SigSpec sig = cell->getPort(ID::Q); + RTLIL::SigSpec sig = cell->getPort("\\Q"); if (GetSize(sig) != 1 || sig.is_fully_const()) goto no_special_reg_name; @@ -488,7 +488,7 @@ std::string cellname(RTLIL::Cell *cell) void dump_cell_expr_uniop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op) { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = %s ", op.c_str()); dump_attributes(f, "", cell->attributes, ' '); dump_cell_expr_port(f, cell, "A", true); @@ -498,7 +498,7 @@ void dump_cell_expr_uniop(std::ostream &f, std::string indent, RTLIL::Cell *cell void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op) { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); dump_cell_expr_port(f, cell, "A", true); f << stringf(" %s ", op.c_str()); @@ -509,9 +509,9 @@ void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) { - if (cell->type == ID($_NOT_)) { + if (cell->type == "$_NOT_") { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); f << stringf("~"); dump_attributes(f, "", cell->attributes, ' '); @@ -520,34 +520,34 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_))) { + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); - if (cell->type.in(ID($_NAND_), ID($_NOR_), ID($_XNOR_))) + if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_")) f << stringf("~("); dump_cell_expr_port(f, cell, "A", false); f << stringf(" "); - if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_ANDNOT_))) + if (cell->type.in("$_AND_", "$_NAND_", "$_ANDNOT_")) f << stringf("&"); - if (cell->type.in(ID($_OR_), ID($_NOR_), ID($_ORNOT_))) + if (cell->type.in("$_OR_", "$_NOR_", "$_ORNOT_")) f << stringf("|"); - if (cell->type.in(ID($_XOR_), ID($_XNOR_))) + if (cell->type.in("$_XOR_", "$_XNOR_")) f << stringf("^"); dump_attributes(f, "", cell->attributes, ' '); f << stringf(" "); - if (cell->type.in(ID($_ANDNOT_), ID($_ORNOT_))) + if (cell->type.in("$_ANDNOT_", "$_ORNOT_")) f << stringf("~("); dump_cell_expr_port(f, cell, "B", false); - if (cell->type.in(ID($_NAND_), ID($_NOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_))) + if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) f << stringf(")"); f << stringf(";\n"); return true; } - if (cell->type == ID($_MUX_)) { + if (cell->type == "$_MUX_") { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); dump_cell_expr_port(f, cell, "S", false); f << stringf(" ? "); @@ -559,9 +559,9 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type == ID($_NMUX_)) { + if (cell->type == "$_NMUX_") { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = !("); dump_cell_expr_port(f, cell, "S", false); f << stringf(" ? "); @@ -573,14 +573,14 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type.in(ID($_AOI3_), ID($_OAI3_))) { + if (cell->type.in("$_AOI3_", "$_OAI3_")) { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = ~(("); dump_cell_expr_port(f, cell, "A", false); - f << stringf(cell->type == ID($_AOI3_) ? " & " : " | "); + f << stringf(cell->type == "$_AOI3_" ? " & " : " | "); dump_cell_expr_port(f, cell, "B", false); - f << stringf(cell->type == ID($_AOI3_) ? ") |" : ") &"); + f << stringf(cell->type == "$_AOI3_" ? ") |" : ") &"); dump_attributes(f, "", cell->attributes, ' '); f << stringf(" "); dump_cell_expr_port(f, cell, "C", false); @@ -588,18 +588,18 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type.in(ID($_AOI4_), ID($_OAI4_))) { + if (cell->type.in("$_AOI4_", "$_OAI4_")) { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = ~(("); dump_cell_expr_port(f, cell, "A", false); - f << stringf(cell->type == ID($_AOI4_) ? " & " : " | "); + f << stringf(cell->type == "$_AOI4_" ? " & " : " | "); dump_cell_expr_port(f, cell, "B", false); - f << stringf(cell->type == ID($_AOI4_) ? ") |" : ") &"); + f << stringf(cell->type == "$_AOI4_" ? ") |" : ") &"); dump_attributes(f, "", cell->attributes, ' '); f << stringf(" ("); dump_cell_expr_port(f, cell, "C", false); - f << stringf(cell->type == ID($_AOI4_) ? " & " : " | "); + f << stringf(cell->type == "$_AOI4_" ? " & " : " | "); dump_cell_expr_port(f, cell, "D", false); f << stringf("));\n"); return true; @@ -608,26 +608,26 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (cell->type.begins_with("$_DFF_")) { std::string reg_name = cellname(cell); - bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name); + bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); if (!out_is_reg_wire) { f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str()); - dump_reg_init(f, cell->getPort(ID::Q)); + dump_reg_init(f, cell->getPort("\\Q")); f << ";\n"; } dump_attributes(f, indent, cell->attributes); f << stringf("%s" "always @(%sedge ", indent.c_str(), cell->type[6] == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->getPort(ID::C)); + dump_sigspec(f, cell->getPort("\\C")); if (cell->type[7] != '_') { f << stringf(" or %sedge ", cell->type[7] == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->getPort(ID::R)); + dump_sigspec(f, cell->getPort("\\R")); } f << stringf(")\n"); if (cell->type[7] != '_') { f << stringf("%s" " if (%s", indent.c_str(), cell->type[7] == 'P' ? "" : "!"); - dump_sigspec(f, cell->getPort(ID::R)); + dump_sigspec(f, cell->getPort("\\R")); f << stringf(")\n"); f << stringf("%s" " %s <= %c;\n", indent.c_str(), reg_name.c_str(), cell->type[8]); f << stringf("%s" " else\n", indent.c_str()); @@ -639,7 +639,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (!out_is_reg_wire) { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Q)); + dump_sigspec(f, cell->getPort("\\Q")); f << stringf(" = %s;\n", reg_name.c_str()); } @@ -651,30 +651,30 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) char pol_c = cell->type[8], pol_s = cell->type[9], pol_r = cell->type[10]; std::string reg_name = cellname(cell); - bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name); + bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); if (!out_is_reg_wire) { f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str()); - dump_reg_init(f, cell->getPort(ID::Q)); + dump_reg_init(f, cell->getPort("\\Q")); f << ";\n"; } dump_attributes(f, indent, cell->attributes); f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_c == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->getPort(ID::C)); + dump_sigspec(f, cell->getPort("\\C")); f << stringf(" or %sedge ", pol_s == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->getPort(ID::S)); + dump_sigspec(f, cell->getPort("\\S")); f << stringf(" or %sedge ", pol_r == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->getPort(ID::R)); + dump_sigspec(f, cell->getPort("\\R")); f << stringf(")\n"); f << stringf("%s" " if (%s", indent.c_str(), pol_r == 'P' ? "" : "!"); - dump_sigspec(f, cell->getPort(ID::R)); + dump_sigspec(f, cell->getPort("\\R")); f << stringf(")\n"); f << stringf("%s" " %s <= 0;\n", indent.c_str(), reg_name.c_str()); f << stringf("%s" " else if (%s", indent.c_str(), pol_s == 'P' ? "" : "!"); - dump_sigspec(f, cell->getPort(ID::S)); + dump_sigspec(f, cell->getPort("\\S")); f << stringf(")\n"); f << stringf("%s" " %s <= 1;\n", indent.c_str(), reg_name.c_str()); @@ -685,7 +685,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (!out_is_reg_wire) { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Q)); + dump_sigspec(f, cell->getPort("\\Q")); f << stringf(" = %s;\n", reg_name.c_str()); } @@ -697,206 +697,117 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) #define HANDLE_BINOP(_type, _operator) \ if (cell->type ==_type) { dump_cell_expr_binop(f, indent, cell, _operator); return true; } - HANDLE_UNIOP(ID($not), "~") - HANDLE_UNIOP(ID($pos), "+") - HANDLE_UNIOP(ID($neg), "-") - - HANDLE_BINOP(ID($and), "&") - HANDLE_BINOP(ID($or), "|") - HANDLE_BINOP(ID($xor), "^") - HANDLE_BINOP(ID($xnor), "~^") - - HANDLE_UNIOP(ID($reduce_and), "&") - HANDLE_UNIOP(ID($reduce_or), "|") - HANDLE_UNIOP(ID($reduce_xor), "^") - HANDLE_UNIOP(ID($reduce_xnor), "~^") - HANDLE_UNIOP(ID($reduce_bool), "|") - - HANDLE_BINOP(ID($shl), "<<") - HANDLE_BINOP(ID($shr), ">>") - HANDLE_BINOP(ID($sshl), "<<<") - HANDLE_BINOP(ID($sshr), ">>>") - - HANDLE_BINOP(ID($lt), "<") - HANDLE_BINOP(ID($le), "<=") - HANDLE_BINOP(ID($eq), "==") - HANDLE_BINOP(ID($ne), "!=") - HANDLE_BINOP(ID($eqx), "===") - HANDLE_BINOP(ID($nex), "!==") - HANDLE_BINOP(ID($ge), ">=") - HANDLE_BINOP(ID($gt), ">") - - HANDLE_BINOP(ID($add), "+") - HANDLE_BINOP(ID($sub), "-") - HANDLE_BINOP(ID($mul), "*") - HANDLE_BINOP(ID($div), "/") - HANDLE_BINOP(ID($mod), "%") - HANDLE_BINOP(ID($pow), "**") - - HANDLE_UNIOP(ID($logic_not), "!") - HANDLE_BINOP(ID($logic_and), "&&") - HANDLE_BINOP(ID($logic_or), "||") + HANDLE_UNIOP("$not", "~") + HANDLE_UNIOP("$pos", "+") + HANDLE_UNIOP("$neg", "-") + + HANDLE_BINOP("$and", "&") + HANDLE_BINOP("$or", "|") + HANDLE_BINOP("$xor", "^") + HANDLE_BINOP("$xnor", "~^") + + HANDLE_UNIOP("$reduce_and", "&") + HANDLE_UNIOP("$reduce_or", "|") + HANDLE_UNIOP("$reduce_xor", "^") + HANDLE_UNIOP("$reduce_xnor", "~^") + HANDLE_UNIOP("$reduce_bool", "|") + + HANDLE_BINOP("$shl", "<<") + HANDLE_BINOP("$shr", ">>") + HANDLE_BINOP("$sshl", "<<<") + HANDLE_BINOP("$sshr", ">>>") + + HANDLE_BINOP("$lt", "<") + HANDLE_BINOP("$le", "<=") + HANDLE_BINOP("$eq", "==") + HANDLE_BINOP("$ne", "!=") + HANDLE_BINOP("$eqx", "===") + HANDLE_BINOP("$nex", "!==") + HANDLE_BINOP("$ge", ">=") + HANDLE_BINOP("$gt", ">") + + HANDLE_BINOP("$add", "+") + HANDLE_BINOP("$sub", "-") + HANDLE_BINOP("$mul", "*") + HANDLE_BINOP("$div", "/") + HANDLE_BINOP("$mod", "%") + HANDLE_BINOP("$pow", "**") + + HANDLE_UNIOP("$logic_not", "!") + HANDLE_BINOP("$logic_and", "&&") + HANDLE_BINOP("$logic_or", "||") #undef HANDLE_UNIOP #undef HANDLE_BINOP - if (cell->type == ID($divfloor)) - { - // wire [MAXLEN+1:0] _0_, _1_, _2_; - // assign _0_ = $signed(A); - // assign _1_ = $signed(B); - // assign _2_ = (A[-1] == B[-1]) || A == 0 ? _0_ : $signed(_0_ - (B[-1] ? _1_ + 1 : _1_ - 1)); - // assign Y = $signed(_2_) / $signed(_1_); - - if (cell->getParam(ID::A_SIGNED).as_bool() && cell->getParam(ID::B_SIGNED).as_bool()) { - SigSpec sig_a = cell->getPort(ID::A); - SigSpec sig_b = cell->getPort(ID::B); - - std::string buf_a = next_auto_id(); - std::string buf_b = next_auto_id(); - std::string buf_num = next_auto_id(); - int size_a = GetSize(sig_a); - int size_b = GetSize(sig_b); - int size_y = GetSize(cell->getPort(ID::Y)); - int size_max = std::max(size_a, std::max(size_b, size_y)); - - // intentionally one wider than maximum width - f << stringf("%s" "wire [%d:0] %s, %s, %s;\n", indent.c_str(), size_max, buf_a.c_str(), buf_b.c_str(), buf_num.c_str()); - f << stringf("%s" "assign %s = ", indent.c_str(), buf_a.c_str()); - dump_cell_expr_port(f, cell, "A", true); - f << stringf(";\n"); - f << stringf("%s" "assign %s = ", indent.c_str(), buf_b.c_str()); - dump_cell_expr_port(f, cell, "B", true); - f << stringf(";\n"); - - f << stringf("%s" "assign %s = ", indent.c_str(), buf_num.c_str()); - f << stringf("("); - dump_sigspec(f, sig_a.extract(sig_a.size()-1)); - f << stringf(" == "); - dump_sigspec(f, sig_b.extract(sig_b.size()-1)); - f << stringf(") || "); - dump_sigspec(f, sig_a); - f << stringf(" == 0 ? %s : ", buf_a.c_str()); - f << stringf("$signed(%s - (", buf_a.c_str()); - dump_sigspec(f, sig_b.extract(sig_b.size()-1)); - f << stringf(" ? %s + 1 : %s - 1));\n", buf_b.c_str(), buf_b.c_str()); - - - f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); - f << stringf(" = $signed(%s) / ", buf_num.c_str()); - dump_attributes(f, "", cell->attributes, ' '); - f << stringf("$signed(%s);\n", buf_b.c_str()); - return true; - } else { - // same as truncating division - dump_cell_expr_binop(f, indent, cell, "/"); - return true; - } - } - - if (cell->type == ID($modfloor)) - { - // wire truncated = $signed(A) % $signed(B); - // assign Y = (A[-1] == B[-1]) || truncated == 0 ? truncated : $signed(B) + $signed(truncated); - - if (cell->getParam(ID::A_SIGNED).as_bool() && cell->getParam(ID::B_SIGNED).as_bool()) { - SigSpec sig_a = cell->getPort(ID::A); - SigSpec sig_b = cell->getPort(ID::B); - - std::string temp_id = next_auto_id(); - f << stringf("%s" "wire [%d:0] %s = ", indent.c_str(), GetSize(cell->getPort(ID::A))-1, temp_id.c_str()); - dump_cell_expr_port(f, cell, "A", true); - f << stringf(" %% "); - dump_attributes(f, "", cell->attributes, ' '); - dump_cell_expr_port(f, cell, "B", true); - f << stringf(";\n"); - - f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); - f << stringf(" = ("); - dump_sigspec(f, sig_a.extract(sig_a.size()-1)); - f << stringf(" == "); - dump_sigspec(f, sig_b.extract(sig_b.size()-1)); - f << stringf(") || %s == 0 ? %s : ", temp_id.c_str(), temp_id.c_str()); - dump_cell_expr_port(f, cell, "B", true); - f << stringf(" + $signed(%s);\n", temp_id.c_str()); - return true; - } else { - // same as truncating modulo - dump_cell_expr_binop(f, indent, cell, "%"); - return true; - } - } - - if (cell->type == ID($shift)) + if (cell->type == "$shift") { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); - if (cell->getParam(ID::B_SIGNED).as_bool()) + if (cell->getParam("\\B_SIGNED").as_bool()) { f << stringf("$signed("); - dump_sigspec(f, cell->getPort(ID::B)); + dump_sigspec(f, cell->getPort("\\B")); f << stringf(")"); f << stringf(" < 0 ? "); - dump_sigspec(f, cell->getPort(ID::A)); + dump_sigspec(f, cell->getPort("\\A")); f << stringf(" << - "); - dump_sigspec(f, cell->getPort(ID::B)); + dump_sigspec(f, cell->getPort("\\B")); f << stringf(" : "); - dump_sigspec(f, cell->getPort(ID::A)); + dump_sigspec(f, cell->getPort("\\A")); f << stringf(" >> "); - dump_sigspec(f, cell->getPort(ID::B)); + dump_sigspec(f, cell->getPort("\\B")); } else { - dump_sigspec(f, cell->getPort(ID::A)); + dump_sigspec(f, cell->getPort("\\A")); f << stringf(" >> "); - dump_sigspec(f, cell->getPort(ID::B)); + dump_sigspec(f, cell->getPort("\\B")); } f << stringf(";\n"); return true; } - if (cell->type == ID($shiftx)) + if (cell->type == "$shiftx") { std::string temp_id = next_auto_id(); - f << stringf("%s" "wire [%d:0] %s = ", indent.c_str(), GetSize(cell->getPort(ID::A))-1, temp_id.c_str()); - dump_sigspec(f, cell->getPort(ID::A)); + f << stringf("%s" "wire [%d:0] %s = ", indent.c_str(), GetSize(cell->getPort("\\A"))-1, temp_id.c_str()); + dump_sigspec(f, cell->getPort("\\A")); f << stringf(";\n"); f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = %s[", temp_id.c_str()); - if (cell->getParam(ID::B_SIGNED).as_bool()) + if (cell->getParam("\\B_SIGNED").as_bool()) f << stringf("$signed("); - dump_sigspec(f, cell->getPort(ID::B)); - if (cell->getParam(ID::B_SIGNED).as_bool()) + dump_sigspec(f, cell->getPort("\\B")); + if (cell->getParam("\\B_SIGNED").as_bool()) f << stringf(")"); - f << stringf(" +: %d", cell->getParam(ID::Y_WIDTH).as_int()); + f << stringf(" +: %d", cell->getParam("\\Y_WIDTH").as_int()); f << stringf("];\n"); return true; } - if (cell->type == ID($mux)) + if (cell->type == "$mux") { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); - dump_sigspec(f, cell->getPort(ID::S)); + dump_sigspec(f, cell->getPort("\\S")); f << stringf(" ? "); dump_attributes(f, "", cell->attributes, ' '); - dump_sigspec(f, cell->getPort(ID::B)); + dump_sigspec(f, cell->getPort("\\B")); f << stringf(" : "); - dump_sigspec(f, cell->getPort(ID::A)); + dump_sigspec(f, cell->getPort("\\A")); f << stringf(";\n"); return true; } - if (cell->type == ID($pmux)) + if (cell->type == "$pmux") { - int width = cell->parameters[ID::WIDTH].as_int(); - int s_width = cell->getPort(ID::S).size(); + int width = cell->parameters["\\WIDTH"].as_int(); + int s_width = cell->getPort("\\S").size(); std::string func_name = cellname(cell); f << stringf("%s" "function [%d:0] %s;\n", indent.c_str(), width-1, func_name.c_str()); @@ -928,76 +839,76 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) f << stringf("%s" "endfunction\n", indent.c_str()); f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = %s(", func_name.c_str()); - dump_sigspec(f, cell->getPort(ID::A)); + dump_sigspec(f, cell->getPort("\\A")); f << stringf(", "); - dump_sigspec(f, cell->getPort(ID::B)); + dump_sigspec(f, cell->getPort("\\B")); f << stringf(", "); - dump_sigspec(f, cell->getPort(ID::S)); + dump_sigspec(f, cell->getPort("\\S")); f << stringf(");\n"); return true; } - if (cell->type == ID($tribuf)) + if (cell->type == "$tribuf") { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); - dump_sigspec(f, cell->getPort(ID::EN)); + dump_sigspec(f, cell->getPort("\\EN")); f << stringf(" ? "); - dump_sigspec(f, cell->getPort(ID::A)); - f << stringf(" : %d'bz;\n", cell->parameters.at(ID::WIDTH).as_int()); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(" : %d'bz;\n", cell->parameters.at("\\WIDTH").as_int()); return true; } - if (cell->type == ID($slice)) + if (cell->type == "$slice") { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); - dump_sigspec(f, cell->getPort(ID::A)); - f << stringf(" >> %d;\n", cell->parameters.at(ID::OFFSET).as_int()); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(" >> %d;\n", cell->parameters.at("\\OFFSET").as_int()); return true; } - if (cell->type == ID($concat)) + if (cell->type == "$concat") { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = { "); - dump_sigspec(f, cell->getPort(ID::B)); + dump_sigspec(f, cell->getPort("\\B")); f << stringf(" , "); - dump_sigspec(f, cell->getPort(ID::A)); + dump_sigspec(f, cell->getPort("\\A")); f << stringf(" };\n"); return true; } - if (cell->type == ID($lut)) + if (cell->type == "$lut") { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Y)); + dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); - dump_const(f, cell->parameters.at(ID::LUT)); + dump_const(f, cell->parameters.at("\\LUT")); f << stringf(" >> "); dump_attributes(f, "", cell->attributes, ' '); - dump_sigspec(f, cell->getPort(ID::A)); + dump_sigspec(f, cell->getPort("\\A")); f << stringf(";\n"); return true; } - if (cell->type == ID($dffsr)) + if (cell->type == "$dffsr") { - SigSpec sig_clk = cell->getPort(ID::CLK); - SigSpec sig_set = cell->getPort(ID::SET); - SigSpec sig_clr = cell->getPort(ID::CLR); - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); + SigSpec sig_clk = cell->getPort("\\CLK"); + SigSpec sig_set = cell->getPort("\\SET"); + SigSpec sig_clr = cell->getPort("\\CLR"); + SigSpec sig_d = cell->getPort("\\D"); + SigSpec sig_q = cell->getPort("\\Q"); - int width = cell->parameters[ID::WIDTH].as_int(); - bool pol_clk = cell->parameters[ID::CLK_POLARITY].as_bool(); - bool pol_set = cell->parameters[ID::SET_POLARITY].as_bool(); - bool pol_clr = cell->parameters[ID::CLR_POLARITY].as_bool(); + int width = cell->parameters["\\WIDTH"].as_int(); + bool pol_clk = cell->parameters["\\CLK_POLARITY"].as_bool(); + bool pol_set = cell->parameters["\\SET_POLARITY"].as_bool(); + bool pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool(); std::string reg_name = cellname(cell); bool out_is_reg_wire = is_reg_wire(sig_q, reg_name); @@ -1039,43 +950,43 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type.in(ID($dff), ID($adff), ID($dffe))) + if (cell->type.in("$dff", "$adff", "$dffe")) { RTLIL::SigSpec sig_clk, sig_arst, sig_en, val_arst; bool pol_clk, pol_arst = false, pol_en = false; - sig_clk = cell->getPort(ID::CLK); - pol_clk = cell->parameters[ID::CLK_POLARITY].as_bool(); + sig_clk = cell->getPort("\\CLK"); + pol_clk = cell->parameters["\\CLK_POLARITY"].as_bool(); - if (cell->type == ID($adff)) { - sig_arst = cell->getPort(ID::ARST); - pol_arst = cell->parameters[ID::ARST_POLARITY].as_bool(); - val_arst = RTLIL::SigSpec(cell->parameters[ID::ARST_VALUE]); + if (cell->type == "$adff") { + sig_arst = cell->getPort("\\ARST"); + pol_arst = cell->parameters["\\ARST_POLARITY"].as_bool(); + val_arst = RTLIL::SigSpec(cell->parameters["\\ARST_VALUE"]); } - if (cell->type == ID($dffe)) { - sig_en = cell->getPort(ID::EN); - pol_en = cell->parameters[ID::EN_POLARITY].as_bool(); + if (cell->type == "$dffe") { + sig_en = cell->getPort("\\EN"); + pol_en = cell->parameters["\\EN_POLARITY"].as_bool(); } std::string reg_name = cellname(cell); - bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name); + bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); if (!out_is_reg_wire) { - f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters[ID::WIDTH].as_int()-1, reg_name.c_str()); - dump_reg_init(f, cell->getPort(ID::Q)); + f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters["\\WIDTH"].as_int()-1, reg_name.c_str()); + dump_reg_init(f, cell->getPort("\\Q")); f << ";\n"; } f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_clk ? "pos" : "neg"); dump_sigspec(f, sig_clk); - if (cell->type == ID($adff)) { + if (cell->type == "$adff") { f << stringf(" or %sedge ", pol_arst ? "pos" : "neg"); dump_sigspec(f, sig_arst); } f << stringf(")\n"); - if (cell->type == ID($adff)) { + if (cell->type == "$adff") { f << stringf("%s" " if (%s", indent.c_str(), pol_arst ? "" : "!"); dump_sigspec(f, sig_arst); f << stringf(")\n"); @@ -1085,7 +996,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) f << stringf("%s" " else\n", indent.c_str()); } - if (cell->type == ID($dffe)) { + if (cell->type == "$dffe") { f << stringf("%s" " if (%s", indent.c_str(), pol_en ? "" : "!"); dump_sigspec(f, sig_en); f << stringf(")\n"); @@ -1097,27 +1008,27 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (!out_is_reg_wire) { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Q)); + dump_sigspec(f, cell->getPort("\\Q")); f << stringf(" = %s;\n", reg_name.c_str()); } return true; } - if (cell->type == ID($dlatch)) + if (cell->type == "$dlatch") { RTLIL::SigSpec sig_en; bool pol_en = false; - sig_en = cell->getPort(ID::EN); - pol_en = cell->parameters[ID::EN_POLARITY].as_bool(); + sig_en = cell->getPort("\\EN"); + pol_en = cell->parameters["\\EN_POLARITY"].as_bool(); std::string reg_name = cellname(cell); - bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name); + bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); if (!out_is_reg_wire) { - f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters[ID::WIDTH].as_int()-1, reg_name.c_str()); - dump_reg_init(f, cell->getPort(ID::Q)); + f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters["\\WIDTH"].as_int()-1, reg_name.c_str()); + dump_reg_init(f, cell->getPort("\\Q")); f << ";\n"; } @@ -1133,29 +1044,28 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (!out_is_reg_wire) { f << stringf("%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::Q)); + dump_sigspec(f, cell->getPort("\\Q")); f << stringf(" = %s;\n", reg_name.c_str()); } return true; } - if (cell->type == ID($mem)) + if (cell->type == "$mem") { - RTLIL::IdString memid = cell->parameters[ID::MEMID].decode_string(); - std::string mem_id = id(cell->parameters[ID::MEMID].decode_string()); - int abits = cell->parameters[ID::ABITS].as_int(); - int size = cell->parameters[ID::SIZE].as_int(); - int offset = cell->parameters[ID::OFFSET].as_int(); - int width = cell->parameters[ID::WIDTH].as_int(); - bool use_init = !(RTLIL::SigSpec(cell->parameters[ID::INIT]).is_fully_undef()); + RTLIL::IdString memid = cell->parameters["\\MEMID"].decode_string(); + std::string mem_id = id(cell->parameters["\\MEMID"].decode_string()); + int abits = cell->parameters["\\ABITS"].as_int(); + int size = cell->parameters["\\SIZE"].as_int(); + int offset = cell->parameters["\\OFFSET"].as_int(); + int width = cell->parameters["\\WIDTH"].as_int(); + bool use_init = !(RTLIL::SigSpec(cell->parameters["\\INIT"]).is_fully_undef()); // for memory block make something like: // reg [7:0] memid [3:0]; // initial begin // memid[0] = ... // end - dump_attributes(f, indent.c_str(), cell->attributes); f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size+offset-1, offset); if (use_init) { @@ -1188,7 +1098,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) { for (int i=0; iparameters[ID::INIT].extract(i*width, width); + RTLIL::Const element = cell->parameters["\\INIT"].extract(i*width, width); for (int j=0; j lof_reg_declarations; - int nread_ports = cell->parameters[ID::RD_PORTS].as_int(); + int nread_ports = cell->parameters["\\RD_PORTS"].as_int(); RTLIL::SigSpec sig_rd_clk, sig_rd_en, sig_rd_data, sig_rd_addr; bool use_rd_clk, rd_clk_posedge, rd_transparent; // read ports for (int i=0; i < nread_ports; i++) { - sig_rd_clk = cell->getPort(ID::RD_CLK).extract(i); - sig_rd_en = cell->getPort(ID::RD_EN).extract(i); - sig_rd_data = cell->getPort(ID::RD_DATA).extract(i*width, width); - sig_rd_addr = cell->getPort(ID::RD_ADDR).extract(i*abits, abits); - use_rd_clk = cell->parameters[ID::RD_CLK_ENABLE].extract(i).as_bool(); - rd_clk_posedge = cell->parameters[ID::RD_CLK_POLARITY].extract(i).as_bool(); - rd_transparent = cell->parameters[ID::RD_TRANSPARENT].extract(i).as_bool(); + sig_rd_clk = cell->getPort("\\RD_CLK").extract(i); + sig_rd_en = cell->getPort("\\RD_EN").extract(i); + sig_rd_data = cell->getPort("\\RD_DATA").extract(i*width, width); + sig_rd_addr = cell->getPort("\\RD_ADDR").extract(i*abits, abits); + use_rd_clk = cell->parameters["\\RD_CLK_ENABLE"].extract(i).as_bool(); + rd_clk_posedge = cell->parameters["\\RD_CLK_POLARITY"].extract(i).as_bool(); + rd_transparent = cell->parameters["\\RD_TRANSPARENT"].extract(i).as_bool(); if (use_rd_clk) { { @@ -1310,18 +1220,18 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) } } - int nwrite_ports = cell->parameters[ID::WR_PORTS].as_int(); + int nwrite_ports = cell->parameters["\\WR_PORTS"].as_int(); RTLIL::SigSpec sig_wr_clk, sig_wr_data, sig_wr_addr, sig_wr_en; bool wr_clk_posedge; // write ports for (int i=0; i < nwrite_ports; i++) { - sig_wr_clk = cell->getPort(ID::WR_CLK).extract(i); - sig_wr_data = cell->getPort(ID::WR_DATA).extract(i*width, width); - sig_wr_addr = cell->getPort(ID::WR_ADDR).extract(i*abits, abits); - sig_wr_en = cell->getPort(ID::WR_EN).extract(i*width, width); - wr_clk_posedge = cell->parameters[ID::WR_CLK_POLARITY].extract(i).as_bool(); + sig_wr_clk = cell->getPort("\\WR_CLK").extract(i); + sig_wr_data = cell->getPort("\\WR_DATA").extract(i*width, width); + sig_wr_addr = cell->getPort("\\WR_ADDR").extract(i*abits, abits); + sig_wr_en = cell->getPort("\\WR_EN").extract(i*width, width); + wr_clk_posedge = cell->parameters["\\WR_CLK_POLARITY"].extract(i).as_bool(); { std::ostringstream os; dump_sigspec(os, sig_wr_clk); @@ -1408,66 +1318,66 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type.in(ID($assert), ID($assume), ID($cover))) + if (cell->type.in("$assert", "$assume", "$cover")) { f << stringf("%s" "always @* if (", indent.c_str()); - dump_sigspec(f, cell->getPort(ID::EN)); + dump_sigspec(f, cell->getPort("\\EN")); f << stringf(") %s(", cell->type.c_str()+1); - dump_sigspec(f, cell->getPort(ID::A)); + dump_sigspec(f, cell->getPort("\\A")); f << stringf(");\n"); return true; } - if (cell->type.in(ID($specify2), ID($specify3))) + if (cell->type.in("$specify2", "$specify3")) { f << stringf("%s" "specify\n%s ", indent.c_str(), indent.c_str()); - SigSpec en = cell->getPort(ID::EN); + SigSpec en = cell->getPort("\\EN"); if (en != State::S1) { f << stringf("if ("); - dump_sigspec(f, cell->getPort(ID::EN)); + dump_sigspec(f, cell->getPort("\\EN")); f << stringf(") "); } f << "("; - if (cell->type == ID($specify3) && cell->getParam(ID::EDGE_EN).as_bool()) - f << (cell->getParam(ID::EDGE_POL).as_bool() ? "posedge ": "negedge "); + if (cell->type == "$specify3" && cell->getParam("\\EDGE_EN").as_bool()) + f << (cell->getParam("\\EDGE_POL").as_bool() ? "posedge ": "negedge "); - dump_sigspec(f, cell->getPort(ID::SRC)); + dump_sigspec(f, cell->getPort("\\SRC")); f << " "; - if (cell->getParam(ID::SRC_DST_PEN).as_bool()) - f << (cell->getParam(ID::SRC_DST_POL).as_bool() ? "+": "-"); - f << (cell->getParam(ID::FULL).as_bool() ? "*> ": "=> "); + if (cell->getParam("\\SRC_DST_PEN").as_bool()) + f << (cell->getParam("\\SRC_DST_POL").as_bool() ? "+": "-"); + f << (cell->getParam("\\FULL").as_bool() ? "*> ": "=> "); - if (cell->type == ID($specify3)) { + if (cell->type == "$specify3") { f << "("; - dump_sigspec(f, cell->getPort(ID::DST)); + dump_sigspec(f, cell->getPort("\\DST")); f << " "; - if (cell->getParam(ID::DAT_DST_PEN).as_bool()) - f << (cell->getParam(ID::DAT_DST_POL).as_bool() ? "+": "-"); + if (cell->getParam("\\DAT_DST_PEN").as_bool()) + f << (cell->getParam("\\DAT_DST_POL").as_bool() ? "+": "-"); f << ": "; - dump_sigspec(f, cell->getPort(ID::DAT)); + dump_sigspec(f, cell->getPort("\\DAT")); f << ")"; } else { - dump_sigspec(f, cell->getPort(ID::DST)); + dump_sigspec(f, cell->getPort("\\DST")); } bool bak_decimal = decimal; decimal = 1; f << ") = ("; - dump_const(f, cell->getParam(ID::T_RISE_MIN)); + dump_const(f, cell->getParam("\\T_RISE_MIN")); f << ":"; - dump_const(f, cell->getParam(ID::T_RISE_TYP)); + dump_const(f, cell->getParam("\\T_RISE_TYP")); f << ":"; - dump_const(f, cell->getParam(ID::T_RISE_MAX)); + dump_const(f, cell->getParam("\\T_RISE_MAX")); f << ", "; - dump_const(f, cell->getParam(ID::T_FALL_MIN)); + dump_const(f, cell->getParam("\\T_FALL_MIN")); f << ":"; - dump_const(f, cell->getParam(ID::T_FALL_TYP)); + dump_const(f, cell->getParam("\\T_FALL_TYP")); f << ":"; - dump_const(f, cell->getParam(ID::T_FALL_MAX)); + dump_const(f, cell->getParam("\\T_FALL_MAX")); f << ");\n"; decimal = bak_decimal; @@ -1476,49 +1386,41 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type == ID($specrule)) + if (cell->type == "$specrule") { f << stringf("%s" "specify\n%s ", indent.c_str(), indent.c_str()); - IdString spec_type = cell->getParam(ID::TYPE).decode_string(); + string spec_type = cell->getParam("\\TYPE").decode_string(); f << stringf("%s(", spec_type.c_str()); - if (cell->getParam(ID::SRC_PEN).as_bool()) - f << (cell->getParam(ID::SRC_POL).as_bool() ? "posedge ": "negedge "); - dump_sigspec(f, cell->getPort(ID::SRC)); + if (cell->getParam("\\SRC_PEN").as_bool()) + f << (cell->getParam("\\SRC_POL").as_bool() ? "posedge ": "negedge "); + dump_sigspec(f, cell->getPort("\\SRC")); - if (cell->getPort(ID::SRC_EN) != State::S1) { + if (cell->getPort("\\SRC_EN") != State::S1) { f << " &&& "; - dump_sigspec(f, cell->getPort(ID::SRC_EN)); + dump_sigspec(f, cell->getPort("\\SRC_EN")); } f << ", "; - if (cell->getParam(ID::DST_PEN).as_bool()) - f << (cell->getParam(ID::DST_POL).as_bool() ? "posedge ": "negedge "); - dump_sigspec(f, cell->getPort(ID::DST)); + if (cell->getParam("\\DST_PEN").as_bool()) + f << (cell->getParam("\\DST_POL").as_bool() ? "posedge ": "negedge "); + dump_sigspec(f, cell->getPort("\\DST")); - if (cell->getPort(ID::DST_EN) != State::S1) { + if (cell->getPort("\\DST_EN") != State::S1) { f << " &&& "; - dump_sigspec(f, cell->getPort(ID::DST_EN)); + dump_sigspec(f, cell->getPort("\\DST_EN")); } bool bak_decimal = decimal; decimal = 1; f << ", "; - dump_const(f, cell->getParam(ID::T_LIMIT_MIN)); - f << ": "; - dump_const(f, cell->getParam(ID::T_LIMIT_TYP)); - f << ": "; - dump_const(f, cell->getParam(ID::T_LIMIT_MAX)); + dump_const(f, cell->getParam("\\T_LIMIT")); - if (spec_type.in(ID($setuphold), ID($recrem), ID($fullskew))) { + if (spec_type == "$setuphold" || spec_type == "$recrem" || spec_type == "$fullskew") { f << ", "; - dump_const(f, cell->getParam(ID::T_LIMIT2_MIN)); - f << ": "; - dump_const(f, cell->getParam(ID::T_LIMIT2_TYP)); - f << ": "; - dump_const(f, cell->getParam(ID::T_LIMIT2_MAX)); + dump_const(f, cell->getParam("\\T_LIMIT2")); } f << ");\n"; @@ -1602,9 +1504,9 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) } } - if (siminit && reg_ct.count(cell->type) && cell->hasPort(ID::Q)) { + if (siminit && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { std::stringstream ss; - dump_reg_init(ss, cell->getPort(ID::Q)); + dump_reg_init(ss, cell->getPort("\\Q")); if (!ss.str().empty()) { f << stringf("%sinitial %s.Q", indent.c_str(), cell_name.c_str()); f << ss.str(); @@ -1787,9 +1689,9 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) active_initdata.clear(); for (auto wire : module->wires()) - if (wire->attributes.count(ID::init)) { + if (wire->attributes.count("\\init")) { SigSpec sig = active_sigmap(wire); - Const val = wire->attributes.at(ID::init); + Const val = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(sig) && i < GetSize(val); i++) if (val[i] == State::S0 || val[i] == State::S1) active_initdata[sig[i]] = val[i]; @@ -1808,12 +1710,13 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) if (!noexpr) { std::set> reg_bits; - for (auto cell : module->cells()) + for (auto &it : module->cells_) { - if (!reg_ct.count(cell->type) || !cell->hasPort(ID::Q)) + RTLIL::Cell *cell = it.second; + if (!reg_ct.count(cell->type) || !cell->hasPort("\\Q")) continue; - RTLIL::SigSpec sig = cell->getPort(ID::Q); + RTLIL::SigSpec sig = cell->getPort("\\Q"); if (sig.is_chunk()) { RTLIL::SigChunk chunk = sig.as_chunk(); @@ -1822,8 +1725,9 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) reg_bits.insert(std::pair(chunk.wire, chunk.offset+i)); } } - for (auto wire : module->wires()) + for (auto &it : module->wires_) { + RTLIL::Wire *wire = it.second; for (int i = 0; i < wire->width; i++) if (reg_bits.count(std::pair(wire, i)) == 0) goto this_wire_aint_reg; @@ -1838,7 +1742,8 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) bool keep_running = true; for (int port_id = 1; keep_running; port_id++) { keep_running = false; - for (auto wire : module->wires()) { + for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) { + RTLIL::Wire *wire = it->second; if (wire->port_id == port_id) { if (port_id != 1) f << stringf(", "); @@ -1850,14 +1755,14 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) } f << stringf(");\n"); - for (auto w : module->wires()) - dump_wire(f, indent + " ", w); + for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) + dump_wire(f, indent + " ", it->second); for (auto it = module->memories.begin(); it != module->memories.end(); ++it) dump_memory(f, indent + " ", it->second); - for (auto cell : module->cells()) - dump_cell(f, indent + " ", cell); + for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) + dump_cell(f, indent + " ", it->second); for (auto it = module->processes.begin(); it != module->processes.end(); ++it) dump_process(f, indent + " ", it->second); @@ -1873,7 +1778,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) struct VerilogBackend : public Backend { VerilogBackend() : Backend("verilog", "write design to Verilog file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1953,7 +1858,7 @@ struct VerilogBackend : public Backend { log("this command is called on a design with RTLIL processes.\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing Verilog backend.\n"); @@ -1978,31 +1883,31 @@ struct VerilogBackend : public Backend { reg_wires.clear(); reg_ct.clear(); - reg_ct.insert(ID($dff)); - reg_ct.insert(ID($adff)); - reg_ct.insert(ID($dffe)); - reg_ct.insert(ID($dlatch)); - - reg_ct.insert(ID($_DFF_N_)); - reg_ct.insert(ID($_DFF_P_)); - - reg_ct.insert(ID($_DFF_NN0_)); - reg_ct.insert(ID($_DFF_NN1_)); - reg_ct.insert(ID($_DFF_NP0_)); - reg_ct.insert(ID($_DFF_NP1_)); - reg_ct.insert(ID($_DFF_PN0_)); - reg_ct.insert(ID($_DFF_PN1_)); - reg_ct.insert(ID($_DFF_PP0_)); - reg_ct.insert(ID($_DFF_PP1_)); - - reg_ct.insert(ID($_DFFSR_NNN_)); - reg_ct.insert(ID($_DFFSR_NNP_)); - reg_ct.insert(ID($_DFFSR_NPN_)); - reg_ct.insert(ID($_DFFSR_NPP_)); - reg_ct.insert(ID($_DFFSR_PNN_)); - reg_ct.insert(ID($_DFFSR_PNP_)); - reg_ct.insert(ID($_DFFSR_PPN_)); - reg_ct.insert(ID($_DFFSR_PPP_)); + reg_ct.insert("$dff"); + reg_ct.insert("$adff"); + reg_ct.insert("$dffe"); + reg_ct.insert("$dlatch"); + + reg_ct.insert("$_DFF_N_"); + reg_ct.insert("$_DFF_P_"); + + reg_ct.insert("$_DFF_NN0_"); + reg_ct.insert("$_DFF_NN1_"); + reg_ct.insert("$_DFF_NP0_"); + reg_ct.insert("$_DFF_NP1_"); + reg_ct.insert("$_DFF_PN0_"); + reg_ct.insert("$_DFF_PN1_"); + reg_ct.insert("$_DFF_PP0_"); + reg_ct.insert("$_DFF_PP1_"); + + reg_ct.insert("$_DFFSR_NNN_"); + reg_ct.insert("$_DFFSR_NNP_"); + reg_ct.insert("$_DFFSR_NPN_"); + reg_ct.insert("$_DFFSR_NPP_"); + reg_ct.insert("$_DFFSR_PNN_"); + reg_ct.insert("$_DFFSR_PNP_"); + reg_ct.insert("$_DFFSR_PPN_"); + reg_ct.insert("$_DFFSR_PPP_"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -2073,7 +1978,7 @@ struct VerilogBackend : public Backend { extra_args(f, filename, args, argidx); if (extmem) { - if (filename == "") + if (filename.empty()) log_cmd_error("Option -extmem must be used with a filename.\n"); extmem_prefix = filename.substr(0, filename.rfind('.')); } @@ -2081,16 +1986,16 @@ struct VerilogBackend : public Backend { design->sort(); *f << stringf("/* Generated by %s */\n", yosys_version_str); - for (auto module : design->modules()) { - if (module->get_blackbox_attribute() != blackboxes) + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { + if (it->second->get_blackbox_attribute() != blackboxes) continue; - if (selected && !design->selected_whole_module(module->name)) { - if (design->selected_module(module->name)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name)); + if (selected && !design->selected_whole_module(it->first)) { + if (design->selected_module(it->first)) + log_cmd_error("Can't handle partially selected module %s!\n", RTLIL::id2cstr(it->first)); continue; } - log("Dumping module `%s'.\n", module->name.c_str()); - dump_module(*f, "", module); + log("Dumping module `%s'.\n", it->first.c_str()); + dump_module(*f, "", it->second); } auto_name_map.clear(); diff --git a/examples/cxx-api/evaldemo.cc b/examples/cxx-api/evaldemo.cc index cfe0c080428..34373487d3e 100644 --- a/examples/cxx-api/evaldemo.cc +++ b/examples/cxx-api/evaldemo.cc @@ -22,15 +22,15 @@ struct EvalDemoPass : public Pass { EvalDemoPass() : Pass("evaldemo") { } - void execute(vector, Design *design) override + void execute(vector, Design *design) YS_OVERRIDE { Module *module = design->top_module(); if (module == nullptr) log_error("No top module found!\n"); - Wire *wire_a = module->wire(ID::A); - Wire *wire_y = module->wire(ID::Y); + Wire *wire_a = module->wire("\\A"); + Wire *wire_y = module->wire("\\Y"); if (wire_a == nullptr) log_error("No wire A found!\n"); diff --git a/examples/smtbmc/Makefile b/examples/smtbmc/Makefile index 61994f942fb..96fa058d6fb 100644 --- a/examples/smtbmc/Makefile +++ b/examples/smtbmc/Makefile @@ -1,5 +1,5 @@ -all: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 demo9 +all: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 demo1: demo1.smt2 yosys-smtbmc --dump-vcd demo1.vcd demo1.smt2 @@ -28,9 +28,6 @@ demo7: demo7.smt2 demo8: demo8.smt2 yosys-smtbmc -s z3 -t 1 -g demo8.smt2 -demo9: demo9.smt2 - yosys-smtbmc -s z3 -t 1 -g demo9.smt2 - demo1.smt2: demo1.v yosys -ql demo1.yslog -p 'read_verilog -formal demo1.v; prep -top demo1 -nordff; write_smt2 -wires demo1.smt2' @@ -55,9 +52,6 @@ demo7.smt2: demo7.v demo8.smt2: demo8.v yosys -ql demo8.yslog -p 'read_verilog -formal demo8.v; prep -top demo8 -nordff; write_smt2 -stbv -wires demo8.smt2' -demo9.smt2: demo9.v - yosys -ql demo9.yslog -p 'read_verilog -formal demo9.v; prep -top demo9 -nordff; write_smt2 -stbv -wires demo9.smt2' - clean: rm -f demo1.yslog demo1.smt2 demo1.vcd rm -f demo2.yslog demo2.smt2 demo2.vcd demo2.smtc demo2_tb.v demo2_tb demo2_tb.vcd @@ -67,7 +61,6 @@ clean: rm -f demo6.yslog demo6.smt2 rm -f demo7.yslog demo7.smt2 rm -f demo8.yslog demo8.smt2 - rm -f demo9.yslog demo9.smt2 -.PHONY: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 demo9 clean +.PHONY: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 clean diff --git a/examples/smtbmc/demo9.v b/examples/smtbmc/demo9.v deleted file mode 100644 index f0b91e2ca27..00000000000 --- a/examples/smtbmc/demo9.v +++ /dev/null @@ -1,13 +0,0 @@ -module demo9; - (* maximize *) wire[7:0] h = $anyconst; - wire [7:0] i = $allconst; - - wire [7:0] t0 = ((i << 8'b00000010) + 8'b00000011); - wire trigger = (t0 > h) && (h < 8'b00000100); - - always @* begin - assume(trigger == 1'b1); - cover(1); - end -endmodule - diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 07e3cd6e0aa..cf060193d03 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,9 +30,7 @@ #include #define __builtin_bswap32 OSSwapInt32 #endif -#ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS -#endif #include #include "kernel/yosys.h" @@ -69,7 +67,7 @@ struct ConstEvalAig continue; for (auto &it2 : it.second->connections()) if (yosys_celltypes.cell_output(it.second->type, it2.first)) { - auto r = sig2driver.insert(std::make_pair(it2.second, it.second)); + auto r YS_ATTRIBUTE(unused) = sig2driver.insert(std::make_pair(it2.second, it.second)); log_assert(r.second); } } @@ -119,7 +117,7 @@ struct ConstEvalAig sig2deps[output].insert(output); RTLIL::Cell *cell = sig2driver.at(output); - RTLIL::SigBit sig_a = cell->getPort(ID::A); + RTLIL::SigBit sig_a = cell->getPort("\\A"); sig2deps[sig_a].reserve(sig2deps[sig_a].size() + sig2deps[output].size()); // Reserve so that any invalidation // that may occur does so here, and // not mid insertion (below) @@ -127,8 +125,8 @@ struct ConstEvalAig if (!inputs.count(sig_a)) compute_deps(sig_a, inputs); - if (cell->type == ID($_AND_)) { - RTLIL::SigSpec sig_b = cell->getPort(ID::B); + if (cell->type == "$_AND_") { + RTLIL::SigSpec sig_b = cell->getPort("\\B"); sig2deps[sig_b].reserve(sig2deps[sig_b].size() + sig2deps[output].size()); // Reserve so that any invalidation // that may occur does so here, and // not mid insertion (below) @@ -137,34 +135,34 @@ struct ConstEvalAig if (!inputs.count(sig_b)) compute_deps(sig_b, inputs); } - else if (cell->type == ID($_NOT_)) { + else if (cell->type == "$_NOT_") { } else log_abort(); } bool eval(RTLIL::Cell *cell) { - RTLIL::SigBit sig_y = cell->getPort(ID::Y); + RTLIL::SigBit sig_y = cell->getPort("\\Y"); if (values_map.count(sig_y)) return true; - RTLIL::SigBit sig_a = cell->getPort(ID::A); + RTLIL::SigBit sig_a = cell->getPort("\\A"); if (!eval(sig_a)) return false; RTLIL::State eval_ret = RTLIL::Sx; - if (cell->type == ID($_NOT_)) { + if (cell->type == "$_NOT_") { if (sig_a == State::S0) eval_ret = State::S1; else if (sig_a == State::S1) eval_ret = State::S0; } - else if (cell->type == ID($_AND_)) { + else if (cell->type == "$_AND_") { if (sig_a == State::S0) { eval_ret = State::S0; goto eval_end; } { - RTLIL::SigBit sig_b = cell->getPort(ID::B); + RTLIL::SigBit sig_b = cell->getPort("\\B"); if (!eval(sig_b)) return false; if (sig_b == State::S0) { @@ -208,7 +206,7 @@ struct ConstEvalAig }; AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports) - : design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports), aiger_autoidx(autoidx++) + : design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports) { module = new RTLIL::Module; module->name = module_name; @@ -257,7 +255,7 @@ void AigerReader::parse_aiger() else log_abort(); - RTLIL::Wire* n0 = module->wire(stringf("$aiger%d$0", aiger_autoidx)); + RTLIL::Wire* n0 = module->wire("\\__0__"); if (n0) module->connect(n0, State::S0); @@ -273,24 +271,14 @@ void AigerReader::parse_aiger() if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) log_error("Line %u has invalid symbol position!\n", line_count); - RTLIL::IdString escaped_s = stringf("\\%s", s.c_str()); RTLIL::Wire* wire; if (c == 'i') wire = inputs[l1]; else if (c == 'l') wire = latches[l1]; - else if (c == 'o') { - wire = module->wire(escaped_s); - if (wire) { - // Could have been renamed by a latch - module->swap_names(wire, outputs[l1]); - module->connect(outputs[l1], wire); - goto next; - } - wire = outputs[l1]; - } + else if (c == 'o') wire = outputs[l1]; else if (c == 'b') wire = bad_properties[l1]; else log_abort(); - module->rename(wire, escaped_s); + module->rename(wire, stringf("\\%s", s.c_str())); } else if (c == 'j' || c == 'f') { // TODO @@ -305,7 +293,6 @@ void AigerReader::parse_aiger() } else log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); -next: std::getline(f, line); // Ignore up to start of next line } @@ -325,18 +312,18 @@ static uint32_t parse_xaiger_literal(std::istream &f) return from_big_endian(l); } -RTLIL::Wire* AigerReader::createWireIfNotExists(RTLIL::Module *module, unsigned literal) +static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) { const unsigned variable = literal >> 1; const bool invert = literal & 1; - RTLIL::IdString wire_name(stringf("$aiger%d$%d%s", aiger_autoidx, variable, invert ? "b" : "")); + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); RTLIL::Wire *wire = module->wire(wire_name); if (wire) return wire; log_debug2("Creating %s\n", wire_name.c_str()); wire = module->addWire(wire_name); wire->port_input = wire->port_output = false; if (!invert) return wire; - RTLIL::IdString wire_inv_name(stringf("$aiger%d$%d", aiger_autoidx, variable)); + RTLIL::IdString wire_inv_name(stringf("\\__%d__", variable)); RTLIL::Wire *wire_inv = module->wire(wire_inv_name); if (wire_inv) { if (module->cell(wire_inv_name)) return wire; @@ -348,12 +335,12 @@ RTLIL::Wire* AigerReader::createWireIfNotExists(RTLIL::Module *module, unsigned } log_debug2("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - module->addNotGate(stringf("$not$aiger%d$%d", aiger_autoidx, variable), wire_inv, wire); + module->addNotGate(stringf("\\__%d__$not", variable), wire_inv, wire); return wire; } -void AigerReader::parse_xaiger() +void AigerReader::parse_xaiger(const dict &box_lookup) { std::string header; f >> header; @@ -385,123 +372,108 @@ void AigerReader::parse_xaiger() else log_abort(); - RTLIL::Wire* n0 = module->wire(stringf("$aiger%d$0", aiger_autoidx)); + RTLIL::Wire* n0 = module->wire("\\__0__"); if (n0) module->connect(n0, State::S0); - int c = f.get(); - if (c != 'c') - log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); - if (f.peek() == '\n') - f.get(); - // Parse footer (symbol table, comments, etc.) std::string s; - for (int c = f.get(); c != EOF; c = f.get()) { - // XAIGER extensions - if (c == 'm') { - uint32_t dataSize = parse_xaiger_literal(f); - uint32_t lutNum = parse_xaiger_literal(f); - uint32_t lutSize = parse_xaiger_literal(f); - log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize); - ConstEvalAig ce(module); - for (unsigned i = 0; i < lutNum; ++i) { - uint32_t rootNodeID = parse_xaiger_literal(f); - uint32_t cutLeavesM = parse_xaiger_literal(f); - log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); - RTLIL::Wire *output_sig = module->wire(stringf("$aiger%d$%d", aiger_autoidx, rootNodeID)); - log_assert(output_sig); - uint32_t nodeID; - RTLIL::SigSpec input_sig; - for (unsigned j = 0; j < cutLeavesM; ++j) { - nodeID = parse_xaiger_literal(f); - log_debug2("\t%u\n", nodeID); - if (nodeID == 0) { - log_debug("\tLUT '$lut$aiger%d$%d' input %d is constant!\n", aiger_autoidx, rootNodeID, cutLeavesM); - continue; + bool comment_seen = false; + for (int c = f.peek(); c != EOF; c = f.peek()) { + if (comment_seen || c == 'c') { + if (!comment_seen) { + f.ignore(1); + c = f.peek(); + comment_seen = true; + } + if (c == '\n') + break; + f.ignore(1); + // XAIGER extensions + if (c == 'm') { + uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + uint32_t lutNum = parse_xaiger_literal(f); + uint32_t lutSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize); + ConstEvalAig ce(module); + for (unsigned i = 0; i < lutNum; ++i) { + uint32_t rootNodeID = parse_xaiger_literal(f); + uint32_t cutLeavesM = parse_xaiger_literal(f); + log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); + RTLIL::Wire *output_sig = module->wire(stringf("\\__%d__", rootNodeID)); + uint32_t nodeID; + RTLIL::SigSpec input_sig; + for (unsigned j = 0; j < cutLeavesM; ++j) { + nodeID = parse_xaiger_literal(f); + log_debug2("\t%u\n", nodeID); + RTLIL::Wire *wire = module->wire(stringf("\\__%d__", nodeID)); + log_assert(wire); + input_sig.append(wire); } - RTLIL::Wire *wire = module->wire(stringf("$aiger%d$%d", aiger_autoidx, nodeID)); - log_assert(wire); - input_sig.append(wire); + // TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size()) + ce.clear(); + ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); + RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size()); + for (int j = 0; j < (1 << cutLeavesM); ++j) { + int gray = j ^ (j >> 1); + ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast(cutLeavesM)}); + RTLIL::SigBit o(output_sig); + bool success YS_ATTRIBUTE(unused) = ce.eval(o); + log_assert(success); + log_assert(o.wire == nullptr); + lut_mask[gray] = o.data; + } + RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID)); + log_assert(output_cell); + module->remove(output_cell); + module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } - // Reverse input order as fastest input is returned first - input_sig.reverse(); - // TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size()) - ce.clear(); - ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); - RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << GetSize(input_sig)); - for (int j = 0; j < GetSize(lut_mask); ++j) { - int gray = j ^ (j >> 1); - ce.set_incremental(input_sig, RTLIL::Const{gray, GetSize(input_sig)}); - RTLIL::SigBit o(output_sig); - bool success = ce.eval(o); - log_assert(success); - log_assert(o.wire == nullptr); - lut_mask[gray] = o.data; + } + else if (c == 'r') { + uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + flopNum = parse_xaiger_literal(f); + log_debug("flopNum: %u\n", flopNum); + log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); + f.ignore(flopNum * sizeof(uint32_t)); + } + else if (c == 'n') { + parse_xaiger_literal(f); + f >> s; + log_debug("n: '%s'\n", s.c_str()); + } + else if (c == 'h') { + f.ignore(sizeof(uint32_t)); + uint32_t version YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_assert(version == 1); + uint32_t ciNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_debug("ciNum = %u\n", ciNum); + uint32_t coNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_debug("coNum = %u\n", coNum); + piNum = parse_xaiger_literal(f); + log_debug("piNum = %u\n", piNum); + uint32_t poNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_debug("poNum = %u\n", poNum); + uint32_t boxNum = parse_xaiger_literal(f); + log_debug("boxNum = %u\n", boxNum); + for (unsigned i = 0; i < boxNum; i++) { + f.ignore(2*sizeof(uint32_t)); + uint32_t boxUniqueId = parse_xaiger_literal(f); + log_assert(boxUniqueId > 0); + uint32_t oldBoxNum = parse_xaiger_literal(f); + RTLIL::Cell* cell = module->addCell(stringf("$__box%u__", oldBoxNum), box_lookup.at(boxUniqueId)); + boxes.emplace_back(cell); } - RTLIL::Cell *output_cell = module->cell(stringf("$and$aiger%d$%d", aiger_autoidx, rootNodeID)); - log_assert(output_cell); - module->remove(output_cell); - module->addLut(stringf("$lut$aiger%d$%d", aiger_autoidx, rootNodeID), input_sig, output_sig, std::move(lut_mask)); } - } - else if (c == 'r') { - uint32_t dataSize = parse_xaiger_literal(f); - flopNum = parse_xaiger_literal(f); - log_debug("flopNum = %u\n", flopNum); - log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); - mergeability.reserve(flopNum); - for (unsigned i = 0; i < flopNum; i++) - mergeability.emplace_back(parse_xaiger_literal(f)); - } - else if (c == 's') { - uint32_t dataSize = parse_xaiger_literal(f); - flopNum = parse_xaiger_literal(f); - log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); - initial_state.reserve(flopNum); - for (unsigned i = 0; i < flopNum; i++) - initial_state.emplace_back(parse_xaiger_literal(f)); - } - else if (c == 'n') { - parse_xaiger_literal(f); - f >> s; - log_debug("n: '%s'\n", s.c_str()); - } - else if (c == 'h') { - f.ignore(sizeof(uint32_t)); - uint32_t version = parse_xaiger_literal(f); - log_assert(version == 1); - uint32_t ciNum = parse_xaiger_literal(f); - log_debug("ciNum = %u\n", ciNum); - uint32_t coNum = parse_xaiger_literal(f); - log_debug("coNum = %u\n", coNum); - piNum = parse_xaiger_literal(f); - log_debug("piNum = %u\n", piNum); - uint32_t poNum = parse_xaiger_literal(f); - log_debug("poNum = %u\n", poNum); - uint32_t boxNum = parse_xaiger_literal(f); - log_debug("boxNum = %u\n", boxNum); - for (unsigned i = 0; i < boxNum; i++) { - uint32_t boxInputs = parse_xaiger_literal(f); - uint32_t boxOutputs = parse_xaiger_literal(f); - uint32_t boxUniqueId = parse_xaiger_literal(f); - log_assert(boxUniqueId > 0); - uint32_t oldBoxNum = parse_xaiger_literal(f); - RTLIL::Cell* cell = module->addCell(stringf("$box%u", oldBoxNum), stringf("$__boxid%u", boxUniqueId)); - cell->setPort(ID(i), SigSpec(State::S0, boxInputs)); - cell->setPort(ID(o), SigSpec(State::S0, boxOutputs)); - cell->attributes[ID::abc9_box_seq] = oldBoxNum; - boxes.emplace_back(cell); + else if (c == 'a' || c == 'i' || c == 'o') { + uint32_t dataSize = parse_xaiger_literal(f); + f.ignore(dataSize); + } + else { + break; } } - else if (c == 'a' || c == 'i' || c == 'o' || c == 's') { - uint32_t dataSize = parse_xaiger_literal(f); - f.ignore(dataSize); - log_debug("ignoring '%c'\n", c); - } - else { - break; - } + else + log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); } post_process(); @@ -515,15 +487,13 @@ void AigerReader::parse_aiger_ascii() unsigned l1, l2, l3; // Parse inputs - int digits = ceil(log10(I)); for (unsigned i = 1; i <= I; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an input!\n", line_count); log_debug2("%d is an input\n", l1); log_assert(!(l1 & 1)); // Inputs can't be inverted - RTLIL::Wire *wire = module->addWire(stringf("$i%0*d", digits, l1 >> 1)); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_input = true; - module->connect(createWireIfNotExists(module, l1), wire); inputs.push_back(wire); } @@ -537,14 +507,12 @@ void AigerReader::parse_aiger_ascii() clk_wire->port_input = true; clk_wire->port_output = false; } - digits = ceil(log10(L)); for (unsigned i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) log_error("Line %u cannot be interpreted as a latch!\n", line_count); log_debug2("%d %d is a latch\n", l1, l2); log_assert(!(l1 & 1)); - RTLIL::Wire *q_wire = module->addWire(stringf("$l%0*d", digits, l1 >> 1)); - module->connect(createWireIfNotExists(module, l1), q_wire); + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); if (clk_wire) @@ -558,35 +526,42 @@ void AigerReader::parse_aiger_ascii() log_error("Line %u cannot be interpreted as a latch!\n", line_count); if (l3 == 0) - q_wire->attributes[ID::init] = State::S0; + q_wire->attributes["\\init"] = State::S0; else if (l3 == 1) - q_wire->attributes[ID::init] = State::S1; + q_wire->attributes["\\init"] = State::S1; else if (l3 == l1) { - //q_wire->attributes[ID::init] = RTLIL::Sx; + //q_wire->attributes["\\init"] = RTLIL::Sx; } else log_error("Line %u has invalid reset literal for latch!\n", line_count); } else { // AIGER latches are assumed to be initialized to zero - q_wire->attributes[ID::init] = State::S0; + q_wire->attributes["\\init"] = State::S0; } latches.push_back(q_wire); } // Parse outputs - digits = ceil(log10(O)); for (unsigned i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); log_debug2("%d is an output\n", l1); - RTLIL::Wire *wire = module->addWire(stringf("$o%0*d", digits, i)); + const unsigned variable = l1 >> 1; + const bool invert = l1 & 1; + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (!wire) + wire = createWireIfNotExists(module, l1); + else if (wire->port_input || wire->port_output) { + RTLIL::Wire *new_wire = module->addWire(NEW_ID); + module->connect(new_wire, wire); + wire = new_wire; + } wire->port_output = true; - module->connect(wire, createWireIfNotExists(module, l1)); outputs.push_back(wire); } - //std::getline(f, line); // Ignore up to start of next line // Parse bad properties for (unsigned i = 0; i < B; ++i, ++line_count) { @@ -598,8 +573,6 @@ void AigerReader::parse_aiger_ascii() wire->port_output = true; bad_properties.push_back(wire); } - //if (B > 0) - // std::getline(f, line); // Ignore up to start of next line // TODO: Parse invariant constraints for (unsigned i = 0; i < C; ++i, ++line_count) @@ -623,7 +596,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - module->addAndGate("$and" + o_wire->name.str(), i1_wire, i2_wire, o_wire); + module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire); } std::getline(f, line); // Ignore up to start of next line } @@ -643,12 +616,11 @@ void AigerReader::parse_aiger_binary() std::string line; // Parse inputs - int digits = ceil(log10(I)); for (unsigned i = 1; i <= I; ++i) { log_debug2("%d is an input\n", i); - RTLIL::Wire *wire = module->addWire(stringf("$i%0*d", digits, i)); + RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); wire->port_input = true; - module->connect(createWireIfNotExists(module, i << 1), wire); + log_assert(!wire->port_output); inputs.push_back(wire); } @@ -662,14 +634,12 @@ void AigerReader::parse_aiger_binary() clk_wire->port_input = true; clk_wire->port_output = false; } - digits = ceil(log10(L)); l1 = (I+1) * 2; for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) { if (!(f >> l2)) log_error("Line %u cannot be interpreted as a latch!\n", line_count); log_debug("%d %d is a latch\n", l1, l2); - RTLIL::Wire *q_wire = module->addWire(stringf("$l%0*d", digits, l1 >> 1)); - module->connect(createWireIfNotExists(module, l1), q_wire); + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); if (clk_wire) @@ -683,32 +653,40 @@ void AigerReader::parse_aiger_binary() log_error("Line %u cannot be interpreted as a latch!\n", line_count); if (l3 == 0) - q_wire->attributes[ID::init] = State::S0; + q_wire->attributes["\\init"] = State::S0; else if (l3 == 1) - q_wire->attributes[ID::init] = State::S1; + q_wire->attributes["\\init"] = State::S1; else if (l3 == l1) { - //q_wire->attributes[ID::init] = RTLIL::Sx; + //q_wire->attributes["\\init"] = RTLIL::Sx; } else log_error("Line %u has invalid reset literal for latch!\n", line_count); } else { // AIGER latches are assumed to be initialized to zero - q_wire->attributes[ID::init] = State::S0; + q_wire->attributes["\\init"] = State::S0; } latches.push_back(q_wire); } // Parse outputs - digits = ceil(log10(O)); for (unsigned i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); log_debug2("%d is an output\n", l1); - RTLIL::Wire *wire = module->addWire(stringf("$o%0*d", digits, i)); + const unsigned variable = l1 >> 1; + const bool invert = l1 & 1; + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_b" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (!wire) + wire = createWireIfNotExists(module, l1); + else if (wire->port_input || wire->port_output) { + RTLIL::Wire *new_wire = module->addWire(NEW_ID); + module->connect(new_wire, wire); + wire = new_wire; + } wire->port_output = true; - module->connect(wire, createWireIfNotExists(module, l1)); outputs.push_back(wire); } std::getline(f, line); // Ignore up to start of next line @@ -749,49 +727,89 @@ void AigerReader::parse_aiger_binary() RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - module->addAndGate("$and" + o_wire->name.str(), i1_wire, i2_wire, o_wire); + module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire); } } void AigerReader::post_process() { + pool seen_boxes; unsigned ci_count = 0, co_count = 0; for (auto cell : boxes) { - for (auto &bit : cell->connections_.at(ID(i))) { - log_assert(bit == State::S0); - log_assert(co_count < outputs.size()); - bit = outputs[co_count++]; - log_assert(bit.wire && GetSize(bit.wire) == 1); - log_assert(bit.wire->port_output); - bit.wire->port_output = false; - } - for (auto &bit : cell->connections_.at(ID(o))) { - log_assert(bit == State::S0); - log_assert((piNum + ci_count) < inputs.size()); - bit = inputs[piNum + ci_count++]; - log_assert(bit.wire && GetSize(bit.wire) == 1); - log_assert(bit.wire->port_input); - bit.wire->port_input = false; + RTLIL::Module* box_module = design->module(cell->type); + log_assert(box_module); + + if (seen_boxes.insert(cell->type).second) { + auto it = box_module->attributes.find("\\abc9_carry"); + if (it != box_module->attributes.end()) { + RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; + auto carry_in_out = it->second.decode_string(); + auto pos = carry_in_out.find(','); + if (pos == std::string::npos) + log_error("'abc9_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); + auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); + carry_in = box_module->wire(carry_in_name); + if (!carry_in || !carry_in->port_input) + log_error("'abc9_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); + + auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); + carry_out = box_module->wire(carry_out_name); + if (!carry_out || !carry_out->port_output) + log_error("'abc9_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); + + auto &ports = box_module->ports; + for (auto jt = ports.begin(); jt != ports.end(); ) { + RTLIL::Wire* w = box_module->wire(*jt); + log_assert(w); + if (w == carry_in || w == carry_out) { + jt = ports.erase(jt); + continue; + } + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); + ++jt; + } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); + } } - } - - for (uint32_t i = 0; i < flopNum; i++) { - RTLIL::Wire *d = outputs[outputs.size() - flopNum + i]; - log_assert(d); - log_assert(d->port_output); - d->port_output = false; - RTLIL::Wire *q = inputs[piNum - flopNum + i]; - log_assert(q); - log_assert(q->port_input); - q->port_input = false; + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (auto port_name : box_module->ports) { + RTLIL::Wire* port = box_module->wire(port_name); + log_assert(port); + RTLIL::SigSpec rhs; + for (int i = 0; i < GetSize(port); i++) { + RTLIL::Wire* wire = nullptr; + if (port->port_input) { + log_assert(co_count < outputs.size()); + wire = outputs[co_count++]; + log_assert(wire); + log_assert(wire->port_output); + wire->port_output = false; + } + if (port->port_output) { + log_assert((piNum + ci_count) < inputs.size()); + wire = inputs[piNum + ci_count++]; + log_assert(wire); + log_assert(wire->port_input); + wire->port_input = false; + } + rhs.append(wire); + } - Cell* ff = module->addFfGate(NEW_ID, d, q); - ff->attributes[ID::abc9_mergeability] = mergeability[i]; - q->attributes[ID::init] = initial_state[i]; + cell->setPort(port_name, rhs); + } } - dict> wideports_cache; + dict wideports_cache; if (!map_filename.empty()) { std::ifstream mf(map_filename); @@ -806,98 +824,114 @@ void AigerReader::post_process() log_assert(wire->port_input); log_debug("Renaming input %s", log_id(wire)); - RTLIL::Wire *existing = nullptr; if (index == 0) { // Cope with the fact that a CI might be identical // to a PI (necessary due to ABC); in those cases // simply connect the latter to the former - existing = module->wire(escaped_s); + RTLIL::Wire* existing = module->wire(escaped_s); if (!existing) module->rename(wire, escaped_s); else { wire->port_input = false; module->connect(wire, existing); } - log_debug(" -> %s\n", log_id(escaped_s)); } - else { - RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s.c_str(), index); - existing = module->wire(indexed_name); - if (!existing) + else if (index > 0) { + std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index); + RTLIL::Wire* existing = module->wire(indexed_name); + if (!existing) { module->rename(wire, indexed_name); + if (wideports) + wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); + } else { module->connect(wire, existing); wire->port_input = false; } - log_debug(" -> %s\n", log_id(indexed_name)); - } - - if (wideports && !existing) { - auto r = wideports_cache.insert(escaped_s); - if (r.second) { - r.first->second.first = index; - r.first->second.second = index; - } - else { - r.first->second.first = std::min(r.first->second.first, index); - r.first->second.second = std::max(r.first->second.second, index); - } } + log_debug(" -> %s\n", log_id(wire)); } else if (type == "output") { log_assert(static_cast(variable + co_count) < outputs.size()); RTLIL::Wire* wire = outputs[variable + co_count]; log_assert(wire); log_assert(wire->port_output); + if (escaped_s == "$__dummy__") { + wire->port_output = false; + continue; + } log_debug("Renaming output %s", log_id(wire)); - RTLIL::Wire *existing; if (index == 0) { // Cope with the fact that a CO might be identical // to a PO (necessary due to ABC); in those cases // simply connect the latter to the former - existing = module->wire(escaped_s); - if (!existing) - module->rename(wire, escaped_s); - else { - wire->port_output = false; - existing->port_output = true; - module->connect(wire, existing); - wire = existing; + RTLIL::Wire* existing = module->wire(escaped_s); + if (!existing) { + if (escaped_s.ends_with("$inout.out")) { + wire->port_output = false; + RTLIL::Wire *in_wire = module->wire(escaped_s.substr(1, escaped_s.size()-11)); + log_assert(in_wire); + log_assert(in_wire->port_input && !in_wire->port_output); + in_wire->port_output = true; + module->connect(in_wire, wire); + } + else + module->rename(wire, escaped_s); } - log_debug(" -> %s\n", log_id(escaped_s)); - } - else { - RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s.c_str(), index); - existing = module->wire(indexed_name); - if (!existing) - module->rename(wire, indexed_name); else { wire->port_output = false; - existing->port_output = true; module->connect(wire, existing); + wire = existing; } - log_debug(" -> %s\n", log_id(indexed_name)); } - - if (wideports && !existing) { - auto r = wideports_cache.insert(escaped_s); - if (r.second) { - r.first->second.first = index; - r.first->second.second = index; + else if (index > 0) { + std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index); + RTLIL::Wire* existing = module->wire(indexed_name); + if (!existing) { + if (escaped_s.ends_with("$inout.out")) { + wire->port_output = false; + RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(1, escaped_s.size()-11).c_str(), index)); + log_assert(in_wire); + log_assert(in_wire->port_input && !in_wire->port_output); + in_wire->port_output = true; + module->connect(in_wire, wire); + } + else { + module->rename(wire, indexed_name); + if (wideports) + wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); + } } else { - r.first->second.first = std::min(r.first->second.first, index); - r.first->second.second = std::max(r.first->second.second, index); + module->connect(wire, existing); + wire->port_output = false; } } + log_debug(" -> %s\n", log_id(wire)); } else if (type == "box") { - RTLIL::Cell* cell = module->cell(stringf("$box%d", variable)); - if (!cell) - log_debug("Box %d (%s) no longer exists.\n", variable, log_id(escaped_s)); - else + RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); + if (cell) { // ABC could have optimised this box away module->rename(cell, escaped_s); + for (const auto &i : cell->connections()) { + RTLIL::IdString port_name = i.first; + RTLIL::SigSpec rhs = i.second; + int index = 0; + for (auto bit : rhs.bits()) { + RTLIL::Wire* wire = bit.wire; + RTLIL::IdString escaped_s = RTLIL::escape_id(stringf("%s.%s", log_id(cell), log_id(port_name))); + if (index == 0) + module->rename(wire, escaped_s); + else if (index > 0) { + module->rename(wire, stringf("%s[%d]", escaped_s.c_str(), index)); + if (wideports) + wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); + } + index++; + } + } + } } else log_error("Symbol type '%s' not recognised.\n", type.c_str()); @@ -906,10 +940,7 @@ void AigerReader::post_process() for (auto &wp : wideports_cache) { auto name = wp.first; - int min = wp.second.first; - int max = wp.second.second; - if (min == 0 && max == 0) - continue; + int width = wp.second + 1; RTLIL::Wire *wire = module->wire(name); if (wire) @@ -918,7 +949,7 @@ void AigerReader::post_process() // Do not make ports with a mix of input/output into // wide ports bool port_input = false, port_output = false; - for (int i = min; i <= max; i++) { + for (int i = 0; i < width; i++) { RTLIL::IdString other_name = name.str() + stringf("[%d]", i); RTLIL::Wire *other_wire = module->wire(other_name); if (other_wire) { @@ -927,21 +958,25 @@ void AigerReader::post_process() } } - wire = module->addWire(name, max-min+1); - wire->start_offset = min; + wire = module->addWire(name, width); wire->port_input = port_input; wire->port_output = port_output; - for (int i = min; i <= max; i++) { - RTLIL::IdString other_name = stringf("%s[%d]", name.c_str(), i); + for (int i = 0; i < width; i++) { + RTLIL::IdString other_name = name.str() + stringf("[%d]", i); RTLIL::Wire *other_wire = module->wire(other_name); if (other_wire) { other_wire->port_input = false; other_wire->port_output = false; - if (wire->port_input) - module->connect(other_wire, SigSpec(wire, i-min)); - else - module->connect(SigSpec(wire, i-min), other_wire); + } + if (wire->port_input) { + if (other_wire) + module->connect(other_wire, SigSpec(wire, i)); + } + else { + // Since we skip POs that are connected to Sx, + // re-connect them here + module->connect(SigSpec(wire, i), other_wire ? other_wire : SigSpec(RTLIL::Sx)); } } } @@ -959,18 +994,18 @@ void AigerReader::post_process() design->add(module); for (auto cell : module->cells().to_vector()) { - if (cell->type != ID($lut)) continue; - auto y_port = cell->getPort(ID::Y).as_bit(); + if (cell->type != "$lut") continue; + auto y_port = cell->getPort("\\Y").as_bit(); if (y_port.wire->width == 1) - module->rename(cell, stringf("$lut%s", y_port.wire->name.c_str())); + module->rename(cell, stringf("%s$lut", y_port.wire->name.c_str())); else - module->rename(cell, stringf("$lut%s[%d]", y_port.wire->name.c_str(), y_port.offset)); + module->rename(cell, stringf("%s[%d]$lut", y_port.wire->name.c_str(), y_port.offset)); } } struct AigerFrontend : public Frontend { AigerFrontend() : Frontend("aiger", "read AIGER file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -979,31 +1014,28 @@ struct AigerFrontend : public Frontend { log("Load module from an AIGER file into the current design.\n"); log("\n"); log(" -module_name \n"); - log(" name of module to be created (default: )\n"); + log(" Name of module to be created (default: )\n"); log("\n"); log(" -clk_name \n"); - log(" if specified, AIGER latches to be transformed into $_DFF_P_ cells\n"); - log(" clocked by wire of this name. otherwise, $_FF_ cells will be used\n"); + log(" If specified, AIGER latches to be transformed into $_DFF_P_ cells\n"); + log(" clocked by wire of this name. Otherwise, $_FF_ cells will be used.\n"); log("\n"); log(" -map \n"); log(" read file with port and latch symbols\n"); log("\n"); log(" -wideports\n"); - log(" merge ports that match the pattern 'name[int]' into a single\n"); - log(" multi-bit port 'name'\n"); - log("\n"); - log(" -xaiger\n"); - log(" read XAIGER extensions\n"); + log(" Merge ports that match the pattern 'name[int]' into a single\n"); + log(" multi-bit port 'name'.\n"); log("\n"); } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing AIGER frontend.\n"); - RTLIL::IdString clk_name; + RTLIL::IdString clk_name = "\\clk"; RTLIL::IdString module_name; std::string map_filename; - bool wideports = false, xaiger = false; + bool wideports = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -1024,10 +1056,6 @@ struct AigerFrontend : public Frontend { wideports = true; continue; } - if (arg == "-xaiger") { - xaiger = true; - continue; - } break; } extra_args(f, filename, args, argidx, true); @@ -1047,10 +1075,7 @@ struct AigerFrontend : public Frontend { } AigerReader reader(design, *f, module_name, clk_name, map_filename, wideports); - if (xaiger) - reader.parse_xaiger(); - else - reader.parse_aiger(); + reader.parse_aiger(); } } AigerFrontend; diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 251a24977e2..583c9d0f999 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -33,7 +33,6 @@ struct AigerReader RTLIL::Module *module; std::string map_filename; bool wideports; - const int aiger_autoidx; unsigned M, I, L, O, A; unsigned B, C, J, F; // Optional in AIGER 1.9 @@ -45,16 +44,13 @@ struct AigerReader std::vector outputs; std::vector bad_properties; std::vector boxes; - std::vector mergeability, initial_state; AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); void parse_aiger(); - void parse_xaiger(); + void parse_xaiger(const dict &box_lookup); void parse_aiger_ascii(); void parse_aiger_binary(); void post_process(); - - RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal); }; YOSYS_NAMESPACE_END diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 03fd272dafd..5bbea0faf69 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -88,13 +88,10 @@ std::string AST::type2str(AstNodeType type) X(AST_LIVE) X(AST_FAIR) X(AST_COVER) - X(AST_ENUM) - X(AST_ENUM_ITEM) X(AST_FCALL) X(AST_TO_BITS) X(AST_TO_SIGNED) X(AST_TO_UNSIGNED) - X(AST_SELFSZ) X(AST_CONCAT) X(AST_REPLICATE) X(AST_BIT_NOT) @@ -111,8 +108,6 @@ std::string AST::type2str(AstNodeType type) X(AST_SHIFT_RIGHT) X(AST_SHIFT_SLEFT) X(AST_SHIFT_SRIGHT) - X(AST_SHIFTX) - X(AST_SHIFT) X(AST_LT) X(AST_LE) X(AST_EQ) @@ -171,9 +166,6 @@ std::string AST::type2str(AstNodeType type) X(AST_PACKAGE) X(AST_WIRETYPE) X(AST_TYPEDEF) - X(AST_STRUCT) - X(AST_UNION) - X(AST_STRUCT_ITEM) #undef X default: log_abort(); @@ -188,7 +180,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id) AstNode *attr = attributes.at(id); if (attr->type != AST_CONSTANT) - log_file_error(attr->filename, attr->location.first_line, "Attribute `%s' with non-constant value!\n", id.c_str()); + log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", id.c_str()); return attr->integer != 0; } @@ -203,13 +195,13 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch this->type = type; filename = current_filename; + linenum = get_line_num(); is_input = false; is_output = false; is_reg = false; is_logic = false; is_signed = false; is_string = false; - is_enum = false; is_wand = false; is_wor = false; is_unsized = false; @@ -224,7 +216,6 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch realvalue = 0; id2ast = NULL; basic_prep = false; - lookahead = false; if (child1) children.push_back(child1); @@ -286,8 +277,7 @@ void AstNode::dumpAst(FILE *f, std::string indent) const } std::string type_name = type2str(type); - fprintf(f, "%s%s <%s:%d.%d-%d.%d>", indent.c_str(), type_name.c_str(), filename.c_str(), location.first_line, - location.first_column, location.last_line, location.last_column); + fprintf(f, "%s%s <%s:%d>", indent.c_str(), type_name.c_str(), filename.c_str(), linenum); if (!flag_no_dump_ptr) { if (id2ast) @@ -317,10 +307,6 @@ void AstNode::dumpAst(FILE *f, std::string indent) const fprintf(f, " reg"); if (is_signed) fprintf(f, " signed"); - if (basic_prep) - fprintf(f, " basic_prep"); - if (lookahead) - fprintf(f, " lookahead"); if (port_id > 0) fprintf(f, " port=%d", port_id); if (range_valid || range_left != -1 || range_right != 0) @@ -335,9 +321,6 @@ void AstNode::dumpAst(FILE *f, std::string indent) const fprintf(f, " %d", v); fprintf(f, " ]"); } - if (is_enum) { - fprintf(f, " type=enum"); - } fprintf(f, "\n"); for (auto &it : attributes) { @@ -621,7 +604,6 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const if (0) { case AST_POS: txt = "+"; } if (0) { case AST_NEG: txt = "-"; } if (0) { case AST_LOGIC_NOT: txt = "!"; } - if (0) { case AST_SELFSZ: txt = "@selfsz@"; } fprintf(f, "%s(", txt.c_str()); children[0]->dumpVlog(f, ""); fprintf(f, ")"); @@ -635,8 +617,6 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const if (0) { case AST_SHIFT_RIGHT: txt = ">>"; } if (0) { case AST_SHIFT_SLEFT: txt = "<<<"; } if (0) { case AST_SHIFT_SRIGHT: txt = ">>>"; } - if (0) { case AST_SHIFTX: txt = "@shiftx@"; } - if (0) { case AST_SHIFT: txt = "@shift@"; } if (0) { case AST_LT: txt = "<"; } if (0) { case AST_LE: txt = "<="; } if (0) { case AST_EQ: txt = "=="; } @@ -953,23 +933,20 @@ RTLIL::Const AstNode::realAsConst(int width) } // create a new AstModule from an AST_MODULE AST node -static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false) +static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL) { - log_assert(current_scope.empty()); log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); if (defer) log("Storing AST representation for module `%s'.\n", ast->str.c_str()); - else if (!quiet) { + else log("Generating RTLIL representation for module `%s'.\n", ast->str.c_str()); - } current_module = new AstModule; current_module->ast = NULL; current_module->name = ast->str; - current_module->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line, - ast->location.first_column, ast->location.last_line, ast->location.last_column); - current_module->set_bool_attribute(ID::cells_not_processed); + current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum); + current_module->set_bool_attribute("\\cells_not_processed"); current_ast_mod = ast; AstNode *ast_before_simplify; @@ -1022,61 +999,61 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast log("--- END OF AST DUMP ---\n"); } - if (flag_nowb && ast->attributes.count(ID::whitebox)) { - delete ast->attributes.at(ID::whitebox); - ast->attributes.erase(ID::whitebox); + if (flag_nowb && ast->attributes.count("\\whitebox")) { + delete ast->attributes.at("\\whitebox"); + ast->attributes.erase("\\whitebox"); } - if (ast->attributes.count(ID::lib_whitebox)) { + if (ast->attributes.count("\\lib_whitebox")) { if (!flag_lib || flag_nowb) { - delete ast->attributes.at(ID::lib_whitebox); - ast->attributes.erase(ID::lib_whitebox); + delete ast->attributes.at("\\lib_whitebox"); + ast->attributes.erase("\\lib_whitebox"); } else { - if (ast->attributes.count(ID::whitebox)) { - delete ast->attributes.at(ID::whitebox); - ast->attributes.erase(ID::whitebox); + if (ast->attributes.count("\\whitebox")) { + delete ast->attributes.at("\\whitebox"); + ast->attributes.erase("\\whitebox"); } - AstNode *n = ast->attributes.at(ID::lib_whitebox); - ast->attributes[ID::whitebox] = n; - ast->attributes.erase(ID::lib_whitebox); + AstNode *n = ast->attributes.at("\\lib_whitebox"); + ast->attributes["\\whitebox"] = n; + ast->attributes.erase("\\lib_whitebox"); } } - if (!blackbox_module && ast->attributes.count(ID::blackbox)) { - AstNode *n = ast->attributes.at(ID::blackbox); + if (!blackbox_module && ast->attributes.count("\\blackbox")) { + AstNode *n = ast->attributes.at("\\blackbox"); if (n->type != AST_CONSTANT) - log_file_error(ast->filename, ast->location.first_line, "Got blackbox attribute with non-constant value!\n"); + log_file_error(ast->filename, ast->linenum, "Got blackbox attribute with non-constant value!\n"); blackbox_module = n->asBool(); } - if (blackbox_module && ast->attributes.count(ID::whitebox)) { - AstNode *n = ast->attributes.at(ID::whitebox); + if (blackbox_module && ast->attributes.count("\\whitebox")) { + AstNode *n = ast->attributes.at("\\whitebox"); if (n->type != AST_CONSTANT) - log_file_error(ast->filename, ast->location.first_line, "Got whitebox attribute with non-constant value!\n"); + log_file_error(ast->filename, ast->linenum, "Got whitebox attribute with non-constant value!\n"); blackbox_module = !n->asBool(); } - if (ast->attributes.count(ID::noblackbox)) { + if (ast->attributes.count("\\noblackbox")) { if (blackbox_module) { - AstNode *n = ast->attributes.at(ID::noblackbox); + AstNode *n = ast->attributes.at("\\noblackbox"); if (n->type != AST_CONSTANT) - log_file_error(ast->filename, ast->location.first_line, "Got noblackbox attribute with non-constant value!\n"); + log_file_error(ast->filename, ast->linenum, "Got noblackbox attribute with non-constant value!\n"); blackbox_module = !n->asBool(); } - delete ast->attributes.at(ID::noblackbox); - ast->attributes.erase(ID::noblackbox); + delete ast->attributes.at("\\noblackbox"); + ast->attributes.erase("\\noblackbox"); } if (blackbox_module) { - if (ast->attributes.count(ID::whitebox)) { - delete ast->attributes.at(ID::whitebox); - ast->attributes.erase(ID::whitebox); + if (ast->attributes.count("\\whitebox")) { + delete ast->attributes.at("\\whitebox"); + ast->attributes.erase("\\whitebox"); } - if (ast->attributes.count(ID::lib_whitebox)) { - delete ast->attributes.at(ID::lib_whitebox); - ast->attributes.erase(ID::lib_whitebox); + if (ast->attributes.count("\\lib_whitebox")) { + delete ast->attributes.at("\\lib_whitebox"); + ast->attributes.erase("\\lib_whitebox"); } std::vector new_children; @@ -1084,6 +1061,8 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast if (child->type == AST_WIRE && (child->is_input || child->is_output)) { new_children.push_back(child); } else if (child->type == AST_PARAMETER) { + child->delete_children(); + child->children.push_back(AstNode::mkconst_int(0, false, 0)); new_children.push_back(child); } else if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE && (child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) { @@ -1095,8 +1074,8 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast ast->children.swap(new_children); - if (ast->attributes.count(ID::blackbox) == 0) { - ast->attributes[ID::blackbox] = AstNode::mkconst_int(1, false); + if (ast->attributes.count("\\blackbox") == 0) { + ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); } } @@ -1104,7 +1083,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); current_module->attributes[attr.first] = attr.second->asAttrConst(); } for (size_t i = 0; i < ast->children.size(); i++) { @@ -1127,7 +1106,6 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast } ignoreThisSignalsInInitial = RTLIL::SigSpec(); - current_scope.clear(); } else { for (auto &attr : ast->attributes) { @@ -1138,7 +1116,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast } if (ast->type == AST_INTERFACE) - current_module->set_bool_attribute(ID::is_interface); + current_module->set_bool_attribute("\\is_interface"); current_module->ast = ast_before_simplify; current_module->nolatches = flag_nolatches; current_module->nomeminit = flag_nomeminit; @@ -1167,7 +1145,6 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire) { current_ast = ast; - current_ast_mod = nullptr; flag_dump_ast1 = dump_ast1; flag_dump_ast2 = dump_ast2; flag_no_dump_ptr = no_dump_ptr; @@ -1194,19 +1171,10 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump for (auto n : design->verilog_globals) (*it)->children.push_back(n->clone()); - // append nodes from previous packages using package-qualified names - for (auto &n : design->verilog_packages) { - for (auto &o : n->children) { + for (auto n : design->verilog_packages){ + for (auto o : n->children) { AstNode *cloned_node = o->clone(); - // log("cloned node %s\n", type2str(cloned_node->type).c_str()); - if (cloned_node->type == AST_ENUM) { - for (auto &e : cloned_node->children) { - log_assert(e->type == AST_ENUM_ITEM); - e->str = n->str + std::string("::") + e->str.substr(1); - } - } else { - cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1); - } + cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1); (*it)->children.push_back(cloned_node); } } @@ -1220,34 +1188,25 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump if (design->has((*it)->str)) { RTLIL::Module *existing_mod = design->module((*it)->str); if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) { - log_file_error((*it)->filename, (*it)->location.first_line, "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) { - log("Ignoring re-definition of module `%s' at %s:%d.%d-%d.%d.\n", - (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->location.first_line, (*it)->location.first_column, (*it)->location.last_line, (*it)->location.last_column); + log("Ignoring re-definition of module `%s' at %s:%d.\n", + (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); continue; } else { - log("Replacing existing%s module `%s' at %s:%d.%d-%d.%d.\n", - existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", - (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->location.first_line, (*it)->location.first_column, (*it)->location.last_line, (*it)->location.last_column); + log("Replacing existing%s module `%s' at %s:%d.\n", + existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "", + (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); design->remove(existing_mod); } } design->add(process_module(*it, defer)); - current_ast_mod = nullptr; } - else if ((*it)->type == AST_PACKAGE) { - // process enum/other declarations - (*it)->simplify(true, false, false, 1, -1, false, false); + else if ((*it)->type == AST_PACKAGE) design->verilog_packages.push_back((*it)->clone()); - current_scope.clear(); - } - else { - // must be global definition - (*it)->simplify(false, false, false, 1, -1, false, false); //process enum/other declarations + else design->verilog_globals.push_back((*it)->clone()); - current_scope.clear(); - } } } @@ -1302,9 +1261,9 @@ AstNode * AST::find_modport(AstNode *intf, std::string name) // Iterate over all wires in an interface and add them as wires in the AST module: void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport) { - for (auto w : intfmodule->wires()){ - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true))); - std::string origname = log_id(w->name); + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string origname = log_id(wire_it.first); std::string newname = intfname + "." + origname; wire->str = newname; if (modport != NULL) { @@ -1338,7 +1297,7 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule // When an interface instance is found in a module, the whole RTLIL for the module will be rederived again // from AST. The interface members are copied into the AST module with the prefix of the interface. -void AstModule::reprocess_module(RTLIL::Design *design, const dict &local_interfaces) +void AstModule::reprocess_module(RTLIL::Design *design, dict local_interfaces) { loadconfig(); @@ -1347,9 +1306,9 @@ void AstModule::reprocess_module(RTLIL::Design *design, const dictwires()){ - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true))); - std::string newname = log_id(w->name); + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string newname = log_id(wire_it.first); newname = intfname + "." + newname; wire->str = newname; new_ast->children.push_back(wire); @@ -1373,7 +1332,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, const dict res = split_modport_from_type(ch->str); std::string interface_type = res.first; std::string interface_modport = res.second; // Is "", if no modport - if (design->module(interface_type) != nullptr) { + if (design->modules_.count(interface_type) > 0) { // Add a cell to the module corresponding to the interface port such that // it can further propagated down if needed: AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE); @@ -1383,7 +1342,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, const dictchildren.push_back(cell_for_intf); // Get all members of this non-overridden dummy interface instance: - RTLIL::Module *intfmodule = design->module(interface_type); // All interfaces should at this point in time (assuming + RTLIL::Module *intfmodule = design->modules_[interface_type]; // All interfaces should at this point in time (assuming // reprocess_module is called from the hierarchy pass) be // present in design->modules_ AstModule *ast_module_of_interface = (AstModule*)intfmodule; @@ -1403,12 +1362,12 @@ void AstModule::reprocess_module(RTLIL::Design *design, const dictname.str(); std::string changed_name = original_name + "_before_replacing_local_interfaces"; design->rename(this, changed_name); - this->set_bool_attribute(ID::to_delete); + this->set_bool_attribute("\\to_delete"); // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the // new module. - if (this->get_bool_attribute(ID::initial_top)) { - this->attributes.erase(ID::initial_top); + if (this->get_bool_attribute("\\initial_top")) { + this->attributes.erase("\\initial_top"); is_top = true; } @@ -1418,15 +1377,15 @@ void AstModule::reprocess_module(RTLIL::Design *design, const dictadd(newmod); RTLIL::Module* mod = design->module(original_name); if (is_top) - mod->set_bool_attribute(ID::top); + mod->set_bool_attribute("\\top"); // Set the attribute "interfaces_replaced_in_module" so that it does not happen again. - mod->set_bool_attribute(ID::interfaces_replaced_in_module); + mod->set_bool_attribute("\\interfaces_replaced_in_module"); } // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces // This method is used to explode the interface when the interface is a port of the module (not instantiated inside) -RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict ¶meters, const dict &interfaces, const dict &modports, bool /*mayfail*/) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool /*mayfail*/) { AstNode *new_ast = NULL; std::string modname = derive_common(design, parameters, &new_ast); @@ -1478,20 +1437,13 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dictwire(intf.first) != nullptr) { - // Normally, removing wires would be batched together as it's an - // expensive operation, however, in this case doing so would mean - // that a cell with the same name cannot be created (below)... - // Since we won't expect many interfaces to exist in a module, - // we can let this slide... - pool to_remove; - to_remove.insert(mod->wire(intf.first)); - mod->remove(to_remove); + if(mod->wires_.count(intf.first)) { + mod->wires_.erase(intf.first); mod->fixup_ports(); - // We copy the cell of the interface to the sub-module such that it - // can further be found if it is propagated down to sub-sub-modules etc. - RTLIL::Cell *new_subcell = mod->addCell(intf.first, intf.second->name); - new_subcell->set_bool_attribute(ID::is_interface); + // We copy the cell of the interface to the sub-module such that it can further be found if it is propagated + // down to sub-sub-modules etc. + RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name); + new_subcell->set_bool_attribute("\\is_interface"); } else { log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname.c_str()); @@ -1500,7 +1452,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict 0) { - mod->set_bool_attribute(ID::interfaces_replaced_in_module); + mod->set_bool_attribute("\\interfaces_replaced_in_module"); } } else { @@ -1512,18 +1464,16 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict ¶meters, bool /*mayfail*/) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, bool /*mayfail*/) { - bool quiet = lib || attributes.count(ID::blackbox) || attributes.count(ID::whitebox); - AstNode *new_ast = NULL; - std::string modname = derive_common(design, parameters, &new_ast, quiet); + std::string modname = derive_common(design, parameters, &new_ast); if (!design->has(modname)) { new_ast->str = modname; - design->add(process_module(new_ast, false, NULL, quiet)); + design->add(process_module(new_ast, false)); design->module(modname)->check(); - } else if (!quiet) { + } else { log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); } @@ -1532,7 +1482,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict ¶meters, AstNode **new_ast_out, bool quiet) +std::string AstModule::derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out) { std::string stripped_name = name.str(); @@ -1546,18 +1496,16 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dicttype != AST_PARAMETER) continue; para_counter++; - auto it = parameters.find(child->str); - if (it != parameters.end()) { - if (!quiet) - log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second)); - para_info += stringf("%s=%s", child->str.c_str(), log_signal(it->second)); + std::string para_id = child->str; + if (parameters.count(para_id) > 0) { + log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str]))); + para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); continue; } - it = parameters.find(stringf("$%d", para_counter)); - if (it != parameters.end()) { - if (!quiet) - log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second)); - para_info += stringf("%s=%s", child->str.c_str(), log_signal(it->second)); + para_id = stringf("$%d", para_counter); + if (parameters.count(para_id) > 0) { + log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); + para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); continue; } } @@ -1573,59 +1521,47 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dicthas(modname)) return modname; - if (!quiet) - 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()); loadconfig(); - pool rewritten; - rewritten.reserve(GetSize(parameters)); - AstNode *new_ast = ast->clone(); - if (!new_ast->attributes.count(ID::hdlname)) - new_ast->attributes[ID::hdlname] = AstNode::mkconst_str(stripped_name); - para_counter = 0; for (auto child : new_ast->children) { if (child->type != AST_PARAMETER) continue; para_counter++; - auto it = parameters.find(child->str); - if (it != parameters.end()) { - if (!quiet) - log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second)); + std::string para_id = child->str; + if (parameters.count(para_id) > 0) { + log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str]))); goto rewrite_parameter; } - it = parameters.find(stringf("$%d", para_counter)); - if (it != parameters.end()) { - if (!quiet) - log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second)); + para_id = stringf("$%d", para_counter); + if (parameters.count(para_id) > 0) { + log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); goto rewrite_parameter; } continue; rewrite_parameter: delete child->children.at(0); - if ((it->second.flags & RTLIL::CONST_FLAG_REAL) != 0) { + if ((parameters[para_id].flags & RTLIL::CONST_FLAG_REAL) != 0) { child->children[0] = new AstNode(AST_REALVALUE); - child->children[0]->realvalue = std::stod(it->second.decode_string()); - } else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0) - child->children[0] = AstNode::mkconst_str(it->second.decode_string()); + child->children[0]->realvalue = std::stod(parameters[para_id].decode_string()); + } else if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0) + child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string()); else - child->children[0] = AstNode::mkconst_bits(it->second.bits, (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0); - rewritten.insert(it->first); + child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0); + parameters.erase(para_id); } - if (GetSize(rewritten) < GetSize(parameters)) - for (const auto ¶m : parameters) { - if (rewritten.count(param.first)) - continue; - AstNode *defparam = new AstNode(AST_DEFPARAM, new AstNode(AST_IDENTIFIER)); - defparam->children[0]->str = param.first.str(); - if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0) - defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string())); - else - defparam->children.push_back(AstNode::mkconst_bits(param.second.bits, (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0)); - new_ast->children.push_back(defparam); - } + for (auto param : parameters) { + AstNode *defparam = new AstNode(AST_DEFPARAM, new AstNode(AST_IDENTIFIER)); + defparam->children[0]->str = param.first.str(); + if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0) + defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string())); + else + defparam->children.push_back(AstNode::mkconst_bits(param.second.bits, (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0)); + new_ast->children.push_back(defparam); + } (*new_ast_out) = new_ast; return modname; @@ -1671,6 +1607,25 @@ void AstModule::loadconfig() const flag_icells = icells; flag_pwires = pwires; flag_autowire = autowire; + use_internal_line_num(); +} + +// internal dummy line number callbacks +namespace { + int internal_line_num; + void internal_set_line_num(int n) { + internal_line_num = n; + } + int internal_get_line_num() { + return internal_line_num; + } +} + +// use internal dummy line number callbacks +void AST::use_internal_line_num() +{ + set_line_num = &internal_set_line_num; + get_line_num = &internal_get_line_num; } YOSYS_NAMESPACE_END diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 46864a4e1b6..918d178c7bf 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -68,14 +68,11 @@ namespace AST AST_LIVE, AST_FAIR, AST_COVER, - AST_ENUM, - AST_ENUM_ITEM, AST_FCALL, AST_TO_BITS, AST_TO_SIGNED, AST_TO_UNSIGNED, - AST_SELFSZ, AST_CONCAT, AST_REPLICATE, AST_BIT_NOT, @@ -92,8 +89,6 @@ namespace AST AST_SHIFT_RIGHT, AST_SHIFT_SLEFT, AST_SHIFT_SRIGHT, - AST_SHIFTX, - AST_SHIFT, AST_LT, AST_LE, AST_EQ, @@ -143,7 +138,7 @@ namespace AST AST_GENCASE, AST_GENBLOCK, AST_TECALL, - + AST_POSEDGE, AST_NEGEDGE, AST_EDGE, @@ -156,17 +151,7 @@ namespace AST AST_PACKAGE, AST_WIRETYPE, - AST_TYPEDEF, - AST_STRUCT, - AST_UNION, - AST_STRUCT_ITEM - }; - - struct AstSrcLocType { - unsigned int first_line, last_line; - unsigned int first_column, last_column; - AstSrcLocType() : first_line(0), last_line(0), first_column(0), last_column(0) {} - AstSrcLocType(int _first_line, int _first_column, int _last_line, int _last_column) : first_line(_first_line), last_line(_last_line), first_column(_first_column), last_column(_last_column) {} + AST_TYPEDEF }; // convert an node type to a string (e.g. for debug output) @@ -196,8 +181,6 @@ namespace AST int port_id, range_left, range_right; uint32_t integer; double realvalue; - // set for IDs typed to an enumeration, not used - bool is_enum; // if this is a multirange memory then this vector contains offset and length of each dimension std::vector multirange_dimensions; @@ -208,14 +191,11 @@ namespace AST // this is used by simplify to detect if basic analysis has been performed already on the node bool basic_prep; - // this is used for ID references in RHS expressions that should use the "new" value for non-blocking assignments - bool lookahead; - // this is the original sourcecode location that resulted in this AST node // it is automatically set by the constructor using AST::current_filename and // the AST::get_line_num() callback function. std::string filename; - AstSrcLocType location; + int linenum; // creating and deleting nodes AstNode(AstNodeType type = AST_NONE, AstNode *child1 = NULL, AstNode *child2 = NULL, AstNode *child3 = NULL); @@ -257,7 +237,6 @@ namespace AST bool mem2reg_check(pool &mem2reg_set); void mem2reg_remove(pool &mem2reg_set, vector &delnodes); void meminfo(int &mem_width, int &mem_size, int &addr_bits); - bool detect_latch(const std::string &var); // additional functionality for evaluating constant functions struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; }; @@ -265,7 +244,6 @@ namespace AST void replace_variables(std::map &variables, AstNode *fcall); AstNode *eval_const_function(AstNode *fcall); bool is_simple_const_expr(); - std::string process_format_str(const std::string &sformat, int next_arg, int stage, int width_hint, bool sign_hint); // create a human-readable text representation of the AST (for debugging) void dumpAst(FILE *f, std::string indent) const; @@ -307,10 +285,6 @@ namespace AST int isConst() const; // return '1' for AST_CONSTANT and '2' for AST_REALVALUE double asReal(bool is_signed); RTLIL::Const realAsConst(int width); - - // helpers for enum - void allocateDefaultEnumValues(); - void annotateTypedEnums(AstNode *template_node); }; // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code @@ -322,12 +296,12 @@ namespace AST struct AstModule : RTLIL::Module { AstNode *ast; bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire; - ~AstModule() override; - RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, bool mayfail) override; - RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, const dict &interfaces, const dict &modports, bool mayfail) override; - std::string derive_common(RTLIL::Design *design, const dict ¶meters, AstNode **new_ast_out, bool quiet = false); - void reprocess_module(RTLIL::Design *design, const dict &local_interfaces) override; - RTLIL::Module *clone() const override; + ~AstModule() YS_OVERRIDE; + RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail) YS_OVERRIDE; + RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) YS_OVERRIDE; + std::string derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out); + void reprocess_module(RTLIL::Design *design, dict local_interfaces) YS_OVERRIDE; + RTLIL::Module *clone() const YS_OVERRIDE; void loadconfig() const; }; @@ -363,7 +337,6 @@ namespace AST_INTERNAL extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child; extern AST::AstModule *current_module; extern bool current_always_clocked; - struct LookaheadRewriter; struct ProcessGenerator; } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 9546558aae3..94f5c0a044d 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -41,28 +41,30 @@ using namespace AST; using namespace AST_INTERNAL; // helper function for creating RTLIL code for unary operations -static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true) +static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true) { - IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++); - RTLIL::Cell *cell = current_module->addCell(name, type); - cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + std::stringstream sstr; + sstr << type << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++); + + RTLIL::Cell *cell = current_module->addCell(sstr.str(), type); + cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); if (gen_attributes) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } - cell->parameters[ID::A_SIGNED] = RTLIL::Const(that->children[0]->is_signed); - cell->parameters[ID::A_WIDTH] = RTLIL::Const(arg.size()); - cell->setPort(ID::A, arg); + cell->parameters["\\A_SIGNED"] = RTLIL::Const(that->children[0]->is_signed); + cell->parameters["\\A_WIDTH"] = RTLIL::Const(arg.size()); + cell->setPort("\\A", arg); - cell->parameters[ID::Y_WIDTH] = result_width; - cell->setPort(ID::Y, wire); + cell->parameters["\\Y_WIDTH"] = result_width; + cell->setPort("\\Y", wire); return wire; } @@ -74,56 +76,60 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s return; } - IdString name = stringf("$extend$%s:%d$%d", that->filename.c_str(), that->location.first_line, autoidx++); - RTLIL::Cell *cell = current_module->addCell(name, ID($pos)); - cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + std::stringstream sstr; + sstr << "$extend" << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++); + + RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$pos"); + cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", width); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); if (that != NULL) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } - cell->parameters[ID::A_SIGNED] = RTLIL::Const(is_signed); - cell->parameters[ID::A_WIDTH] = RTLIL::Const(sig.size()); - cell->setPort(ID::A, sig); + cell->parameters["\\A_SIGNED"] = RTLIL::Const(is_signed); + cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig.size()); + cell->setPort("\\A", sig); - cell->parameters[ID::Y_WIDTH] = width; - cell->setPort(ID::Y, wire); + cell->parameters["\\Y_WIDTH"] = width; + cell->setPort("\\Y", wire); sig = wire; } // helper function for creating RTLIL code for binary operations -static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right) +static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right) { - IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++); - RTLIL::Cell *cell = current_module->addCell(name, type); - cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + std::stringstream sstr; + sstr << type << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++); + + RTLIL::Cell *cell = current_module->addCell(sstr.str(), type); + cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } - cell->parameters[ID::A_SIGNED] = RTLIL::Const(that->children[0]->is_signed); - cell->parameters[ID::B_SIGNED] = RTLIL::Const(that->children[1]->is_signed); + cell->parameters["\\A_SIGNED"] = RTLIL::Const(that->children[0]->is_signed); + cell->parameters["\\B_SIGNED"] = RTLIL::Const(that->children[1]->is_signed); - cell->parameters[ID::A_WIDTH] = RTLIL::Const(left.size()); - cell->parameters[ID::B_WIDTH] = RTLIL::Const(right.size()); + cell->parameters["\\A_WIDTH"] = RTLIL::Const(left.size()); + cell->parameters["\\B_WIDTH"] = RTLIL::Const(right.size()); - cell->setPort(ID::A, left); - cell->setPort(ID::B, right); + cell->setPort("\\A", left); + cell->setPort("\\B", right); - cell->parameters[ID::Y_WIDTH] = result_width; - cell->setPort(ID::Y, wire); + cell->parameters["\\Y_WIDTH"] = result_width; + cell->setPort("\\Y", wire); return wire; } @@ -133,150 +139,30 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const log_assert(cond.size() == 1); std::stringstream sstr; - sstr << "$ternary$" << that->filename << ":" << that->location.first_line << "$" << (autoidx++); + sstr << "$ternary$" << that->filename << ":" << that->linenum << "$" << (autoidx++); - RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($mux)); - cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$mux"); + cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", left.size()); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column); + wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } - cell->parameters[ID::WIDTH] = RTLIL::Const(left.size()); + cell->parameters["\\WIDTH"] = RTLIL::Const(left.size()); - cell->setPort(ID::A, right); - cell->setPort(ID::B, left); - cell->setPort(ID::S, cond); - cell->setPort(ID::Y, wire); + cell->setPort("\\A", right); + cell->setPort("\\B", left); + cell->setPort("\\S", cond); + cell->setPort("\\Y", wire); return wire; } -// helper class for rewriting simple lookahead references in AST always blocks -struct AST_INTERNAL::LookaheadRewriter -{ - dict> lookaheadids; - - void collect_lookaheadids(AstNode *node) - { - if (node->lookahead) { - log_assert(node->type == AST_IDENTIFIER); - if (!lookaheadids.count(node->str)) { - AstNode *wire = new AstNode(AST_WIRE); - for (auto c : node->id2ast->children) - wire->children.push_back(c->clone()); - wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++); - wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false); - wire->is_logic = true; - while (wire->simplify(true, false, false, 1, -1, false, false)) { } - current_ast_mod->children.push_back(wire); - lookaheadids[node->str] = make_pair(node->id2ast, wire); - wire->genRTLIL(); - } - } - - for (auto child : node->children) - collect_lookaheadids(child); - } - - bool has_lookaheadids(AstNode *node) - { - if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) != 0) - return true; - - for (auto child : node->children) - if (has_lookaheadids(child)) - return true; - - return false; - } - - bool has_nonlookaheadids(AstNode *node) - { - if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) == 0) - return true; - - for (auto child : node->children) - if (has_nonlookaheadids(child)) - return true; - - return false; - } - - void rewrite_lookaheadids(AstNode *node, bool lhs = false) - { - if (node->type == AST_ASSIGN_LE) - { - if (has_lookaheadids(node->children[0])) - { - if (has_nonlookaheadids(node->children[0])) - log_error("incompatible mix of lookahead and non-lookahead IDs in LHS expression.\n"); - - rewrite_lookaheadids(node->children[0], true); - node->type = AST_ASSIGN_EQ; - } - - rewrite_lookaheadids(node->children[1], lhs); - return; - } - - if (node->type == AST_IDENTIFIER && (node->lookahead || lhs)) { - AstNode *newwire = lookaheadids.at(node->str).second; - node->str = newwire->str; - node->id2ast = newwire; - lhs = false; - } - - for (auto child : node->children) - rewrite_lookaheadids(child, lhs); - } - - LookaheadRewriter(AstNode *top) - { - // top->dumpAst(NULL, "REWRITE-BEFORE> "); - // top->dumpVlog(NULL, "REWRITE-BEFORE> "); - - AstNode *block = nullptr; - - for (auto c : top->children) - if (c->type == AST_BLOCK) { - log_assert(block == nullptr); - block = c; - } - log_assert(block != nullptr); - - collect_lookaheadids(block); - rewrite_lookaheadids(block); - - for (auto it : lookaheadids) - { - AstNode *ref_orig = new AstNode(AST_IDENTIFIER); - ref_orig->str = it.second.first->str; - ref_orig->id2ast = it.second.first; - ref_orig->was_checked = true; - - AstNode *ref_temp = new AstNode(AST_IDENTIFIER); - ref_temp->str = it.second.second->str; - ref_temp->id2ast = it.second.second; - ref_temp->was_checked = true; - - AstNode *init_assign = new AstNode(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone()); - AstNode *final_assign = new AstNode(AST_ASSIGN_LE, ref_orig, ref_temp); - - block->children.insert(block->children.begin(), init_assign); - block->children.push_back(final_assign); - } - - // top->dumpAst(NULL, "REWRITE-AFTER> "); - // top->dumpVlog(NULL, "REWRITE-AFTER> "); - } -}; - // helper class for converting AST always nodes to RTLIL processes struct AST_INTERNAL::ProcessGenerator { @@ -311,16 +197,13 @@ struct AST_INTERNAL::ProcessGenerator ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg) { - // rewrite lookahead references - LookaheadRewriter la_rewriter(always); - // generate process and simple root case proc = new RTLIL::Process; - proc->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column); - proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->location.first_line, autoidx++); + proc->attributes["\\src"] = stringf("%s:%d", always->filename.c_str(), always->linenum); + proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->linenum, autoidx++); for (auto &attr : always->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(always->filename, always->location.first_line, "Attribute `%s' with non-constant value!\n", + log_file_error(always->filename, always->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); proc->attributes[attr.first] = attr.second->asAttrConst(); } @@ -338,7 +221,7 @@ struct AST_INTERNAL::ProcessGenerator for (auto child : always->children) { if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && - child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) { + child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk")) { found_global_syncs = true; } if (child->type == AST_EDGE) { @@ -351,8 +234,8 @@ struct AST_INTERNAL::ProcessGenerator if (found_anyedge_syncs) { if (found_global_syncs) - log_file_error(always->filename, always->location.first_line, "Found non-synthesizable event list!\n"); - log("Note: Assuming pure combinatorial block at %s:%d.%d-%d.%d in\n", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column); + log_file_error(always->filename, always->linenum, "Found non-synthesizable event list!\n"); + log("Note: Assuming pure combinatorial block at %s:%d in\n", always->filename.c_str(), always->linenum); log("compliance with IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002. Recommending\n"); log("use of @* instead of @(...) for better match of synthesis and simulation.\n"); } @@ -362,16 +245,16 @@ struct AST_INTERNAL::ProcessGenerator for (auto child : always->children) if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) { if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast && - child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) + child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk")) continue; found_clocked_sync = true; if (found_global_syncs || found_anyedge_syncs) - log_file_error(always->filename, always->location.first_line, "Found non-synthesizable event list!\n"); + log_file_error(always->filename, always->linenum, "Found non-synthesizable event list!\n"); RTLIL::SyncRule *syncrule = new RTLIL::SyncRule; syncrule->type = child->type == AST_POSEDGE ? RTLIL::STp : RTLIL::STn; syncrule->signal = child->children[0]->genRTLIL(); if (GetSize(syncrule->signal) != 1) - log_file_error(always->filename, always->location.first_line, "Found posedge/negedge event on a signal that is not 1 bit wide!\n"); + log_file_error(always->filename, always->linenum, "Found posedge/negedge event on a signal that is not 1 bit wide!\n"); addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true); proc->syncs.push_back(syncrule); } @@ -384,7 +267,7 @@ struct AST_INTERNAL::ProcessGenerator } // create initial assignments for the temporary signals - if ((flag_nolatches || always->get_bool_attribute(ID::nolatches) || current_module->get_bool_attribute(ID::nolatches)) && !found_clocked_sync) { + if ((flag_nolatches || always->get_bool_attribute("\\nolatches") || current_module->get_bool_attribute("\\nolatches")) && !found_clocked_sync) { subst_rvalue_map = subst_lvalue_from.to_sigbit_dict(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from))); } else { addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from); @@ -452,7 +335,7 @@ struct AST_INTERNAL::ProcessGenerator } while (current_module->wires_.count(wire_name) > 0); RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column); + wire->attributes["\\src"] = stringf("%s:%d", always->filename.c_str(), always->linenum); chunk.wire = wire; chunk.offset = 0; @@ -461,7 +344,7 @@ struct AST_INTERNAL::ProcessGenerator return chunks; } - // recursively traverse the AST and collect all assigned signals + // recursively traverse the AST an collect all assigned signals void collect_lvalues(RTLIL::SigSpec ®, AstNode *ast, bool type_eq, bool type_le, bool run_sort_and_unify = true) { switch (ast->type) @@ -537,7 +420,7 @@ struct AST_INTERNAL::ProcessGenerator for (auto &lvalue_c : lvalue.chunks()) { RTLIL::SigSpec lhs = lvalue_c; RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue_c.width); - if (inSyncRule && lvalue_c.wire && lvalue_c.wire->get_bool_attribute(ID::nosync)) + if (inSyncRule && lvalue_c.wire && lvalue_c.wire->get_bool_attribute("\\nosync")) rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.size()); remove_unwanted_lvalue_bits(lhs, rhs); actions.push_back(RTLIL::SigSig(lhs, rhs)); @@ -587,13 +470,13 @@ struct AST_INTERNAL::ProcessGenerator case AST_CASE: { RTLIL::SwitchRule *sw = new RTLIL::SwitchRule; - sw->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line, ast->location.first_column, ast->location.last_line, ast->location.last_column); + sw->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum); sw->signal = ast->children[0]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap()); current_case->switches.push_back(sw); for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); sw->attributes[attr.first] = attr.second->asAttrConst(); } @@ -621,7 +504,7 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::CaseRule *backup_case = current_case; current_case = new RTLIL::CaseRule; - current_case->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", child->filename.c_str(), child->location.first_line, child->location.first_column, child->location.last_line, child->location.last_column); + current_case->attributes["\\src"] = stringf("%s:%d", child->filename.c_str(), child->linenum); last_generated_case = current_case; addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue); for (auto node : child->children) { @@ -642,7 +525,7 @@ struct AST_INTERNAL::ProcessGenerator subst_rvalue_map.restore(); } - if (last_generated_case != NULL && ast->get_bool_attribute(ID::full_case) && default_case == NULL) { + if (last_generated_case != NULL && ast->get_bool_attribute("\\full_case") && default_case == NULL) { #if 0 // this is a valid transformation, but as optimization it is premature. // better: add a default case that assigns 'x' to everything, and let later @@ -671,16 +554,16 @@ struct AST_INTERNAL::ProcessGenerator break; case AST_WIRE: - log_file_error(ast->filename, ast->location.first_line, "Found reg declaration in block without label!\n"); + log_file_error(ast->filename, ast->linenum, "Found reg declaration in block without label!\n"); break; case AST_ASSIGN: - log_file_error(ast->filename, ast->location.first_line, "Found continous assignment in always/initial block!\n"); + log_file_error(ast->filename, ast->linenum, "Found continous assignment in always/initial block!\n"); break; case AST_PARAMETER: case AST_LOCALPARAM: - log_file_error(ast->filename, ast->location.first_line, "Found parameter declaration in block without label!\n"); + log_file_error(ast->filename, ast->linenum, "Found parameter declaration in block without label!\n"); break; case AST_NONE: @@ -712,9 +595,6 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun switch (type) { - case AST_NONE: - // unallocated enum, ignore - break; case AST_CONSTANT: width_hint = max(width_hint, int(bits.size())); if (!is_signed) @@ -731,8 +611,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (id_ast == NULL && current_scope.count(str)) id_ast = current_scope.at(str); if (!id_ast) - log_file_error(filename, location.first_line, "Failed to resolve identifier %s for width detection!\n", str.c_str()); - if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM || id_ast->type == AST_ENUM_ITEM) { + log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", str.c_str()); + if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM) { if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) { this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1; } else @@ -741,7 +621,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (id_ast->children[0]->type == AST_CONSTANT) this_width = id_ast->children[0]->bits.size(); else - log_file_error(filename, location.first_line, "Failed to detect width for parameter %s!\n", str.c_str()); + log_file_error(filename, linenum, "Failed to detect width for parameter %s!\n", str.c_str()); if (children.size() != 0) range = children[0]; } else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) { @@ -753,7 +633,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun // log("---\n"); // id_ast->dumpAst(NULL, "decl> "); // dumpAst(NULL, "ref> "); - log_file_error(filename, location.first_line, "Failed to detect width of signal access `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Failed to detect width of signal access `%s'!\n", str.c_str()); } } else { this_width = id_ast->range_left - id_ast->range_right + 1; @@ -764,12 +644,12 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun this_width = 32; } else if (id_ast->type == AST_MEMORY) { if (!id_ast->children[0]->range_valid) - log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str()); this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1; if (children.size() > 1) range = children[1]; } else - log_file_error(filename, location.first_line, "Failed to detect width for identifier %s!\n", str.c_str()); + log_file_error(filename, linenum, "Failed to detect width for identifier %s!\n", str.c_str()); if (range) { if (range->children.size() == 1) this_width = 1; @@ -779,7 +659,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; delete left_at_zero_ast; delete right_at_zero_ast; @@ -795,7 +675,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_TO_BITS: while (children[0]->simplify(true, false, false, 1, -1, false, false) == true) { } if (children[0]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Left operand of tobits expression is not constant!\n"); + log_file_error(filename, linenum, "Left operand of tobits expression is not constant!\n"); children[1]->detectSignWidthWorker(sub_width_hint, sign_hint); width_hint = max(width_hint, children[0]->bitsAsConst().as_int()); break; @@ -809,11 +689,6 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun sign_hint = false; break; - case AST_SELFSZ: - sub_width_hint = 0; - children.at(0)->detectSignWidthWorker(sub_width_hint, sign_hint); - break; - case AST_CONCAT: for (auto child : children) { sub_width_hint = 0; @@ -828,7 +703,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_REPLICATE: while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { } if (children[0]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Left operand of replicate expression is not constant!\n"); + log_file_error(filename, linenum, "Left operand of replicate expression is not constant!\n"); children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint); width_hint = max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint); sign_hint = false; @@ -861,8 +736,6 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_SHIFT_RIGHT: case AST_SHIFT_SLEFT: case AST_SHIFT_SRIGHT: - case AST_SHIFTX: - case AST_SHIFT: case AST_POW: children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real); break; @@ -904,7 +777,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (!id2ast->is_signed) sign_hint = false; if (!id2ast->children[0]->range_valid) - log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str()); this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1; width_hint = max(width_hint, this_width); break; @@ -914,7 +787,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (GetSize(children) == 1) { while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { } if (children[0]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "System function %s called with non-const argument!\n", + log_file_error(filename, linenum, "System function %s called with non-const argument!\n", RTLIL::unescape_id(str).c_str()); width_hint = max(width_hint, int(children[0]->asInt(true))); } @@ -930,13 +803,13 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun } break; } - YS_FALLTHROUGH + /* fall through */ // everything should have been handled above -> print error if not. default: for (auto f : log_files) current_ast_mod->dumpAst(f, "verilog-ast> "); - log_file_error(filename, location.first_line, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str()); + log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str()); } if (*found_real) @@ -966,9 +839,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // Clifford's Device (http://www.clifford.at/cfun/cliffdev/). In this // cases this variable is used to hold the type of the cell that should // be instantiated for this type of AST node. - IdString type_name; + std::string type_name; current_filename = filename; + set_line_num(linenum); switch (type) { @@ -987,31 +861,28 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENIF: case AST_GENCASE: case AST_PACKAGE: - case AST_ENUM: case AST_MODPORT: case AST_MODPORTMEMBER: case AST_TYPEDEF: - case AST_STRUCT: - case AST_UNION: break; case AST_INTERFACEPORT: { // If a port in a module with unknown type is found, mark it with the attribute 'is_interface' // This is used by the hierarchy pass to know when it can replace interface connection with the individual // signals. RTLIL::Wire *wire = current_module->addWire(str, 1); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); wire->start_offset = 0; wire->port_id = port_id; wire->port_input = true; wire->port_output = true; - wire->set_bool_attribute(ID::is_interface); + wire->set_bool_attribute("\\is_interface"); if (children.size() > 0) { for(size_t i=0; itype == AST_INTERFACEPORTTYPE) { std::pair res = AST::split_modport_from_type(children[i]->str); - wire->attributes[ID::interface_type] = res.first; + wire->attributes["\\interface_type"] = res.first; if (res.second != "") - wire->attributes[ID::interface_modport] = res.second; + wire->attributes["\\interface_modport"] = res.second; break; } } @@ -1024,27 +895,24 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // remember the parameter, needed for example in techmap case AST_PARAMETER: - current_module->avail_parameters(str); - if (GetSize(children) >= 1 && children[0]->type == AST_CONSTANT) { - current_module->parameter_default_values[str] = children[0]->asParaConst(); - } - YS_FALLTHROUGH + current_module->avail_parameters.insert(str); + /* fall through */ case AST_LOCALPARAM: if (flag_pwires) { if (GetSize(children) < 1 || children[0]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Parameter `%s' with non-constant value!\n", str.c_str()); + log_file_error(filename, linenum, "Parameter `%s' with non-constant value!\n", str.c_str()); RTLIL::Const val = children[0]->bitsAsConst(); RTLIL::Wire *wire = current_module->addWire(str, GetSize(val)); current_module->connect(wire, val); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); - wire->attributes[type == AST_PARAMETER ? ID::parameter : ID::localparam] = 1; + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + wire->attributes[type == AST_PARAMETER ? "\\parameter" : "\\localparam"] = 1; for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); wire->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -1053,47 +921,46 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Wire for an AST_WIRE node case AST_WIRE: { if (current_module->wires_.count(str) != 0) - log_file_error(filename, location.first_line, "Re-definition of signal `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", str.c_str()); if (!range_valid) - log_file_error(filename, location.first_line, "Signal `%s' with non-constant width!\n", str.c_str()); + log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str()); - if (!(range_left + 1 >= range_right)) - log_file_error(filename, location.first_line, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1); + if (!(range_left >= range_right || (range_left == -1 && range_right == 0))) + log_file_error(filename, linenum, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1); RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); wire->start_offset = range_right; wire->port_id = port_id; wire->port_input = is_input; wire->port_output = is_output; wire->upto = range_swapped; - wire->is_signed = is_signed; for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); wire->attributes[attr.first] = attr.second->asAttrConst(); } - if (is_wand) wire->set_bool_attribute(ID::wand); - if (is_wor) wire->set_bool_attribute(ID::wor); + if (is_wand) wire->set_bool_attribute("\\wand"); + if (is_wor) wire->set_bool_attribute("\\wor"); } break; // create an RTLIL::Memory for an AST_MEMORY node case AST_MEMORY: { if (current_module->memories.count(str) != 0) - log_file_error(filename, location.first_line, "Re-definition of memory `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", str.c_str()); log_assert(children.size() >= 2); log_assert(children[0]->type == AST_RANGE); log_assert(children[1]->type == AST_RANGE); if (!children[0]->range_valid || !children[1]->range_valid) - log_file_error(filename, location.first_line, "Memory `%s' with non-constant width or size!\n", str.c_str()); + log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", str.c_str()); RTLIL::Memory *memory = new RTLIL::Memory; - memory->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); memory->name = str; memory->width = children[0]->range_left - children[0]->range_right + 1; if (children[1]->range_right < children[1]->range_left) { @@ -1107,7 +974,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); memory->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -1130,7 +997,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } RTLIL::SigSpec sig = realAsConst(width_hint); - log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); + log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); return sig; } @@ -1146,26 +1013,24 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int add_undef_bits_msb = 0; int add_undef_bits_lsb = 0; - log_assert(id2ast != nullptr); - - if (id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) { + if (id2ast && id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) { RTLIL::Wire *wire = current_module->addWire(str); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); wire->name = str; if (flag_autowire) - log_file_warning(filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str()); + log_file_warning(filename, linenum, "Identifier `%s' is implicitly declared.\n", str.c_str()); else - log_file_error(filename, location.first_line, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str()); } - else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM || id2ast->type == AST_ENUM_ITEM) { + else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) { if (id2ast->children[0]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Parameter %s does not evaluate to constant value!\n", str.c_str()); + log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str()); chunk = RTLIL::Const(id2ast->children[0]->bits); goto use_const_chunk; } - else if ((id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) { + else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) { RTLIL::Wire *current_wire = current_module->wire(str); - if (current_wire->get_bool_attribute(ID::is_interface)) + if (current_wire->get_bool_attribute("\\is_interface")) is_interface = true; // Ignore } @@ -1174,23 +1039,26 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) is_interface = true; } else { - log_file_error(filename, location.first_line, "Identifier `%s' doesn't map to any signal!\n", str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str()); } if (id2ast->type == AST_MEMORY) - log_file_error(filename, location.first_line, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); // If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface' // This makes it possible for the hierarchy pass to see what are interface connections and then replace them // with the individual signals: if (is_interface) { - IdString dummy_wire_name = stringf("$dummywireforinterface%s", str.c_str()); - RTLIL::Wire *dummy_wire = current_module->wire(dummy_wire_name); - if (!dummy_wire) { + RTLIL::Wire *dummy_wire; + std::string dummy_wire_name = "$dummywireforinterface" + str; + if (current_module->wires_.count(dummy_wire_name)) + dummy_wire = current_module->wires_[dummy_wire_name]; + else { dummy_wire = current_module->addWire(dummy_wire_name); - dummy_wire->set_bool_attribute(ID::is_interface); + dummy_wire->set_bool_attribute("\\is_interface"); } - return dummy_wire; + RTLIL::SigSpec tmp = RTLIL::SigSpec(dummy_wire); + return tmp; } wire = current_module->wires_[str]; @@ -1201,7 +1069,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) use_const_chunk: if (children.size() != 0) { if (children[0]->type != AST_RANGE) - log_file_error(filename, location.first_line, "Single range expected.\n"); + log_file_error(filename, linenum, "Single range expected.\n"); int source_width = id2ast->range_left - id2ast->range_right + 1; int source_offset = id2ast->range_right; if (!children[0]->range_valid) { @@ -1210,28 +1078,23 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : children[0]->children[0]->clone()); fake_ast->children[0]->delete_children(); - - int fake_ast_width = 0; - bool fake_ast_sign = true; - fake_ast->children[1]->detectSignWidth(fake_ast_width, fake_ast_sign); - RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL(fake_ast_width, fake_ast_sign); - + RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL(); if (id2ast->range_right != 0) { - shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast_sign); + shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast->children[1]->is_signed); fake_ast->children[1]->is_signed = true; } if (id2ast->range_swapped) { - shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast_sign); + shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast->children[1]->is_signed); fake_ast->children[1]->is_signed = true; } if (GetSize(shift_val) >= 32) fake_ast->children[1]->is_signed = true; - RTLIL::SigSpec sig = binop2rtlil(fake_ast, ID($shiftx), width, fake_ast->children[0]->genRTLIL(), shift_val); + RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shiftx", width, fake_ast->children[0]->genRTLIL(), shift_val); delete left_at_zero_ast; delete right_at_zero_ast; delete fake_ast; @@ -1243,10 +1106,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width); if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) { if (chunk.width == 1) - log_file_warning(filename, location.first_line, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", + log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", str.c_str()); else - log_file_warning(filename, location.first_line, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", + log_file_warning(filename, linenum, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width); chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width); } else { @@ -1260,10 +1123,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset += add_undef_bits_lsb; } if (add_undef_bits_lsb) - log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", + log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); if (add_undef_bits_msb) - log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", + log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); } } @@ -1280,8 +1143,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // just pass thru the signal. the parent will evaluate the is_signed property and interpret the SigSpec accordingly case AST_TO_SIGNED: - case AST_TO_UNSIGNED: - case AST_SELFSZ: { + case AST_TO_UNSIGNED: { RTLIL::SigSpec sig = children[0]->genRTLIL(); if (sig.size() < width_hint) sig.extend_u0(width_hint, sign_hint); @@ -1304,7 +1166,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::SigSpec left = children[0]->genRTLIL(); RTLIL::SigSpec right = children[1]->genRTLIL(); if (!left.is_fully_const()) - log_file_error(filename, location.first_line, "Left operand of replicate expression is not constant!\n"); + log_file_error(filename, linenum, "Left operand of replicate expression is not constant!\n"); int count = left.as_int(); RTLIL::SigSpec sig; for (int i = 0; i < count; i++) @@ -1316,9 +1178,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } // generate cells for unary operations: $not, $pos, $neg - if (0) { case AST_BIT_NOT: type_name = ID($not); } - if (0) { case AST_POS: type_name = ID($pos); } - if (0) { case AST_NEG: type_name = ID($neg); } + if (0) { case AST_BIT_NOT: type_name = "$not"; } + if (0) { case AST_POS: type_name = "$pos"; } + if (0) { case AST_NEG: type_name = "$neg"; } { RTLIL::SigSpec arg = children[0]->genRTLIL(width_hint, sign_hint); is_signed = children[0]->is_signed; @@ -1331,10 +1193,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } // generate cells for binary operations: $and, $or, $xor, $xnor - if (0) { case AST_BIT_AND: type_name = ID($and); } - if (0) { case AST_BIT_OR: type_name = ID($or); } - if (0) { case AST_BIT_XOR: type_name = ID($xor); } - if (0) { case AST_BIT_XNOR: type_name = ID($xnor); } + if (0) { case AST_BIT_AND: type_name = "$and"; } + if (0) { case AST_BIT_OR: type_name = "$or"; } + if (0) { case AST_BIT_XOR: type_name = "$xor"; } + if (0) { case AST_BIT_XNOR: type_name = "$xnor"; } { if (width_hint < 0) detectSignWidth(width_hint, sign_hint); @@ -1348,10 +1210,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } // generate cells for unary operations: $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor - if (0) { case AST_REDUCE_AND: type_name = ID($reduce_and); } - if (0) { case AST_REDUCE_OR: type_name = ID($reduce_or); } - if (0) { case AST_REDUCE_XOR: type_name = ID($reduce_xor); } - if (0) { case AST_REDUCE_XNOR: type_name = ID($reduce_xnor); } + if (0) { case AST_REDUCE_AND: type_name = "$reduce_and"; } + if (0) { case AST_REDUCE_OR: type_name = "$reduce_or"; } + if (0) { case AST_REDUCE_XOR: type_name = "$reduce_xor"; } + if (0) { case AST_REDUCE_XNOR: type_name = "$reduce_xnor"; } { RTLIL::SigSpec arg = children[0]->genRTLIL(); RTLIL::SigSpec sig = uniop2rtlil(this, type_name, max(width_hint, 1), arg); @@ -1360,7 +1222,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // generate cells for unary operations: $reduce_bool // (this is actually just an $reduce_or, but for clarity a different cell type is used) - if (0) { case AST_REDUCE_BOOL: type_name = ID($reduce_bool); } + if (0) { case AST_REDUCE_BOOL: type_name = "$reduce_bool"; } { RTLIL::SigSpec arg = children[0]->genRTLIL(); RTLIL::SigSpec sig = arg.size() > 1 ? uniop2rtlil(this, type_name, max(width_hint, 1), arg) : arg; @@ -1368,12 +1230,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } // generate cells for binary operations: $shl, $shr, $sshl, $sshr - if (0) { case AST_SHIFT_LEFT: type_name = ID($shl); } - if (0) { case AST_SHIFT_RIGHT: type_name = ID($shr); } - if (0) { case AST_SHIFT_SLEFT: type_name = ID($sshl); } - if (0) { case AST_SHIFT_SRIGHT: type_name = ID($sshr); } - if (0) { case AST_SHIFTX: type_name = ID($shiftx); } - if (0) { case AST_SHIFT: type_name = ID($shift); } + if (0) { case AST_SHIFT_LEFT: type_name = "$shl"; } + if (0) { case AST_SHIFT_RIGHT: type_name = "$shr"; } + if (0) { case AST_SHIFT_SLEFT: type_name = "$sshl"; } + if (0) { case AST_SHIFT_SRIGHT: type_name = "$sshr"; } { if (width_hint < 0) detectSignWidth(width_hint, sign_hint); @@ -1397,19 +1257,19 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int width = width_hint > 0 ? width_hint : left.size(); is_signed = children[0]->is_signed; if (!flag_noopt && left.is_fully_const() && left.as_int() == 2 && !right_signed) - return binop2rtlil(this, ID($shl), width, RTLIL::SigSpec(1, left.size()), right); - return binop2rtlil(this, ID($pow), width, left, right); + return binop2rtlil(this, "$shl", width, RTLIL::SigSpec(1, left.size()), right); + return binop2rtlil(this, "$pow", width, left, right); } // generate cells for binary operations: $lt, $le, $eq, $ne, $ge, $gt - if (0) { case AST_LT: type_name = ID($lt); } - if (0) { case AST_LE: type_name = ID($le); } - if (0) { case AST_EQ: type_name = ID($eq); } - if (0) { case AST_NE: type_name = ID($ne); } - if (0) { case AST_EQX: type_name = ID($eqx); } - if (0) { case AST_NEX: type_name = ID($nex); } - if (0) { case AST_GE: type_name = ID($ge); } - if (0) { case AST_GT: type_name = ID($gt); } + if (0) { case AST_LT: type_name = "$lt"; } + if (0) { case AST_LE: type_name = "$le"; } + if (0) { case AST_EQ: type_name = "$eq"; } + if (0) { case AST_NE: type_name = "$ne"; } + if (0) { case AST_EQX: type_name = "$eqx"; } + if (0) { case AST_NEX: type_name = "$nex"; } + if (0) { case AST_GE: type_name = "$ge"; } + if (0) { case AST_GT: type_name = "$gt"; } { int width = max(width_hint, 1); width_hint = -1, sign_hint = true; @@ -1422,11 +1282,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } // generate cells for binary operations: $add, $sub, $mul, $div, $mod - if (0) { case AST_ADD: type_name = ID($add); } - if (0) { case AST_SUB: type_name = ID($sub); } - if (0) { case AST_MUL: type_name = ID($mul); } - if (0) { case AST_DIV: type_name = ID($div); } - if (0) { case AST_MOD: type_name = ID($mod); } + if (0) { case AST_ADD: type_name = "$add"; } + if (0) { case AST_SUB: type_name = "$sub"; } + if (0) { case AST_MUL: type_name = "$mul"; } + if (0) { case AST_DIV: type_name = "$div"; } + if (0) { case AST_MOD: type_name = "$mod"; } { if (width_hint < 0) detectSignWidth(width_hint, sign_hint); @@ -1452,8 +1312,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } // generate cells for binary operations: $logic_and, $logic_or - if (0) { case AST_LOGIC_AND: type_name = ID($logic_and); } - if (0) { case AST_LOGIC_OR: type_name = ID($logic_or); } + if (0) { case AST_LOGIC_AND: type_name = "$logic_and"; } + if (0) { case AST_LOGIC_OR: type_name = "$logic_or"; } { RTLIL::SigSpec left = children[0]->genRTLIL(); RTLIL::SigSpec right = children[1]->genRTLIL(); @@ -1464,7 +1324,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_LOGIC_NOT: { RTLIL::SigSpec arg = children[0]->genRTLIL(); - return uniop2rtlil(this, ID($logic_not), max(width_hint, 1), arg); + return uniop2rtlil(this, "$logic_not", max(width_hint, 1), arg); } // generate multiplexer for ternary operator (aka ?:-operator) @@ -1472,39 +1332,20 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) { if (width_hint < 0) detectSignWidth(width_hint, sign_hint); - is_signed = sign_hint; RTLIL::SigSpec cond = children[0]->genRTLIL(); - RTLIL::SigSpec sig; - - if (cond.is_fully_def()) - { - if (cond.as_bool()) { - sig = children[1]->genRTLIL(width_hint, sign_hint); - log_assert(is_signed == children[1]->is_signed); - } else { - sig = children[2]->genRTLIL(width_hint, sign_hint); - log_assert(is_signed == children[2]->is_signed); - } - - widthExtend(this, sig, sig.size(), is_signed); - } - else - { - RTLIL::SigSpec val1 = children[1]->genRTLIL(width_hint, sign_hint); - RTLIL::SigSpec val2 = children[2]->genRTLIL(width_hint, sign_hint); + RTLIL::SigSpec val1 = children[1]->genRTLIL(width_hint, sign_hint); + RTLIL::SigSpec val2 = children[2]->genRTLIL(width_hint, sign_hint); - if (cond.size() > 1) - cond = uniop2rtlil(this, ID($reduce_bool), 1, cond, false); + if (cond.size() > 1) + cond = uniop2rtlil(this, "$reduce_bool", 1, cond, false); - int width = max(val1.size(), val2.size()); - log_assert(is_signed == children[1]->is_signed); - log_assert(is_signed == children[2]->is_signed); - widthExtend(this, val1, width, is_signed); - widthExtend(this, val2, width, is_signed); + int width = max(val1.size(), val2.size()); + is_signed = children[1]->is_signed && children[2]->is_signed; + widthExtend(this, val1, width, is_signed); + widthExtend(this, val2, width, is_signed); - sig = mux2rtlil(this, cond, val1, val2); - } + RTLIL::SigSpec sig = mux2rtlil(this, cond, val1, val2); if (sig.size() < width_hint) sig.extend_u0(width_hint, sign_hint); @@ -1515,13 +1356,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_MEMRD: { std::stringstream sstr; - sstr << "$memrd$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++); + sstr << "$memrd$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++); - RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($memrd)); - cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$memrd"); + cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_DATA", current_module->memories[str]->width); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); int mem_width, mem_size, addr_bits; is_signed = id2ast->is_signed; @@ -1529,18 +1370,18 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::SigSpec addr_sig = children[0]->genRTLIL(); - cell->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::Sx, 1)); - cell->setPort(ID::EN, RTLIL::SigSpec(RTLIL::State::Sx, 1)); - cell->setPort(ID::ADDR, addr_sig); - cell->setPort(ID::DATA, RTLIL::SigSpec(wire)); + cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1)); + cell->setPort("\\EN", RTLIL::SigSpec(RTLIL::State::Sx, 1)); + cell->setPort("\\ADDR", addr_sig); + cell->setPort("\\DATA", RTLIL::SigSpec(wire)); - cell->parameters[ID::MEMID] = RTLIL::Const(str); - cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig)); - cell->parameters[ID::WIDTH] = RTLIL::Const(wire->width); + cell->parameters["\\MEMID"] = RTLIL::Const(str); + cell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr_sig)); + cell->parameters["\\WIDTH"] = RTLIL::Const(wire->width); - cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(0); - cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(0); - cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0); + cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0); + cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0); if (!sign_hint) is_signed = false; @@ -1553,10 +1394,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_MEMINIT: { std::stringstream sstr; - sstr << (type == AST_MEMWR ? "$memwr$" : "$meminit$") << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++); + sstr << (type == AST_MEMWR ? "$memwr$" : "$meminit$") << str << "$" << filename << ":" << linenum << "$" << (autoidx++); - RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_MEMWR ? ID($memwr) : ID($meminit)); - cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_MEMWR ? "$memwr" : "$meminit"); + cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); int mem_width, mem_size, addr_bits; id2ast->meminfo(mem_width, mem_size, addr_bits); @@ -1564,28 +1405,28 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int num_words = 1; if (type == AST_MEMINIT) { if (children[2]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Memory init with non-constant word count!\n"); + log_file_error(filename, linenum, "Memory init with non-constant word count!\n"); num_words = int(children[2]->asInt(false)); - cell->parameters[ID::WORDS] = RTLIL::Const(num_words); + cell->parameters["\\WORDS"] = RTLIL::Const(num_words); } SigSpec addr_sig = children[0]->genRTLIL(); - cell->setPort(ID::ADDR, addr_sig); - cell->setPort(ID::DATA, children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words)); + cell->setPort("\\ADDR", addr_sig); + cell->setPort("\\DATA", children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words)); - cell->parameters[ID::MEMID] = RTLIL::Const(str); - cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig)); - cell->parameters[ID::WIDTH] = RTLIL::Const(current_module->memories[str]->width); + cell->parameters["\\MEMID"] = RTLIL::Const(str); + cell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr_sig)); + cell->parameters["\\WIDTH"] = RTLIL::Const(current_module->memories[str]->width); if (type == AST_MEMWR) { - cell->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::Sx, 1)); - cell->setPort(ID::EN, children[2]->genRTLIL()); - cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(0); - cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(0); + cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1)); + cell->setPort("\\EN", children[2]->genRTLIL()); + cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0); } - cell->parameters[ID::PRIORITY] = RTLIL::Const(autoidx-1); + cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1); } break; @@ -1596,12 +1437,12 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_FAIR: case AST_COVER: { - IdString celltype; - if (type == AST_ASSERT) celltype = ID($assert); - if (type == AST_ASSUME) celltype = ID($assume); - if (type == AST_LIVE) celltype = ID($live); - if (type == AST_FAIR) celltype = ID($fair); - if (type == AST_COVER) celltype = ID($cover); + const char *celltype = nullptr; + if (type == AST_ASSERT) celltype = "$assert"; + if (type == AST_ASSUME) celltype = "$assume"; + if (type == AST_LIVE) celltype = "$live"; + if (type == AST_FAIR) celltype = "$fair"; + if (type == AST_COVER) celltype = "$cover"; log_assert(children.size() == 2); @@ -1614,22 +1455,25 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) en = current_module->ReduceBool(NEW_ID, en); IdString cellname; - if (str.empty()) - cellname = stringf("%s$%s:%d$%d", celltype.c_str(), filename.c_str(), location.first_line, autoidx++); - else + if (str.empty()) { + std::stringstream sstr; + sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++); + cellname = sstr.str(); + } else { cellname = str; + } RTLIL::Cell *cell = current_module->addCell(cellname, celltype); - cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } - cell->setPort(ID::A, check); - cell->setPort(ID::EN, en); + cell->setPort("\\A", check); + cell->setPort("\\EN", en); } break; @@ -1645,7 +1489,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) new_left.append(left[i]); new_right.append(right[i]); } - log_file_warning(filename, location.first_line, "Ignoring assignment to constant bits:\n" + log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n" " old assignment: %s = %s\n new assignment: %s = %s.\n", log_signal(left), log_signal(right), log_signal(new_left), log_signal(new_right)); @@ -1662,12 +1506,12 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int port_counter = 0, para_counter = 0; if (current_module->count_id(str) != 0) - log_file_error(filename, location.first_line, "Re-definition of cell `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Re-definition of cell `%s'!\n", str.c_str()); RTLIL::Cell *cell = current_module->addCell(str, ""); - cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); // Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass - cell->set_bool_attribute(ID::module_not_derived); + cell->set_bool_attribute("\\module_not_derived"); for (auto it = children.begin(); it != children.end(); it++) { AstNode *child = *it; @@ -1681,7 +1525,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int extra_const_flags = 0; IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str; if (child->children[0]->type == AST_REALVALUE) { - log_file_warning(filename, location.first_line, "Replacing floating point parameter %s.%s = %f with string.\n", + log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n", log_id(cell), log_id(paraname), child->children[0]->realvalue); extra_const_flags = RTLIL::CONST_FLAG_REAL; auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue)); @@ -1689,7 +1533,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) delete strnode; } if (child->children[0]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Parameter %s.%s with non-constant value!\n", + log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n", log_id(cell), log_id(paraname)); cell->parameters[paraname] = child->children[0]->asParaConst(); cell->parameters[paraname].flags |= extra_const_flags; @@ -1712,32 +1556,28 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value.\n", attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value.\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } - if (cell->type == ID($specify2)) { - int src_width = GetSize(cell->getPort(ID::SRC)); - int dst_width = GetSize(cell->getPort(ID::DST)); - bool full = cell->getParam(ID::FULL).as_bool(); + if (cell->type.in("$specify2", "$specify3")) { + int src_width = GetSize(cell->getPort("\\SRC")); + int dst_width = GetSize(cell->getPort("\\DST")); + bool full = cell->getParam("\\FULL").as_bool(); if (!full && src_width != dst_width) - log_file_error(filename, location.first_line, "Parallel specify SRC width does not match DST width.\n"); - cell->setParam(ID::SRC_WIDTH, Const(src_width)); - cell->setParam(ID::DST_WIDTH, Const(dst_width)); - } - else if (cell->type == ID($specify3)) { - int dat_width = GetSize(cell->getPort(ID::DAT)); - int dst_width = GetSize(cell->getPort(ID::DST)); - if (dat_width != dst_width) - log_file_error(filename, location.first_line, "Specify DAT width does not match DST width.\n"); - int src_width = GetSize(cell->getPort(ID::SRC)); - cell->setParam(ID::SRC_WIDTH, Const(src_width)); - cell->setParam(ID::DST_WIDTH, Const(dst_width)); + log_file_error(filename, linenum, "Parallel specify SRC width does not match DST width.\n"); + if (cell->type == "$specify3") { + int dat_width = GetSize(cell->getPort("\\DAT")); + if (dat_width != dst_width) + log_file_error(filename, linenum, "Specify DAT width does not match DST width.\n"); + } + cell->setParam("\\SRC_WIDTH", Const(src_width)); + cell->setParam("\\DST_WIDTH", Const(dst_width)); } - else if (cell->type == ID($specrule)) { - int src_width = GetSize(cell->getPort(ID::SRC)); - int dst_width = GetSize(cell->getPort(ID::DST)); - cell->setParam(ID::SRC_WIDTH, Const(src_width)); - cell->setParam(ID::DST_WIDTH, Const(dst_width)); + if (cell->type == "$specrule") { + int src_width = GetSize(cell->getPort("\\SRC")); + int dst_width = GetSize(cell->getPort("\\DST")); + cell->setParam("\\SRC_WIDTH", Const(src_width)); + cell->setParam("\\DST_WIDTH", Const(dst_width)); } } break; @@ -1760,30 +1600,30 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int sz = children.size(); if (str == "$info") { if (sz > 0) - log_file_info(filename, location.first_line, "%s.\n", children[0]->str.c_str()); + log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); else - log_file_info(filename, location.first_line, "\n"); + log_file_info(filename, linenum, "\n"); } else if (str == "$warning") { if (sz > 0) - log_file_warning(filename, location.first_line, "%s.\n", children[0]->str.c_str()); + log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); else - log_file_warning(filename, location.first_line, "\n"); + log_file_warning(filename, linenum, "\n"); } else if (str == "$error") { if (sz > 0) - log_file_error(filename, location.first_line, "%s.\n", children[0]->str.c_str()); + log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); else - log_file_error(filename, location.first_line, "\n"); + log_file_error(filename, linenum, "\n"); } else if (str == "$fatal") { // TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish() // if no parameter is given, default value is 1 // dollar_finish(sz ? children[0] : 1); // perhaps create & use log_file_fatal() if (sz > 0) - log_file_error(filename, location.first_line, "FATAL: %s.\n", children[0]->str.c_str()); + log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); else - log_file_error(filename, location.first_line, "FATAL.\n"); + log_file_error(filename, linenum, "FATAL.\n"); } else { - log_file_error(filename, location.first_line, "Unknown elabortoon system task '%s'.\n", str.c_str()); + log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); } } break; @@ -1794,46 +1634,45 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int width = width_hint; if (GetSize(children) > 1) - log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 0.\n", + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n", RTLIL::unescape_id(str).c_str(), GetSize(children)); if (GetSize(children) == 1) { if (children[0]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "System function %s called with non-const argument!\n", + log_file_error(filename, linenum, "System function %s called with non-const argument!\n", RTLIL::unescape_id(str).c_str()); width = children[0]->asInt(true); } if (width <= 0) - log_file_error(filename, location.first_line, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str()); + log_file_error(filename, linenum, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str()); Cell *cell = current_module->addCell(myid, str.substr(1)); - cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); - cell->parameters[ID::WIDTH] = width; + cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + cell->parameters["\\WIDTH"] = width; - if (attributes.count(ID::reg)) { - auto &attr = attributes.at(ID::reg); + if (attributes.count("\\reg")) { + auto &attr = attributes.at("\\reg"); if (attr->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Attribute `reg' with non-constant value!\n"); - cell->attributes[ID::reg] = attr->asAttrConst(); + log_file_error(filename, linenum, "Attribute `reg' with non-constant value!\n"); + cell->attributes["\\reg"] = attr->asAttrConst(); } Wire *wire = current_module->addWire(myid + "_wire", width); - wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); - cell->setPort(ID::Y, wire); + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + cell->setPort("\\Y", wire); is_signed = sign_hint; return SigSpec(wire); } - } - YS_FALLTHROUGH + } /* fall through */ // everything should have been handled above -> print error if not. default: for (auto f : log_files) current_ast_mod->dumpAst(f, "verilog-ast> "); type_name = type2str(type); - log_file_error(filename, location.first_line, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str()); + log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str()); } return RTLIL::SigSpec(); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 55e7da0aa88..44fd32cdc8e 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -41,448 +41,6 @@ YOSYS_NAMESPACE_BEGIN using namespace AST; using namespace AST_INTERNAL; -// Process a format string and arguments for $display, $write, $sprintf, etc - -std::string AstNode::process_format_str(const std::string &sformat, int next_arg, int stage, int width_hint, bool sign_hint) { - // Other arguments are placeholders. Process the string as we go through it - std::string sout; - for (size_t i = 0; i < sformat.length(); i++) - { - // format specifier - if (sformat[i] == '%') - { - // If there's no next character, that's a problem - if (i+1 >= sformat.length()) - log_file_error(filename, location.first_line, "System task `%s' called with `%%' at end of string.\n", str.c_str()); - - char cformat = sformat[++i]; - - // %% is special, does not need a matching argument - if (cformat == '%') - { - sout += '%'; - continue; - } - - bool got_len = false; - bool got_zlen = false; - int len_value = 0; - - while ('0' <= cformat && cformat <= '9') - { - if (!got_len && cformat == '0') - got_zlen = true; - - got_len = true; - len_value = 10*len_value + (cformat - '0'); - - cformat = sformat[++i]; - } - - // Simplify the argument - AstNode *node_arg = nullptr; - - // Everything from here on depends on the format specifier - switch (cformat) - { - case 's': - case 'S': - case 'd': - case 'D': - if (got_len) - goto unsupported_format; - YS_FALLTHROUGH - case 'x': - case 'X': - if (next_arg >= GetSize(children)) - log_file_error(filename, location.first_line, "Missing argument for %%%c format specifier in system task `%s'.\n", - cformat, str.c_str()); - - node_arg = children[next_arg++]; - while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } - if (node_arg->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Failed to evaluate system task `%s' with non-constant argument.\n", str.c_str()); - break; - - case 'm': - case 'M': - if (got_len) - goto unsupported_format; - break; - - default: - unsupported_format: - log_file_error(filename, location.first_line, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str()); - break; - } - - switch (cformat) - { - case 's': - case 'S': - sout += node_arg->bitsAsConst().decode_string(); - break; - - case 'd': - case 'D': - sout += stringf("%d", node_arg->bitsAsConst().as_int()); - break; - - case 'x': - case 'X': - { - Const val = node_arg->bitsAsConst(); - - while (GetSize(val) % 4 != 0) - val.bits.push_back(State::S0); - - int len = GetSize(val) / 4; - for (int i = len; i < len_value; i++) - sout += got_zlen ? '0' : ' '; - - for (int i = len-1; i >= 0; i--) { - Const digit = val.extract(4*i, 4); - if (digit.is_fully_def()) - sout += stringf(cformat == 'x' ? "%x" : "%X", digit.as_int()); - else - sout += cformat == 'x' ? "x" : "X"; - } - } - break; - - case 'm': - case 'M': - sout += log_id(current_module->name); - break; - - default: - log_abort(); - } - } - - // not a format specifier - else - sout += sformat[i]; - } - return sout; -} - - -void AstNode::annotateTypedEnums(AstNode *template_node) -{ - //check if enum - if (template_node->attributes.count(ID::enum_type)) { - //get reference to enum node: - std::string enum_type = template_node->attributes[ID::enum_type]->str.c_str(); - // log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type)); - // log("current scope:\n"); - // for (auto &it : current_scope) - // log(" %s\n", it.first.c_str()); - log_assert(current_scope.count(enum_type) == 1); - AstNode *enum_node = current_scope.at(enum_type); - log_assert(enum_node->type == AST_ENUM); - //get width from 1st enum item: - log_assert(enum_node->children.size() >= 1); - AstNode *enum_item0 = enum_node->children[0]; - log_assert(enum_item0->type == AST_ENUM_ITEM); - int width; - if (!enum_item0->range_valid) - width = 1; - else if (enum_item0->range_swapped) - width = enum_item0->range_right - enum_item0->range_left + 1; - else - width = enum_item0->range_left - enum_item0->range_right + 1; - log_assert(width > 0); - //add declared enum items: - for (auto enum_item : enum_node->children){ - log_assert(enum_item->type == AST_ENUM_ITEM); - //get is_signed - bool is_signed; - if (enum_item->children.size() == 1){ - is_signed = false; - } else if (enum_item->children.size() == 2){ - log_assert(enum_item->children[1]->type == AST_RANGE); - is_signed = enum_item->children[1]->is_signed; - } else { - log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n", - enum_item->children.size(), - enum_item->str.c_str(), enum_node->str.c_str() - ); - } - //start building attribute string - std::string enum_item_str = "\\enum_value_"; - //get enum item value - if(enum_item->children[0]->type != AST_CONSTANT){ - log_error("expected const, got %s for %s (%s)\n", - type2str(enum_item->children[0]->type).c_str(), - enum_item->str.c_str(), enum_node->str.c_str() - ); - } - RTLIL::Const val = enum_item->children[0]->bitsAsConst(width, is_signed); - enum_item_str.append(val.as_string()); - //set attribute for available val to enum item name mappings - attributes[enum_item_str.c_str()] = mkconst_str(enum_item->str); - } - } -} - -static bool name_has_dot(const std::string &name, std::string &struct_name) -{ - // check if plausible struct member name \sss.mmm - std::string::size_type pos; - if (name.substr(0, 1) == "\\" && (pos = name.find('.', 0)) != std::string::npos) { - struct_name = name.substr(0, pos); - return true; - } - return false; -} - -static AstNode *make_range(int left, int right, bool is_signed = false) -{ - // generate a pre-validated range node for a fixed signal range. - auto range = new AstNode(AST_RANGE); - range->range_left = left; - range->range_right = right; - range->range_valid = true; - range->children.push_back(AstNode::mkconst_int(left, true)); - range->children.push_back(AstNode::mkconst_int(right, true)); - range->is_signed = is_signed; - return range; -} - -static int range_width(AstNode *node, AstNode *rnode) -{ - log_assert(rnode->type==AST_RANGE); - if (!rnode->range_valid) { - log_file_error(node->filename, node->location.first_line, "Size must be constant in packed struct/union member %s\n", node->str.c_str()); - - } - // note: range swapping has already been checked for - return rnode->range_left - rnode->range_right + 1; -} - -[[noreturn]] static void struct_array_packing_error(AstNode *node) -{ - log_file_error(node->filename, node->location.first_line, "Unpacked array in packed struct/union member %s\n", node->str.c_str()); -} - -static void save_struct_array_width(AstNode *node, int width) -{ - // stash the stride for the array - node->multirange_dimensions.push_back(width); - -} - -static int get_struct_array_width(AstNode *node) -{ - // the stride for the array, 1 if not an array - return (node->multirange_dimensions.empty() ? 1 : node->multirange_dimensions.back()); - -} - -static int size_packed_struct(AstNode *snode, int base_offset) -{ - // Struct members will be laid out in the structure contiguously from left to right. - // Union members all have zero offset from the start of the union. - // Determine total packed size and assign offsets. Store these in the member node. - bool is_union = (snode->type == AST_UNION); - int offset = 0; - int packed_width = -1; - // examine members from last to first - for (auto it = snode->children.rbegin(); it != snode->children.rend(); ++it) { - auto node = *it; - int width; - if (node->type == AST_STRUCT || node->type == AST_UNION) { - // embedded struct or union - width = size_packed_struct(node, base_offset + offset); - } - else { - log_assert(node->type == AST_STRUCT_ITEM); - if (node->children.size() > 0 && node->children[0]->type == AST_RANGE) { - // member width e.g. bit [7:0] a - width = range_width(node, node->children[0]); - if (node->children.size() == 2) { - if (node->children[1]->type == AST_RANGE) { - // unpacked array e.g. bit [63:0] a [0:3] - auto rnode = node->children[1]; - int array_count = range_width(node, rnode); - if (array_count == 1) { - // C-type array size e.g. bit [63:0] a [4] - array_count = rnode->range_left; - } - save_struct_array_width(node, width); - width *= array_count; - } - else { - // array element must be single bit for a packed array - struct_array_packing_error(node); - } - } - // range nodes are now redundant - node->children.clear(); - } - else if (node->children.size() == 1 && node->children[0]->type == AST_MULTIRANGE) { - // packed 2D array, e.g. bit [3:0][63:0] a - auto rnode = node->children[0]; - if (rnode->children.size() != 2) { - // packed arrays can only be 2D - struct_array_packing_error(node); - } - int array_count = range_width(node, rnode->children[0]); - width = range_width(node, rnode->children[1]); - save_struct_array_width(node, width); - width *= array_count; - // range nodes are now redundant - node->children.clear(); - } - else if (node->range_left < 0) { - // 1 bit signal: bit, logic or reg - width = 1; - } - else { - // already resolved and compacted - width = node->range_left - node->range_right + 1; - } - if (is_union) { - node->range_right = base_offset; - node->range_left = base_offset + width - 1; - } - else { - node->range_right = base_offset + offset; - node->range_left = base_offset + offset + width - 1; - } - node->range_valid = true; - } - if (is_union) { - // check that all members have the same size - if (packed_width == -1) { - // first member - packed_width = width; - } - else { - if (packed_width != width) { - - log_file_error(node->filename, node->location.first_line, "member %s of a packed union has %d bits, expecting %d\n", node->str.c_str(), width, packed_width); - } - } - } - else { - offset += width; - } - } - return (is_union ? packed_width : offset); -} - -[[noreturn]] static void struct_op_error(AstNode *node) -{ - log_file_error(node->filename, node->location.first_line, "Unsupported operation for struct/union member %s\n", node->str.c_str()+1); -} - -static AstNode *node_int(int ival) -{ - // maybe mkconst_int should have default values for the common integer case - return AstNode::mkconst_int(ival, true, 32); -} - -static AstNode *offset_indexed_range(int offset_right, int stride, AstNode *left_expr, AstNode *right_expr) -{ - // adjust the range expressions to add an offset into the struct - // and maybe index using an array stride - auto left = left_expr->clone(); - auto right = right_expr->clone(); - if (stride == 1) { - // just add the offset - left = new AstNode(AST_ADD, node_int(offset_right), left); - right = new AstNode(AST_ADD, node_int(offset_right), right); - } - else { - // newleft = offset_right - 1 + (left + 1) * stride - left = new AstNode(AST_ADD, new AstNode(AST_SUB, node_int(offset_right), node_int(1)), - new AstNode(AST_MUL, node_int(stride), new AstNode(AST_ADD, left, node_int(1)))); - // newright = offset_right + right * stride - right = new AstNode(AST_ADD, node_int(offset_right), new AstNode(AST_MUL, right, node_int(stride))); - } - return new AstNode(AST_RANGE, left, right); -} - -static AstNode *make_struct_member_range(AstNode *node, AstNode *member_node) -{ - // Work out the range in the packed array that corresponds to a struct member - // taking into account any range operations applicable to the current node - // such as array indexing or slicing - int range_left = member_node->range_left; - int range_right = member_node->range_right; - if (node->children.empty()) { - // no range operations apply, return the whole width - } - else if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { - auto rnode = node->children[0]; - int stride = get_struct_array_width(member_node); - if (rnode->children.size() == 1) { - // index e.g. s.a[i] - return offset_indexed_range(range_right, stride, rnode->children[0], rnode->children[0]); - } - else if (rnode->children.size() == 2) { - // slice e.g. s.a[i:j] - return offset_indexed_range(range_right, stride, rnode->children[0], rnode->children[1]); - } - else { - struct_op_error(node); - } - } - else { - // TODO multirange, i.e. bit slice after array index s.a[i][p:q] - struct_op_error(node); - } - return make_range(range_left, range_right); -} - -static void add_members_to_scope(AstNode *snode, std::string name) -{ - // add all the members in a struct or union to local scope - // in case later referenced in assignments - log_assert(snode->type==AST_STRUCT || snode->type==AST_UNION); - for (auto *node : snode->children) { - if (node->type != AST_STRUCT_ITEM) { - // embedded struct or union - add_members_to_scope(node, name + "." + node->str); - } - else { - auto member_name = name + "." + node->str; - current_scope[member_name] = node; - } - } -} - -static int get_max_offset(AstNode *node) -{ - // get the width from the MS member in the struct - // as members are laid out from left to right in the packed wire - log_assert(node->type==AST_STRUCT || node->type==AST_UNION); - while (node->type != AST_STRUCT_ITEM) { - node = node->children[0]; - } - return node->range_left; -} - -static AstNode *make_packed_struct(AstNode *template_node, std::string &name) -{ - // create a wire for the packed struct - auto wnode = new AstNode(AST_WIRE); - wnode->str = name; - wnode->is_logic = true; - wnode->range_valid = true; - wnode->is_signed = template_node->is_signed; - int offset = get_max_offset(template_node); - auto range = make_range(offset, 0); - wnode->children.push_back(range); - // make sure this node is the one in scope for this name - current_scope[name] = wnode; - // add all the struct members to scope under the wire's name - add_members_to_scope(template_node, name); - return wnode; -} - // convert the AST into a simpler AST that has all parameters substituted by their // values, unrolled for-loops, expanded generate blocks, etc. when this function // is done with an AST it can be converted into RTLIL using genRTLIL(). @@ -504,7 +62,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, #if 0 log("-------------\n"); - log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, filename.c_str(), location.first_line, type2str(type).c_str(), this); + log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, filename.c_str(), linenum, type2str(type).c_str(), this); log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n", int(const_fold), int(at_zero), int(in_lvalue), int(stage), int(width_hint), int(sign_hint), int(in_param)); // dumpAst(NULL, "> "); @@ -517,7 +75,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, deep_recursion_warning = true; while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { } - if (!flag_nomem2reg && !get_bool_attribute(ID::nomem2reg)) + if (!flag_nomem2reg && !get_bool_attribute("\\nomem2reg")) { dict> mem2reg_places; dict mem2reg_candidates, dummy_proc_flags; @@ -532,10 +90,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, bool this_nomeminit = flag_nomeminit; log_assert((memflags & ~0x00ffff00) == 0); - if (mem->get_bool_attribute(ID::nomem2reg)) + if (mem->get_bool_attribute("\\nomem2reg")) continue; - if (mem->get_bool_attribute(ID::nomeminit) || get_bool_attribute(ID::nomeminit)) + if (mem->get_bool_attribute("\\nomeminit") || get_bool_attribute("\\nomeminit")) this_nomeminit = true; if (memflags & AstNode::MEM2REG_FL_FORCED) @@ -593,10 +151,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, reg->is_reg = true; reg->is_signed = node->is_signed; for (auto &it : node->attributes) - if (it.first != ID::mem2reg) + if (it.first != ID(mem2reg)) reg->attributes.emplace(it.first, it.second->clone()); reg->filename = node->filename; - reg->location = node->location; + reg->linenum = node->linenum; children.push_back(reg); while (reg->simplify(true, false, false, 1, -1, false, false)) { } } @@ -618,6 +176,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } current_filename = filename; + set_line_num(linenum); // we do not look inside a task or function // (but as soon as a task or function is instantiated we process the generated AST as usual) @@ -630,13 +189,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" || str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) { - log_file_warning(filename, location.first_line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str()); + log_file_warning(filename, linenum, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str()); delete_children(); str = std::string(); } if ((type == AST_TCALL) && (str == "$display" || str == "$write") && (!current_always || current_always->type != AST_INITIAL)) { - log_file_warning(filename, location.first_line, "System task `%s' outside initial block is unsupported.\n", str.c_str()); + log_file_warning(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str()); delete_children(); str = std::string(); } @@ -648,16 +207,108 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, { int nargs = GetSize(children); if (nargs < 1) - log_file_error(filename, location.first_line, "System task `%s' got %d arguments, expected >= 1.\n", + log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n", str.c_str(), int(children.size())); // First argument is the format string AstNode *node_string = children[0]; while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_string->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str.c_str()); + log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str.c_str()); std::string sformat = node_string->bitsAsConst().decode_string(); - std::string sout = process_format_str(sformat, 1, stage, width_hint, sign_hint); + + // Other arguments are placeholders. Process the string as we go through it + std::string sout; + int next_arg = 1; + for (size_t i = 0; i < sformat.length(); i++) + { + // format specifier + if (sformat[i] == '%') + { + // If there's no next character, that's a problem + if (i+1 >= sformat.length()) + log_file_error(filename, linenum, "System task `%s' called with `%%' at end of string.\n", str.c_str()); + + char cformat = sformat[++i]; + + // %% is special, does not need a matching argument + if (cformat == '%') + { + sout += '%'; + continue; + } + + // Simplify the argument + AstNode *node_arg = nullptr; + + // Everything from here on depends on the format specifier + switch (cformat) + { + case 's': + case 'S': + case 'd': + case 'D': + case 'x': + case 'X': + if (next_arg >= GetSize(children)) + log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n", + cformat, str.c_str()); + + node_arg = children[next_arg++]; + while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + if (node_arg->type != AST_CONSTANT) + log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant argument.\n", str.c_str()); + break; + + case 'm': + case 'M': + break; + + default: + log_file_error(filename, linenum, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str()); + break; + } + + switch (cformat) + { + case 's': + case 'S': + sout += node_arg->bitsAsConst().decode_string(); + break; + + case 'd': + case 'D': + { + char tmp[128]; + snprintf(tmp, sizeof(tmp), "%d", node_arg->bitsAsConst().as_int()); + sout += tmp; + } + break; + + case 'x': + case 'X': + { + char tmp[128]; + snprintf(tmp, sizeof(tmp), "%x", node_arg->bitsAsConst().as_int()); + sout += tmp; + } + break; + + case 'm': + case 'M': + sout += log_id(current_module->name); + break; + + default: + log_abort(); + } + } + + // not a format specifier + else + sout += sformat[i]; + } + // Finally, print the message (only include a \n for $display, not for $write) log("%s", sout.c_str()); if (str == "$display") @@ -667,9 +318,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.) - if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_ENUM_ITEM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF) + if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF) const_fold = true; - if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM || current_scope[str]->type == AST_ENUM_ITEM)) + if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) const_fold = true; // in certain cases a function must be evaluated constant. this is what in_param controls. @@ -690,9 +341,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { for (auto c : node->children[0]->children) { if (!c->is_simple_const_expr()) { - if (attributes.count(ID::dynports)) - delete attributes.at(ID::dynports); - attributes[ID::dynports] = AstNode::mkconst_int(1, true); + if (attributes.count("\\dynports")) + delete attributes.at("\\dynports"); + attributes["\\dynports"] = AstNode::mkconst_int(1, true); } } } @@ -749,67 +400,26 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, continue; wires_are_incompatible: if (stage > 1) - log_file_error(filename, location.first_line, "Incompatible re-declaration of wire %s.\n", node->str.c_str()); + log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", node->str.c_str()); continue; } this_wire_scope[node->str] = node; } - // these nodes appear at the top level in a module and can define names if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR || node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL || node->type == AST_TYPEDEF) { backup_scope[node->str] = current_scope[node->str]; current_scope[node->str] = node; } - if (node->type == AST_ENUM) { - current_scope[node->str] = node; - for (auto enode : node->children) { - log_assert(enode->type==AST_ENUM_ITEM); - if (current_scope.count(enode->str) == 0) - current_scope[enode->str] = enode; - else - log_file_error(filename, location.first_line, "enum item %s already exists\n", enode->str.c_str()); - } - } } for (size_t i = 0; i < children.size(); i++) { AstNode *node = children[i]; if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF) while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM)) did_something = true; - if (node->type == AST_ENUM) { - for (auto enode : node->children){ - log_assert(enode->type==AST_ENUM_ITEM); - while (node->simplify(true, false, false, 1, -1, false, in_param)) - did_something = true; - } - } } } - // create name resolution entries for all objects with names - if (type == AST_PACKAGE) { - //add names to package scope - for (size_t i = 0; i < children.size(); i++) { - AstNode *node = children[i]; - // these nodes appear at the top level in a package and can define names - if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_TYPEDEF) { - current_scope[node->str] = node; - } - if (node->type == AST_ENUM) { - current_scope[node->str] = node; - for (auto enode : node->children) { - log_assert(enode->type==AST_ENUM_ITEM); - if (current_scope.count(enode->str) == 0) - current_scope[enode->str] = enode; - else - log_file_error(filename, location.first_line, "enum item %s already exists in package\n", enode->str.c_str()); - } - } - } - } - - auto backup_current_block = current_block; auto backup_current_block_child = current_block_child; auto backup_current_top_block = current_top_block; @@ -819,7 +429,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_ALWAYS || type == AST_INITIAL) { if (current_always != nullptr) - log_file_error(filename, location.first_line, "Invalid nesting of always blocks and/or initializations.\n"); + log_file_error(filename, linenum, "Invalid nesting of always blocks and/or initializations.\n"); current_always = this; current_always_clocked = false; @@ -862,7 +472,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic) children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg) - log_warning("wire '%s' is assigned in a block at %s:%d.%d-%d.%d.\n", children[0]->str.c_str(), filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); if (type == AST_ASSIGN && children[0]->id2ast->is_reg) { bool is_rand_reg = false; if (children[1]->type == AST_FCALL) { @@ -876,50 +486,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, is_rand_reg = true; } if (!is_rand_reg) - log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.%d-%d.%d.\n", children[0]->str.c_str(), filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); } children[0]->was_checked = true; } break; - case AST_STRUCT: - case AST_UNION: - if (!basic_prep) { - for (auto *node : children) { - // resolve any ranges - while (!node->basic_prep && node->simplify(true, false, false, stage, -1, false, false)) { - did_something = true; - } - } - // determine member offsets and widths - size_packed_struct(this, 0); - - // instance rather than just a type in a typedef or outer struct? - if (!str.empty() && str[0] == '\\') { - // instance so add a wire for the packed structure - auto wnode = make_packed_struct(this, str); - log_assert(current_ast_mod); - current_ast_mod->children.push_back(wnode); - } - basic_prep = true; - } - break; - - case AST_STRUCT_ITEM: - break; - - case AST_ENUM: - //log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep); - if (!basic_prep) { - for (auto item_node : children) { - while (!item_node->basic_prep && item_node->simplify(false, false, false, stage, -1, false, in_param)) - did_something = true; - } - // allocate values (called more than once) - allocateDefaultEnumValues(); - } - break; - case AST_PARAMETER: case AST_LOCALPARAM: while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true) @@ -929,19 +501,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true) did_something = true; if (!children[1]->range_valid) - log_file_error(filename, location.first_line, "Non-constant width range on parameter decl.\n"); - width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1); - } - break; - case AST_ENUM_ITEM: - while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, in_param)) - did_something = true; - children[0]->detectSignWidth(width_hint, sign_hint); - if (children.size() > 1 && children[1]->type == AST_RANGE) { - while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, in_param)) - did_something = true; - if (!children[1]->range_valid) - log_file_error(filename, location.first_line, "Non-constant width range on enum item decl.\n"); + log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n"); width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1); } break; @@ -949,7 +509,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case AST_TO_BITS: case AST_TO_SIGNED: case AST_TO_UNSIGNED: - case AST_SELFSZ: case AST_CONCAT: case AST_REPLICATE: case AST_REDUCE_AND: @@ -1181,6 +740,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } current_filename = filename; + set_line_num(linenum); if (type == AST_MODULE) current_scope.clear(); @@ -1189,7 +749,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_DEFPARAM && !children.empty()) { if (children[0]->type != AST_IDENTIFIER) - log_file_error(filename, location.first_line, "Module name in defparam contains non-constant expressions!\n"); + log_file_error(filename, linenum, "Module name in defparam contains non-constant expressions!\n"); string modname, paramname = children[0]->str; @@ -1206,12 +766,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } if (pos == std::string::npos) - log_file_error(filename, location.first_line, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname).c_str()); + log_file_error(filename, linenum, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname).c_str()); paramname = "\\" + paramname.substr(pos+1); if (current_scope.at(modname)->type != AST_CELL) - log_file_error(filename, location.first_line, "Defparam argument `%s . %s` does not match a cell!\n", + log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n", RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL); @@ -1225,12 +785,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // resolve typedefs if (type == AST_TYPEDEF) { log_assert(children.size() == 1); - auto type_node = children[0]; - log_assert(type_node->type == AST_WIRE || type_node->type == AST_MEMORY || type_node->type == AST_STRUCT || type_node->type == AST_UNION); - while (type_node->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { + log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY); + while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) did_something = true; - } - log_assert(!type_node->is_custom_type); + log_assert(!children[0]->is_custom_type); } // resolve types of wires @@ -1238,57 +796,45 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (is_custom_type) { log_assert(children.size() >= 1); log_assert(children[0]->type == AST_WIRETYPE); - auto type_name = children[0]->str; - if (!current_scope.count(type_name)) { - log_file_error(filename, location.first_line, "Unknown identifier `%s' used as type name\n", type_name.c_str()); - } - AstNode *resolved_type_node = current_scope.at(type_name); - if (resolved_type_node->type != AST_TYPEDEF) - log_file_error(filename, location.first_line, "`%s' does not name a type\n", type_name.c_str()); - log_assert(resolved_type_node->children.size() == 1); - AstNode *template_node = resolved_type_node->children[0]; - - // Ensure typedef itself is fully simplified - while (template_node->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; - - if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) { - // replace with wire representing the packed structure - newNode = make_packed_struct(template_node, str); - current_scope[str] = this; - goto apply_newNode; - } - + if (!current_scope.count(children[0]->str)) + log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str()); + AstNode *resolved_type = current_scope.at(children[0]->str); + if (resolved_type->type != AST_TYPEDEF) + log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str()); + log_assert(resolved_type->children.size() == 1); + AstNode *templ = resolved_type->children[0]; // Remove type reference delete children[0]; children.erase(children.begin()); - if (type == AST_WIRE) - type = template_node->type; - is_reg = template_node->is_reg; - is_logic = template_node->is_logic; - is_signed = template_node->is_signed; - is_string = template_node->is_string; - is_custom_type = template_node->is_custom_type; - - range_valid = template_node->range_valid; - range_swapped = template_node->range_swapped; - range_left = template_node->range_left; - range_right = template_node->range_right; - - attributes[ID::wiretype] = mkconst_str(resolved_type_node->str); + // Ensure typedef itself is fully simplified + while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; - // if an enum then add attributes to support simulator tracing - annotateTypedEnums(template_node); + if (type == AST_WIRE) + type = templ->type; + is_reg = templ->is_reg; + is_logic = templ->is_logic; + is_signed = templ->is_signed; + is_string = templ->is_string; + is_custom_type = templ->is_custom_type; + + range_valid = templ->range_valid; + range_swapped = templ->range_swapped; + range_left = templ->range_left; + range_right = templ->range_right; // Insert clones children from template at beginning - for (int i = 0; i < GetSize(template_node->children); i++) - children.insert(children.begin() + i, template_node->children[i]->clone()); - + for (int i = 0; i < GetSize(templ->children); i++) + children.insert(children.begin() + i, templ->children[i]->clone()); + if (type == AST_MEMORY && GetSize(children) == 1) { // Single-bit memories must have [0:0] range - AstNode *rng = make_range(0, 0); + AstNode *rng = new AstNode(AST_RANGE); + rng->children.push_back(AstNode::mkconst_int(0, true)); + rng->children.push_back(AstNode::mkconst_int(0, true)); children.insert(children.begin(), rng); } + did_something = true; } log_assert(!is_custom_type); @@ -1300,41 +846,40 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_assert(children.size() == 2); log_assert(children[1]->type == AST_WIRETYPE); if (!current_scope.count(children[1]->str)) - log_file_error(filename, location.first_line, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str()); - AstNode *resolved_type_node = current_scope.at(children[1]->str); - if (resolved_type_node->type != AST_TYPEDEF) - log_file_error(filename, location.first_line, "`%s' does not name a type\n", children[1]->str.c_str()); - log_assert(resolved_type_node->children.size() == 1); - AstNode *template_node = resolved_type_node->children[0]; + log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str()); + AstNode *resolved_type = current_scope.at(children[1]->str); + if (resolved_type->type != AST_TYPEDEF) + log_file_error(filename, linenum, "`%s' does not name a type\n", children[1]->str.c_str()); + log_assert(resolved_type->children.size() == 1); + AstNode *templ = resolved_type->children[0]; delete children[1]; children.pop_back(); // Ensure typedef itself is fully simplified - while(template_node->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; - - if (template_node->type == AST_MEMORY) - log_file_error(filename, location.first_line, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str()); - is_signed = template_node->is_signed; - is_string = template_node->is_string; - is_custom_type = template_node->is_custom_type; - - range_valid = template_node->range_valid; - range_swapped = template_node->range_swapped; - range_left = template_node->range_left; - range_right = template_node->range_right; - attributes[ID::wiretype] = mkconst_str(resolved_type_node->str); - for (auto template_child : template_node->children) + while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + + if (templ->type == AST_MEMORY) + log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str()); + is_signed = templ->is_signed; + is_string = templ->is_string; + is_custom_type = templ->is_custom_type; + + range_valid = templ->range_valid; + range_swapped = templ->range_swapped; + range_left = templ->range_left; + range_right = templ->range_right; + for (auto template_child : templ->children) children.push_back(template_child->clone()); did_something = true; } log_assert(!is_custom_type); - } + } // resolve constant prefixes if (type == AST_PREFIX) { if (children[0]->type != AST_CONSTANT) { // dumpAst(NULL, "> "); - log_file_error(filename, location.first_line, "Index in generate block prefix syntax is not constant!\n"); + log_file_error(filename, linenum, "Index in generate block prefix syntax is not constant!\n"); } if (children[1]->type == AST_PREFIX) children[1]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param); @@ -1350,9 +895,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // evaluate TO_BITS nodes if (type == AST_TO_BITS) { if (children[0]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Left operand of to_bits expression is not constant!\n"); + log_file_error(filename, linenum, "Left operand of to_bits expression is not constant!\n"); if (children[1]->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Right operand of to_bits expression is not constant!\n"); + log_file_error(filename, linenum, "Right operand of to_bits expression is not constant!\n"); RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed); newNode = mkconst_bits(new_value.bits, children[1]->is_signed); goto apply_newNode; @@ -1380,7 +925,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } if (old_range_valid != range_valid) did_something = true; - if (range_valid && range_right > range_left) { + if (range_valid && range_left >= 0 && range_right > range_left) { int tmp = range_right; range_right = range_left; range_left = tmp; @@ -1398,25 +943,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, range_swapped = children[0]->range_swapped; range_left = children[0]->range_left; range_right = children[0]->range_right; - bool force_upto = false, force_downto = false; - if (attributes.count(ID::force_upto)) { - AstNode *val = attributes[ID::force_upto]; - if (val->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Attribute `force_upto' with non-constant value!\n"); - force_upto = val->asAttrConst().as_bool(); - } - if (attributes.count(ID::force_downto)) { - AstNode *val = attributes[ID::force_downto]; - if (val->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Attribute `force_downto' with non-constant value!\n"); - force_downto = val->asAttrConst().as_bool(); - } - if (force_upto && force_downto) - log_file_error(filename, location.first_line, "Attributes `force_downto' and `force_upto' cannot be both set!\n"); - if ((force_upto && !range_swapped) || (force_downto && range_swapped)) { - std::swap(range_left, range_right); - range_swapped = force_upto; - } } } else { if (!range_valid) @@ -1435,7 +961,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, multirange_dimensions.clear(); for (auto range : children[1]->children) { if (!range->range_valid) - log_file_error(filename, location.first_line, "Non-constant range on memory decl.\n"); + log_file_error(filename, linenum, "Non-constant range on memory decl.\n"); multirange_dimensions.push_back(min(range->range_left, range->range_right)); multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1); total_size *= multirange_dimensions.back(); @@ -1453,7 +979,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++) { if (GetSize(children[0]->children) < i) - log_file_error(filename, location.first_line, "Insufficient number of array indices for %s.\n", log_id(str)); + log_file_error(filename, linenum, "Insufficient number of array indices for %s.\n", log_id(str)); AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone(); @@ -1479,14 +1005,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } // trim/extend parameters - if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_ENUM_ITEM) { + if (type == AST_PARAMETER || type == AST_LOCALPARAM) { if (children.size() > 1 && children[1]->type == AST_RANGE) { if (!children[1]->range_valid) - log_file_error(filename, location.first_line, "Non-constant width range on parameter decl.\n"); + log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n"); int width = std::abs(children[1]->range_left - children[1]->range_right) + 1; if (children[0]->type == AST_REALVALUE) { RTLIL::Const constvalue = children[0]->realAsConst(width); - log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n", + log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", children[0]->realvalue, log_signal(constvalue)); delete children[0]; children[0] = mkconst_bits(constvalue.bits, sign_hint); @@ -1516,71 +1042,26 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } } - if (type == AST_IDENTIFIER && !basic_prep) { - // check if a plausible struct member sss.mmmm - std::string sname; - if (name_has_dot(str, sname)) { - if (current_scope.count(str) > 0) { - auto item_node = current_scope[str]; - if (item_node->type == AST_STRUCT_ITEM) { - // structure member, rewrite this node to reference the packed struct wire - auto range = make_struct_member_range(this, item_node); - newNode = new AstNode(AST_IDENTIFIER, range); - newNode->str = sname; - newNode->basic_prep = true; - goto apply_newNode; - } - } - } - } // annotate identifiers using scope resolution and create auto-wires as needed if (type == AST_IDENTIFIER) { if (current_scope.count(str) == 0) { - AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod; - for (auto node : current_scope_ast->children) { - //log("looking at mod scope child %s\n", type2str(node->type).c_str()); - switch (node->type) { - case AST_PARAMETER: - case AST_LOCALPARAM: - case AST_WIRE: - case AST_AUTOWIRE: - case AST_GENVAR: - case AST_MEMORY: - case AST_FUNCTION: - case AST_TASK: - case AST_DPI_FUNCTION: - //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str()); - if (str == node->str) { - //log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str()); - current_scope[node->str] = node; - } - break; - case AST_ENUM: + for (auto node : current_ast_mod->children) { + if ((node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR || + node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION) && str == node->str) { current_scope[node->str] = node; - for (auto enum_node : node->children) { - log_assert(enum_node->type==AST_ENUM_ITEM); - if (str == enum_node->str) { - //log("\nadding enum item %s to scope\n", str.c_str()); - current_scope[str] = enum_node; - } - } - break; - default: break; } } } if (current_scope.count(str) == 0) { - if (current_ast_mod == nullptr) { - log_file_error(filename, location.first_line, "Identifier `%s' is implicitly declared outside of a module.\n", str.c_str()); - } else if (flag_autowire || str == "\\$global_clock") { + if (flag_autowire || str == "\\$global_clock") { AstNode *auto_wire = new AstNode(AST_AUTOWIRE); auto_wire->str = str; current_ast_mod->children.push_back(auto_wire); current_scope[str] = auto_wire; did_something = true; } else { - log_file_error(filename, location.first_line, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str()); } } if (id2ast != current_scope[str]) { @@ -1593,7 +1074,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue) { if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1) - log_file_error(filename, location.first_line, "Invalid bit-select on memory access!\n"); + log_file_error(filename, linenum, "Invalid bit-select on memory access!\n"); int mem_width, mem_size, addr_bits; id2ast->meminfo(mem_width, mem_size, addr_bits); @@ -1605,13 +1086,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, std::swap(data_range_left, data_range_right); std::stringstream sstr; - sstr << "$mem2bits$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++); + sstr << "$mem2bits$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++); std::string wire_id = sstr.str(); AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true))); wire->str = wire_id; if (current_block) - wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false); + wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); current_ast_mod->children.push_back(wire); while (wire->simplify(true, false, false, 1, -1, false, false)) { } @@ -1646,7 +1127,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } if (type == AST_WHILE) - log_file_error(filename, location.first_line, "While loops are only allowed in constant functions!\n"); + log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n"); if (type == AST_REPEAT) { @@ -1657,7 +1138,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (count->simplify(true, false, false, stage, 32, true, false)) { } if (count->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Repeat loops outside must have constant repeat counts!\n"); + log_file_error(filename, linenum, "Repeat loops outside must have constant repeat counts!\n"); // convert to a block with the body repeated n times type = AST_BLOCK; @@ -1683,24 +1164,24 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, body_ast = body_ast->children.at(0); if (init_ast->type != AST_ASSIGN_EQ) - log_file_error(filename, location.first_line, "Unsupported 1st expression of generate for-loop!\n"); + log_file_error(filename, linenum, "Unsupported 1st expression of generate for-loop!\n"); if (next_ast->type != AST_ASSIGN_EQ) - log_file_error(filename, location.first_line, "Unsupported 3rd expression of generate for-loop!\n"); + log_file_error(filename, linenum, "Unsupported 3rd expression of generate for-loop!\n"); if (type == AST_GENFOR) { if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR) - log_file_error(filename, location.first_line, "Left hand side of 1st expression of generate for-loop is not a gen var!\n"); + log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a gen var!\n"); if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_GENVAR) - log_file_error(filename, location.first_line, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n"); + log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n"); } else { if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_WIRE) - log_file_error(filename, location.first_line, "Left hand side of 1st expression of generate for-loop is not a register!\n"); + log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a register!\n"); if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_WIRE) - log_file_error(filename, location.first_line, "Left hand side of 3rd expression of generate for-loop is not a register!\n"); + log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a register!\n"); } if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast) - log_file_error(filename, location.first_line, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n"); + log_file_error(filename, linenum, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n"); // eval 1st expression AstNode *varbuf = init_ast->children[1]->clone(); @@ -1712,21 +1193,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } if (varbuf->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Right hand side of 1st expression of generate for-loop is not constant!\n"); - - auto resolved = current_scope.at(init_ast->children[0]->str); - if (resolved->range_valid) { - int const_size = varbuf->range_left - varbuf->range_right; - int resolved_size = resolved->range_left - resolved->range_right; - if (const_size < resolved_size) { - for (int i = const_size; i < resolved_size; i++) - varbuf->bits.push_back(resolved->is_signed ? varbuf->bits.back() : State::S0); - varbuf->range_left = resolved->range_left; - varbuf->range_right = resolved->range_right; - varbuf->range_swapped = resolved->range_swapped; - varbuf->range_valid = resolved->range_valid; - } - } + log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n"); varbuf = new AstNode(AST_LOCALPARAM, varbuf); varbuf->str = init_ast->children[0]->str; @@ -1753,7 +1220,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } if (buf->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "2nd expression of generate for-loop is not constant!\n"); + log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n"); if (buf->integer == 0) { delete buf; @@ -1769,7 +1236,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, buf = new AstNode(AST_GENBLOCK, body_ast->clone()); if (buf->str.empty()) { std::stringstream sstr; - sstr << "$genblock$" << filename << ":" << location.first_line << "$" << (autoidx++); + sstr << "$genblock$" << filename << ":" << linenum << "$" << (autoidx++); buf->str = sstr.str(); } std::map name_map; @@ -1799,7 +1266,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } if (buf->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Right hand side of 3rd expression of generate for-loop is not constant (%s)!\n", type2str(buf->type).c_str()); + log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n"); delete varbuf->children[0]; varbuf->children[0] = buf; @@ -1823,7 +1290,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, { for (size_t i = 0; i < children.size(); i++) if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) - log_file_error(children[i]->filename, children[i]->location.first_line, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n"); + log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n"); } // transform block with name @@ -1871,7 +1338,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (buf->type != AST_CONSTANT) { // for (auto f : log_files) // dumpAst(f, "verilog-ast> "); - log_file_error(filename, location.first_line, "Condition for generate if is not constant!\n"); + log_file_error(filename, linenum, "Condition for generate if is not constant!\n"); } if (buf->asBool() != 0) { delete buf; @@ -1912,7 +1379,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (buf->type != AST_CONSTANT) { // for (auto f : log_files) // dumpAst(f, "verilog-ast> "); - log_file_error(filename, location.first_line, "Condition for generate case is not constant!\n"); + log_file_error(filename, linenum, "Condition for generate case is not constant!\n"); } bool ref_signed = buf->is_signed; @@ -1946,7 +1413,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (buf->type != AST_CONSTANT) { // for (auto f : log_files) // dumpAst(f, "verilog-ast> "); - log_file_error(filename, location.first_line, "Expression in generate case is not constant!\n"); + log_file_error(filename, linenum, "Expression in generate case is not constant!\n"); } bool is_selected = RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool(); @@ -1987,7 +1454,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_CELLARRAY) { if (!children.at(0)->range_valid) - log_file_error(filename, location.first_line, "Non-constant array range on cell array.\n"); + log_file_error(filename, linenum, "Non-constant array range on cell array.\n"); newNode = new AstNode(AST_GENBLOCK); int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1; @@ -1998,7 +1465,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, newNode->children.push_back(new_cell); new_cell->str += stringf("[%d]", idx); if (new_cell->type == AST_PRIMITIVE) { - log_file_error(filename, location.first_line, "Cell arrays of primitives are currently not supported.\n"); + log_file_error(filename, linenum, "Cell arrays of primitives are currently not supported.\n"); } else { log_assert(new_cell->children.at(0)->type == AST_CELLTYPE); new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str()); @@ -2012,7 +1479,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_PRIMITIVE) { if (children.size() < 2) - log_file_error(filename, location.first_line, "Insufficient number of arguments for primitive `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", str.c_str()); std::vector children_list; for (auto child : children) { @@ -2027,7 +1494,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1") { if (children_list.size() != 3) - log_file_error(filename, location.first_line, "Invalid number of arguments for primitive `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", str.c_str()); std::vector z_const(1, RTLIL::State::Sz); @@ -2076,10 +1543,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, AstNode *node = children_list[1]; if (op_type != AST_POS) - for (size_t i = 2; i < children_list.size(); i++) { + for (size_t i = 2; i < children_list.size(); i++) node = new AstNode(op_type, node, children_list[i]); - node->location = location; - } if (invert_results) node = new AstNode(AST_BIT_NOT, node); @@ -2093,10 +1558,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with - // either a big case block that selects the correct single-bit assignment, or mask and - // shift operations. - if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) - { + // a big case block that selects the correct single-bit assignment. + if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) { if (children[0]->type != AST_IDENTIFIER || children[0]->children.size() == 0) goto skip_dynamic_range_lvalue_expansion; if (children[0]->children[0]->range_valid || did_something) @@ -2105,13 +1568,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, goto skip_dynamic_range_lvalue_expansion; if (!children[0]->id2ast->range_valid) goto skip_dynamic_range_lvalue_expansion; - int source_width = children[0]->id2ast->range_left - children[0]->id2ast->range_right + 1; int result_width = 1; - AstNode *shift_expr = NULL; AstNode *range = children[0]->children[0]; - if (range->children.size() == 1) { shift_expr = range->children[0]->clone(); } else { @@ -2121,118 +1581,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; } - - bool use_case_method = false; - - if (children[0]->id2ast->attributes.count(ID::nowrshmsk)) { - AstNode *node = children[0]->id2ast->attributes.at(ID::nowrshmsk); - while (node->simplify(true, false, false, stage, -1, false, false)) { } - if (node->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children[0]->id2ast->str.c_str()); - if (node->asAttrConst().as_bool()) - use_case_method = true; - } - - if (!use_case_method && current_always->detect_latch(children[0]->str)) - use_case_method = true; - - if (use_case_method) - { - // big case block - - did_something = true; - newNode = new AstNode(AST_CASE, shift_expr); - for (int i = 0; i < source_width; i++) { - int start_bit = children[0]->id2ast->range_right + i; - int end_bit = std::min(start_bit+result_width,source_width) - 1; - AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true)); - AstNode *lvalue = children[0]->clone(); - lvalue->delete_children(); - lvalue->children.push_back(new AstNode(AST_RANGE, - mkconst_int(end_bit, true), mkconst_int(start_bit, true))); - cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone()))); - newNode->children.push_back(cond); - } - } - else - { - // mask and shift operations, disabled for now - - AstNode *wire_mask = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true))); - wire_mask->str = stringf("$bitselwrite$mask$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); - wire_mask->attributes[ID::nosync] = AstNode::mkconst_int(1, false); - wire_mask->is_logic = true; - while (wire_mask->simplify(true, false, false, 1, -1, false, false)) { } - current_ast_mod->children.push_back(wire_mask); - - AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true))); - wire_data->str = stringf("$bitselwrite$data$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); - wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false); - wire_data->is_logic = true; - while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } - current_ast_mod->children.push_back(wire_data); - - did_something = true; - newNode = new AstNode(AST_BLOCK); - + did_something = true; + newNode = new AstNode(AST_CASE, shift_expr); + for (int i = 0; i <= source_width-result_width; i++) { + int start_bit = children[0]->id2ast->range_right + i; + AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true)); AstNode *lvalue = children[0]->clone(); lvalue->delete_children(); - - AstNode *ref_mask = new AstNode(AST_IDENTIFIER); - ref_mask->str = wire_mask->str; - ref_mask->id2ast = wire_mask; - ref_mask->was_checked = true; - - AstNode *ref_data = new AstNode(AST_IDENTIFIER); - ref_data->str = wire_data->str; - ref_data->id2ast = wire_data; - ref_data->was_checked = true; - - AstNode *old_data = lvalue->clone(); - if (type == AST_ASSIGN_LE) - old_data->lookahead = true; - - AstNode *shamt = shift_expr; - - int shamt_width_hint = 0; - bool shamt_sign_hint = true; - shamt->detectSignWidth(shamt_width_hint, shamt_sign_hint); - - int start_bit = children[0]->id2ast->range_right; - bool use_shift = shamt_sign_hint; - - if (start_bit != 0) { - shamt = new AstNode(AST_SUB, shamt, mkconst_int(start_bit, true)); - use_shift = true; - } - - AstNode *t; - - t = mkconst_bits(std::vector(result_width, State::S1), false); - if (use_shift) - t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt->clone())); - else - t = new AstNode(AST_SHIFT_LEFT, t, shamt->clone()); - t = new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), t); - newNode->children.push_back(t); - - t = new AstNode(AST_BIT_AND, mkconst_bits(std::vector(result_width, State::S1), false), children[1]->clone()); - if (use_shift) - t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt)); - else - t = new AstNode(AST_SHIFT_LEFT, t, shamt); - t = new AstNode(AST_ASSIGN_EQ, ref_data->clone(), t); - newNode->children.push_back(t); - - t = new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)); - t = new AstNode(AST_BIT_OR, t, ref_data); - t = new AstNode(type, lvalue, t); - newNode->children.push_back(t); + lvalue->children.push_back(new AstNode(AST_RANGE, + mkconst_int(start_bit+result_width-1, true), mkconst_int(start_bit, true))); + cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone()))); + newNode->children.push_back(cond); } - goto apply_newNode; } skip_dynamic_range_lvalue_expansion:; @@ -2240,7 +1603,7 @@ skip_dynamic_range_lvalue_expansion:; if (stage > 1 && (type == AST_ASSERT || type == AST_ASSUME || type == AST_LIVE || type == AST_FAIR || type == AST_COVER) && current_block != NULL) { std::stringstream sstr; - sstr << "$formal$" << filename << ":" << location.first_line << "$" << (autoidx++); + sstr << "$formal$" << filename << ":" << linenum << "$" << (autoidx++); std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN"; AstNode *wire_check = new AstNode(AST_WIRE); @@ -2307,7 +1670,6 @@ skip_dynamic_range_lvalue_expansion:; newNode->children.push_back(assign_en); AstNode *assertnode = new AstNode(type); - assertnode->location = location; assertnode->str = str; assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); @@ -2349,10 +1711,10 @@ skip_dynamic_range_lvalue_expansion:; newNode = new AstNode(AST_BLOCK); AstNode *wire_tmp = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true))); - wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); + wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", filename.c_str(), linenum, autoidx++); current_ast_mod->children.push_back(wire_tmp); current_scope[wire_tmp->str] = wire_tmp; - wire_tmp->attributes[ID::nosync] = AstNode::mkconst_int(1, false); + wire_tmp->attributes["\\nosync"] = AstNode::mkconst_int(1, false); while (wire_tmp->simplify(true, false, false, 1, -1, false, false)) { } wire_tmp->is_logic = true; @@ -2387,16 +1749,13 @@ skip_dynamic_range_lvalue_expansion:; (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE) { std::stringstream sstr; - sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << location.first_line << "$" << (autoidx++); + sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++); std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN"; int mem_width, mem_size, addr_bits; bool mem_signed = children[0]->id2ast->is_signed; children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); - newNode = new AstNode(AST_BLOCK); - AstNode *defNode = new AstNode(AST_BLOCK); - int data_range_left = children[0]->id2ast->children[0]->range_left; int data_range_right = children[0]->id2ast->children[0]->range_right; int mem_data_range_offset = std::min(data_range_left, data_range_right); @@ -2406,6 +1765,31 @@ skip_dynamic_range_lvalue_expansion:; children[0]->children[0]->children[0]->detectSignWidthWorker(addr_width_hint, addr_sign_hint); addr_bits = std::max(addr_bits, addr_width_hint); + AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); + wire_addr->str = id_addr; + wire_addr->was_checked = true; + current_ast_mod->children.push_back(wire_addr); + current_scope[wire_addr->str] = wire_addr; + while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } + + AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); + wire_data->str = id_data; + wire_data->was_checked = true; + wire_data->is_signed = mem_signed; + current_ast_mod->children.push_back(wire_data); + current_scope[wire_data->str] = wire_data; + while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } + + AstNode *wire_en = nullptr; + if (current_always->type != AST_INITIAL) { + wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); + wire_en->str = id_en; + wire_en->was_checked = true; + current_ast_mod->children.push_back(wire_en); + current_scope[wire_en->str] = wire_en; + while (wire_en->simplify(true, false, false, 1, -1, false, false)) { } + } + std::vector x_bits_addr, x_bits_data, set_bits_en; for (int i = 0; i < addr_bits; i++) x_bits_addr.push_back(RTLIL::State::Sx); @@ -2414,79 +1798,32 @@ skip_dynamic_range_lvalue_expansion:; for (int i = 0; i < mem_width; i++) set_bits_en.push_back(RTLIL::State::S1); - AstNode *node_addr = nullptr; - if (children[0]->children[0]->children[0]->isConst()) { - node_addr = children[0]->children[0]->children[0]->clone(); - } else { - AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); - wire_addr->str = id_addr; - wire_addr->was_checked = true; - current_ast_mod->children.push_back(wire_addr); - current_scope[wire_addr->str] = wire_addr; - while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } - - AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false)); - assign_addr->children[0]->str = id_addr; - assign_addr->children[0]->was_checked = true; - defNode->children.push_back(assign_addr); - - assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); - assign_addr->children[0]->str = id_addr; - assign_addr->children[0]->was_checked = true; - newNode->children.push_back(assign_addr); - - node_addr = new AstNode(AST_IDENTIFIER); - node_addr->str = id_addr; - } - - AstNode *node_data = nullptr; - if (children[0]->children.size() == 1 && children[1]->isConst()) { - node_data = children[1]->clone(); - } else { - AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); - wire_data->str = id_data; - wire_data->was_checked = true; - wire_data->is_signed = mem_signed; - current_ast_mod->children.push_back(wire_data); - current_scope[wire_data->str] = wire_data; - while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } - - AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false)); - assign_data->children[0]->str = id_data; - assign_data->children[0]->was_checked = true; - defNode->children.push_back(assign_data); + AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false)); + assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->was_checked = true; - node_data = new AstNode(AST_IDENTIFIER); - node_data->str = id_data; - } + AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false)); + assign_data->children[0]->str = id_data; + assign_data->children[0]->was_checked = true; - AstNode *node_en = nullptr; - if (current_always->type == AST_INITIAL) { - node_en = AstNode::mkconst_int(1, false); - } else { - AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); - wire_en->str = id_en; - wire_en->was_checked = true; - current_ast_mod->children.push_back(wire_en); - current_scope[wire_en->str] = wire_en; - while (wire_en->simplify(true, false, false, 1, -1, false, false)) { } - - AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width)); + AstNode *assign_en = nullptr; + if (current_always->type != AST_INITIAL) { + assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width)); assign_en->children[0]->str = id_en; assign_en->children[0]->was_checked = true; - defNode->children.push_back(assign_en); - - node_en = new AstNode(AST_IDENTIFIER); - node_en->str = id_en; } - if (!defNode->children.empty()) - current_top_block->children.insert(current_top_block->children.begin(), defNode); - else - delete defNode; + AstNode *default_signals = new AstNode(AST_BLOCK); + default_signals->children.push_back(assign_addr); + default_signals->children.push_back(assign_data); + if (current_always->type != AST_INITIAL) + default_signals->children.push_back(assign_en); + current_top_block->children.insert(current_top_block->children.begin(), default_signals); + + assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); + assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->was_checked = true; - AstNode *assign_data = nullptr; - AstNode *assign_en = nullptr; if (children[0]->children.size() == 2) { if (children[0]->children[1]->range_valid) @@ -2523,7 +1860,7 @@ skip_dynamic_range_lvalue_expansion:; while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), @@ -2547,11 +1884,9 @@ skip_dynamic_range_lvalue_expansion:; } else { - if (!(children[0]->children.size() == 1 && children[1]->isConst())) { - assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone()); - assign_data->children[0]->str = id_data; - assign_data->children[0]->was_checked = true; - } + assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone()); + assign_data->children[0]->str = id_data; + assign_data->children[0]->was_checked = true; if (current_always->type != AST_INITIAL) { assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); @@ -2559,20 +1894,28 @@ skip_dynamic_range_lvalue_expansion:; assign_en->children[0]->was_checked = true; } } - if (assign_data) - newNode->children.push_back(assign_data); - if (assign_en) + + newNode = new AstNode(AST_BLOCK); + newNode->children.push_back(assign_addr); + newNode->children.push_back(assign_data); + if (current_always->type != AST_INITIAL) newNode->children.push_back(assign_en); - AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR, node_addr, node_data, node_en); + AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR); + wrnode->children.push_back(new AstNode(AST_IDENTIFIER)); + wrnode->children.push_back(new AstNode(AST_IDENTIFIER)); + if (current_always->type != AST_INITIAL) + wrnode->children.push_back(new AstNode(AST_IDENTIFIER)); + else + wrnode->children.push_back(AstNode::mkconst_int(1, false)); wrnode->str = children[0]->str; wrnode->id2ast = children[0]->id2ast; + wrnode->children[0]->str = id_addr; + wrnode->children[1]->str = id_data; + if (current_always->type != AST_INITIAL) + wrnode->children[2]->str = id_en; current_ast_mod->children.push_back(wrnode); - if (newNode->children.empty()) { - delete newNode; - newNode = new AstNode(); - } goto apply_newNode; } @@ -2613,11 +1956,11 @@ skip_dynamic_range_lvalue_expansion:; int num_steps = 1; if (GetSize(children) != 1 && GetSize(children) != 2) - log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 2.\n", + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) - log_file_error(filename, location.first_line, "System function %s is only allowed in clocked blocks.\n", + log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", RTLIL::unescape_id(str).c_str()); if (GetSize(children) == 2) @@ -2625,7 +1968,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *buf = children[1]->clone(); while (buf->simplify(true, false, false, stage, -1, false, false)) { } if (buf->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); num_steps = buf->asInt(true); delete buf; @@ -2652,7 +1995,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true))); - reg->str = stringf("$past$%s:%d$%d$%d", filename.c_str(), location.first_line, myidx, i); + reg->str = stringf("$past$%s:%d$%d$%d", filename.c_str(), linenum, myidx, i); reg->is_reg = true; current_ast_mod->children.push_back(reg); @@ -2687,11 +2030,11 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell" || str == "\\$changed") { if (GetSize(children) != 1) - log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n", + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) - log_file_error(filename, location.first_line, "System function %s is only allowed in clocked blocks.\n", + log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", RTLIL::unescape_id(str).c_str()); AstNode *present = children.at(0)->clone(); @@ -2729,13 +2072,13 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$clog2") { if (children.size() != 1) - log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n", + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *buf = children[0]->clone(); while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (buf->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); RTLIL::Const arg_value = buf->bitsAsConst(); if (arg_value.as_bool()) @@ -2754,11 +2097,11 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$size" || str == "\\$bits") { if (str == "\\$bits" && children.size() != 1) - log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n", + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); if (str == "\\$size" && children.size() != 1 && children.size() != 2) - log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 2.\n", + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); int dim = 1; @@ -2782,7 +2125,7 @@ skip_dynamic_range_lvalue_expansion:; if (id_ast == NULL && current_scope.count(buf->str)) id_ast = current_scope.at(buf->str); if (!id_ast) - log_file_error(filename, location.first_line, "Failed to resolve identifier %s for width detection!\n", buf->str.c_str()); + log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", buf->str.c_str()); if (id_ast->type == AST_MEMORY) { // We got here only if the argument is a memory // Otherwise $size() and $bits() return the expression width @@ -2790,15 +2133,15 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$bits") { if (mem_range->type == AST_RANGE) { if (!mem_range->range_valid) - log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", buf->str.c_str()); + log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str()); mem_depth = mem_range->range_left - mem_range->range_right + 1; } else - log_file_error(filename, location.first_line, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str()); + log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str()); } else { // $size() if (mem_range->type == AST_RANGE) { if (!mem_range->range_valid) - log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", buf->str.c_str()); + log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str()); int dims; if (id_ast->multirange_dimensions.empty()) dims = 1; @@ -2809,9 +2152,9 @@ skip_dynamic_range_lvalue_expansion:; else if (dim <= dims) { width_hint = id_ast->multirange_dimensions[2*dim-1]; } else if ((dim > dims+1) || (dim < 0)) - log_file_error(filename, location.first_line, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim, buf->str.c_str(), dims+1); + log_file_error(filename, linenum, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim, buf->str.c_str(), dims+1); } else - log_file_error(filename, location.first_line, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str()); + log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str()); } } } @@ -2832,18 +2175,18 @@ skip_dynamic_range_lvalue_expansion:; if (func_with_two_arguments) { if (children.size() != 2) - log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 2.\n", + log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); } else { if (children.size() != 1) - log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n", + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); } if (children.size() >= 1) { while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[0]->isConst()) - log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant argument.\n", + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; @@ -2854,7 +2197,7 @@ skip_dynamic_range_lvalue_expansion:; if (children.size() >= 2) { while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[1]->isConst()) - log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant argument.\n", + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; @@ -2893,17 +2236,6 @@ skip_dynamic_range_lvalue_expansion:; goto apply_newNode; } - if (str == "\\$sformatf") { - AstNode *node_string = children[0]; - while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } - if (node_string->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str()); - std::string sformat = node_string->bitsAsConst().decode_string(); - std::string sout = process_format_str(sformat, 1, stage, width_hint, sign_hint); - newNode = AstNode::mkconst_str(sout); - goto apply_newNode; - } - if (current_scope.count(str) != 0 && current_scope[str]->type == AST_DPI_FUNCTION) { AstNode *dpi_decl = current_scope[str]; @@ -2918,14 +2250,14 @@ skip_dynamic_range_lvalue_expansion:; for (int i = 2; i < GetSize(dpi_decl->children); i++) { if (i-2 >= GetSize(children)) - log_file_error(filename, location.first_line, "Insufficient number of arguments in DPI function call.\n"); + log_file_error(filename, linenum, "Insufficient number of arguments in DPI function call.\n"); argtypes.push_back(RTLIL::unescape_id(dpi_decl->children.at(i)->str)); args.push_back(children.at(i-2)->clone()); while (args.back()->simplify(true, false, false, stage, -1, false, true)) { } if (args.back()->type != AST_CONSTANT && args.back()->type != AST_REALVALUE) - log_file_error(filename, location.first_line, "Failed to evaluate DPI function with non-constant argument.\n"); + log_file_error(filename, linenum, "Failed to evaluate DPI function with non-constant argument.\n"); } newNode = dpi_call(rtype, fname, argtypes, args); @@ -2937,7 +2269,7 @@ skip_dynamic_range_lvalue_expansion:; } if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION) - log_file_error(filename, location.first_line, "Can't resolve function name `%s'.\n", str.c_str()); + log_file_error(filename, linenum, "Can't resolve function name `%s'.\n", str.c_str()); } if (type == AST_TCALL) @@ -2945,26 +2277,26 @@ skip_dynamic_range_lvalue_expansion:; if (str == "$finish" || str == "$stop") { if (!current_always || current_always->type != AST_INITIAL) - log_file_error(filename, location.first_line, "System task `%s' outside initial block is unsupported.\n", str.c_str()); + log_file_error(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str()); - log_file_error(filename, location.first_line, "System task `%s' executed.\n", str.c_str()); + log_file_error(filename, linenum, "System task `%s' executed.\n", str.c_str()); } if (str == "\\$readmemh" || str == "\\$readmemb") { if (GetSize(children) < 2 || GetSize(children) > 4) - log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 2-4.\n", + log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *node_filename = children[0]->clone(); while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_filename->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str()); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str()); AstNode *node_memory = children[1]->clone(); while (node_memory->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY) - log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str()); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str()); int start_addr = -1, finish_addr = -1; @@ -2972,7 +2304,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *node_addr = children[2]->clone(); while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_addr->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str()); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str()); start_addr = int(node_addr->asInt(false)); } @@ -2980,7 +2312,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *node_addr = children[3]->clone(); while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_addr->type != AST_CONSTANT) - log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str()); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str()); finish_addr = int(node_addr->asInt(false)); } @@ -3008,18 +2340,18 @@ skip_dynamic_range_lvalue_expansion:; } if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK) - log_file_error(filename, location.first_line, "Can't resolve task name `%s'.\n", str.c_str()); + log_file_error(filename, linenum, "Can't resolve task name `%s'.\n", str.c_str()); } AstNode *decl = current_scope[str]; std::stringstream sstr; - sstr << "$func$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++) << "$"; + sstr << "$func$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++) << "$"; std::string prefix = sstr.str(); bool recommend_const_eval = false; bool require_const_eval = in_param ? false : has_const_only_constructs(recommend_const_eval); - if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count(ID::via_celltype)) + if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count("\\via_celltype")) { bool all_args_const = true; for (auto child : children) { @@ -3036,9 +2368,9 @@ skip_dynamic_range_lvalue_expansion:; } if (in_param) - log_file_error(filename, location.first_line, "Non-constant function call in constant expression.\n"); + log_file_error(filename, linenum, "Non-constant function call in constant expression.\n"); if (require_const_eval) - log_file_error(filename, location.first_line, "Function %s can only be called with constant arguments.\n", str.c_str()); + log_file_error(filename, linenum, "Function %s can only be called with constant arguments.\n", str.c_str()); } size_t arg_count = 0; @@ -3078,9 +2410,9 @@ skip_dynamic_range_lvalue_expansion:; goto replace_fcall_with_id; } - if (decl->attributes.count(ID::via_celltype)) + if (decl->attributes.count("\\via_celltype")) { - std::string celltype = decl->attributes.at(ID::via_celltype)->asAttrConst().decode_string(); + std::string celltype = decl->attributes.at("\\via_celltype")->asAttrConst().decode_string(); std::string outport = str; if (celltype.find(' ') != std::string::npos) { @@ -3142,7 +2474,7 @@ skip_dynamic_range_lvalue_expansion:; } for (auto child : decl->children) - if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_ENUM_ITEM) + if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM) { AstNode *wire = nullptr; @@ -3160,7 +2492,7 @@ skip_dynamic_range_lvalue_expansion:; goto tcall_incompatible_wires; } else { tcall_incompatible_wires: - log_file_error(filename, location.first_line, "Incompatible re-declaration of wire %s.\n", child->str.c_str()); + log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", child->str.c_str()); } } } @@ -3172,10 +2504,7 @@ skip_dynamic_range_lvalue_expansion:; wire->is_input = false; wire->is_output = false; wire->is_reg = true; - wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false); - if (child->type == AST_ENUM_ITEM) - wire->attributes[ID::enum_base_type] = child->attributes[ID::enum_base_type]; - + wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); wire_cache[child->str] = wire; current_ast_mod->children.push_back(wire); @@ -3251,7 +2580,7 @@ replace_fcall_later:; switch (type) { case AST_IDENTIFIER: - if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM || current_scope[str]->type == AST_ENUM_ITEM)) { + if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) { if (current_scope[str]->children[0]->type == AST_CONSTANT) { if (children.size() != 0 && children[0]->type == AST_RANGE && children[0]->range_valid) { std::vector data; @@ -3406,7 +2735,6 @@ replace_fcall_later:; } } break; - if (0) { case AST_SELFSZ: const_func = RTLIL::const_pos; } if (0) { case AST_POS: const_func = RTLIL::const_pos; } if (0) { case AST_NEG: const_func = RTLIL::const_neg; } if (children[0]->type == AST_CONSTANT) { @@ -3415,10 +2743,10 @@ replace_fcall_later:; } else if (children[0]->isConst()) { newNode = new AstNode(AST_REALVALUE); - if (type == AST_NEG) - newNode->realvalue = -children[0]->asReal(sign_hint); - else + if (type == AST_POS) newNode->realvalue = +children[0]->asReal(sign_hint); + else + newNode->realvalue = -children[0]->asReal(sign_hint); } break; case AST_TERNARY: @@ -3515,7 +2843,7 @@ replace_fcall_later:; // newNode->dumpAst(stderr, "+ "); log_assert(newNode != NULL); newNode->filename = filename; - newNode->location = location; + newNode->linenum = linenum; newNode->cloneInto(this); delete newNode; did_something = true; @@ -3551,20 +2879,10 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m std::ifstream f; f.open(mem_filename.c_str()); - if (f.fail()) { -#ifdef _WIN32 - char slash = '\\'; -#else - char slash = '/'; -#endif - std::string path = filename.substr(0, filename.find_last_of(slash)+1); - f.open(path + mem_filename.c_str()); - yosys_input_files.insert(path + mem_filename); - } else { - yosys_input_files.insert(mem_filename); - } - if (f.fail() || GetSize(mem_filename) == 0) - log_file_error(filename, location.first_line, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str()); + yosys_input_files.insert(mem_filename); + + if (f.fail()) + log_file_error(filename, linenum, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str()); log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid); int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right; @@ -3610,7 +2928,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m char *endptr; cursor = strtol(nptr, &endptr, 16); if (!*nptr || *endptr) - log_file_error(filename, location.first_line, "Can not parse address `%s` for %s.\n", nptr, str.c_str()); + log_file_error(filename, linenum, "Can not parse address `%s` for %s.\n", nptr, str.c_str()); continue; } @@ -3691,7 +3009,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma for (size_t i = 0; i < children.size(); i++) { AstNode *child = children[i]; if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || - child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF || child->type == AST_ENUM_ITEM) { + child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) { if (backup_name_map.size() == 0) backup_name_map = name_map; std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix; @@ -3710,27 +3028,6 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma child->str = new_name; current_scope[new_name] = child; } - if (child->type == AST_ENUM){ - current_scope[child->str] = child; - for (auto enode : child->children){ - log_assert(enode->type == AST_ENUM_ITEM); - if (backup_name_map.size() == 0) - backup_name_map = name_map; - std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix; - size_t pos = enode->str.rfind('.'); - if (pos == std::string::npos) - pos = enode->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0; - else - pos = pos + 1; - new_name = enode->str.substr(0, pos) + new_name + enode->str.substr(pos); - if (new_name[0] != '$' && new_name[0] != '\\') - new_name = prefix[0] + new_name; - name_map[enode->str] = new_name; - - enode->str = new_name; - current_scope[new_name] = enode; - } - } } for (size_t i = 0; i < children.size(); i++) { @@ -3785,7 +3082,7 @@ static void mark_memories_assign_lhs_complex(dict> & if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) { AstNode *mem = that->id2ast; if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_CMPLX_LHS)) - mem2reg_places[mem].insert(stringf("%s:%d", that->filename.c_str(), that->location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", that->filename.c_str(), that->linenum)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CMPLX_LHS; } } @@ -3813,14 +3110,14 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg // activate mem2reg if this is assigned in an async proc if (flags & AstNode::MEM2REG_FL_ASYNC) { if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC)) - mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC; } // remember if this is assigned blocking (=) if (type == AST_ASSIGN_EQ) { if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1)) - mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum)); proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1; } @@ -3837,11 +3134,11 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg // remember where this is if (flags & MEM2REG_FL_INIT) { if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT)) - mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT; } else { if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE)) - mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE; } } @@ -3855,16 +3152,16 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg // flag if used after blocking assignment (in same proc) if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) { - mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2; } } - // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg' or 'logic' - if (type == AST_MEMORY && (get_bool_attribute(ID::mem2reg) || (flags & AstNode::MEM2REG_FL_ALL) || !(is_reg || is_logic))) + // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg' + if (type == AST_MEMORY && (get_bool_attribute("\\mem2reg") || (flags & AstNode::MEM2REG_FL_ALL) || !is_reg)) mem2reg_candidates[this] |= AstNode::MEM2REG_FL_FORCED; - if (type == AST_MODULE && get_bool_attribute(ID::mem2reg)) + if (type == AST_MODULE && get_bool_attribute("\\mem2reg")) children_flags |= AstNode::MEM2REG_FL_ALL; dict *proc_flags_p = NULL; @@ -3924,7 +3221,7 @@ bool AstNode::mem2reg_check(pool &mem2reg_set) return false; if (children.empty() || children[0]->type != AST_RANGE || GetSize(children[0]->children) != 1) - log_file_error(filename, location.first_line, "Invalid array access.\n"); + log_file_error(filename, linenum, "Invalid array access.\n"); return true; } @@ -4016,7 +3313,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, children[0]->children[0]->children[0]->type != AST_CONSTANT) { std::stringstream sstr; - sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << location.first_line << "$" << (autoidx++); + sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++); std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA"; int mem_width, mem_size, addr_bits; @@ -4027,7 +3324,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, wire_addr->str = id_addr; wire_addr->is_reg = true; wire_addr->was_checked = true; - wire_addr->attributes[ID::nosync] = AstNode::mkconst_int(1, false); + wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_addr); while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } @@ -4036,7 +3333,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, wire_data->is_reg = true; wire_data->was_checked = true; wire_data->is_signed = mem_signed; - wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false); + wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_data); while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } @@ -4095,7 +3392,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, else { std::stringstream sstr; - sstr << "$mem2reg_rd$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++); + sstr << "$mem2reg_rd$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++); std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA"; int mem_width, mem_size, addr_bits; @@ -4107,7 +3404,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, wire_addr->is_reg = true; wire_addr->was_checked = true; if (block) - wire_addr->attributes[ID::nosync] = AstNode::mkconst_int(1, false); + wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_addr); while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } @@ -4117,7 +3414,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, wire_data->was_checked = true; wire_data->is_signed = mem_signed; if (block) - wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false); + wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_data); while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } @@ -4207,60 +3504,6 @@ void AstNode::meminfo(int &mem_width, int &mem_size, int &addr_bits) addr_bits++; } -bool AstNode::detect_latch(const std::string &var) -{ - switch (type) - { - case AST_ALWAYS: - for (auto &c : children) - { - switch (c->type) - { - case AST_POSEDGE: - case AST_NEGEDGE: - return false; - case AST_BLOCK: - if (!c->detect_latch(var)) - return false; - break; - default: - log_abort(); - } - } - return true; - case AST_BLOCK: - for (auto &c : children) - if (!c->detect_latch(var)) - return false; - return true; - case AST_CASE: - { - bool r = true; - for (auto &c : children) { - if (c->type == AST_COND) { - if (c->children.at(1)->detect_latch(var)) - return true; - r = false; - } - if (c->type == AST_DEFAULT) { - if (c->children.at(0)->detect_latch(var)) - return true; - r = false; - } - } - return r; - } - case AST_ASSIGN_EQ: - case AST_ASSIGN_LE: - if (children.at(0)->type == AST_IDENTIFIER && - children.at(0)->children.empty() && children.at(0)->str == var) - return false; - return true; - default: - return true; - } -} - bool AstNode::has_const_only_constructs(bool &recommend_const_eval) { if (type == AST_FOR) @@ -4293,13 +3536,13 @@ void AstNode::replace_variables(std::map &varia int offset = variables.at(str).offset, width = variables.at(str).val.bits.size(); if (!children.empty()) { if (children.size() != 1 || children.at(0)->type != AST_RANGE) - log_file_error(filename, location.first_line, "Memory access in constant function is not supported\n%s:%d.%d-%d.%d: ...called from here.\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n", + fcall->filename.c_str(), fcall->linenum); children.at(0)->replace_variables(variables, fcall); while (simplify(true, false, false, 1, -1, false, true)) { } if (!children.at(0)->range_valid) - log_file_error(filename, location.first_line, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); offset = min(children.at(0)->range_left, children.at(0)->range_right); width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width); } @@ -4330,8 +3573,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) { while (child->simplify(true, false, false, 1, -1, false, true)) { } if (!child->range_valid) - log_file_error(child->filename, child->location.first_line, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n", - child->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n", + child->str.c_str(), fcall->filename.c_str(), fcall->linenum); variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1); variables[child->str].offset = min(child->range_left, child->range_right); variables[child->str].is_signed = child->is_signed; @@ -4370,24 +3613,24 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) continue; if (stmt->children.at(1)->type != AST_CONSTANT) - log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here. X\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n", + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->type != AST_IDENTIFIER) - log_file_error(stmt->filename, stmt->location.first_line, "Unsupported composite left hand side in constant function\n%s:%d.%d-%d.%d: ... called from here.\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); if (!variables.count(stmt->children.at(0)->str)) - log_file_error(stmt->filename, stmt->location.first_line, "Assignment to non-local variable in constant function\n%s:%d.%d-%d.%d: ... called from here.\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->children.empty()) { variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size()); } else { AstNode *range = stmt->children.at(0)->children.at(0); if (!range->range_valid) - log_file_error(range->filename, range->location.first_line, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); int offset = min(range->range_left, range->range_right); int width = std::abs(range->range_left - range->range_right) + 1; varinfo_t &v = variables[stmt->children.at(0)->str]; @@ -4418,8 +3661,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (cond->simplify(true, false, false, 1, -1, false, true)) { } if (cond->type != AST_CONSTANT) - log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); if (cond->asBool()) { block->children.insert(block->children.begin(), stmt->children.at(1)->clone()); @@ -4439,8 +3682,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (num->simplify(true, false, false, 1, -1, false, true)) { } if (num->type != AST_CONSTANT) - log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); block->children.erase(block->children.begin()); for (int i = 0; i < num->bitsAsConst().as_int(); i++) @@ -4477,8 +3720,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (cond->simplify(true, false, false, 1, -1, false, true)) { } if (cond->type != AST_CONSTANT) - log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); found_match = cond->asBool(); delete cond; @@ -4507,8 +3750,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) continue; } - log_file_error(stmt->filename, stmt->location.first_line, "Unsupported language construct in constant function\n%s:%d.%d-%d.%d: ... called from here.\n", - fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); + log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); log_abort(); } @@ -4523,32 +3766,4 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed); } -void AstNode::allocateDefaultEnumValues() -{ - log_assert(type==AST_ENUM); - int last_enum_int = -1; - for (auto node : children) { - log_assert(node->type==AST_ENUM_ITEM); - node->attributes[ID::enum_base_type] = mkconst_str(str); - for (size_t i = 0; i < node->children.size(); i++) { - switch (node->children[i]->type) { - case AST_NONE: - // replace with auto-incremented constant - delete node->children[i]; - node->children[i] = AstNode::mkconst_int(++last_enum_int, true); - break; - case AST_CONSTANT: - // explicit constant (or folded expression) - // TODO: can't extend 'x or 'z item - last_enum_int = node->children[i]->integer; - break; - default: - // ignore ranges - break; - } - // TODO: range check - } - } -} - YOSYS_NAMESPACE_END diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 9ae3fac2c0e..cab210605e3 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -176,7 +176,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool if (!strcmp(cmd, ".blackbox")) { - module->attributes[ID::blackbox] = RTLIL::Const(1); + module->attributes["\\blackbox"] = RTLIL::Const(1); continue; } @@ -215,17 +215,17 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool vector remove_cells; for (auto cell : module->cells()) - if (cell->type == ID($lut) && cell->getParam(ID::LUT) == buffer_lut) { - module->connect(cell->getPort(ID::Y), cell->getPort(ID::A)); + if (cell->type == "$lut" && cell->getParam("\\LUT") == buffer_lut) { + module->connect(cell->getPort("\\Y"), cell->getPort("\\A")); remove_cells.push_back(cell); } for (auto cell : remove_cells) module->remove(cell); - Wire *true_wire = module->wire(ID($true)); - Wire *false_wire = module->wire(ID($false)); - Wire *undef_wire = module->wire(ID($undef)); + Wire *true_wire = module->wire("$true"); + Wire *false_wire = module->wire("$false"); + Wire *undef_wire = module->wire("$undef"); if (true_wire != nullptr) module->rename(true_wire, stringf("$true$%d", ++blif_maxnum)); @@ -337,7 +337,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool } if (init != nullptr && (init[0] == '0' || init[0] == '1')) - blif_wire(q)->attributes[ID::init] = Const(init[0] == '1' ? 1 : 0, 1); + blif_wire(q)->attributes["\\init"] = Const(init[0] == '1' ? 1 : 0, 1); if (clock == nullptr) goto no_latch_clock; @@ -356,8 +356,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool cell = module->addFf(NEW_ID, blif_wire(d), blif_wire(q)); } else { cell = module->addCell(NEW_ID, dff_name); - cell->setPort(ID::D, blif_wire(d)); - cell->setPort(ID::Q, blif_wire(q)); + cell->setPort("\\D", blif_wire(d)); + cell->setPort("\\Q", blif_wire(q)); } } @@ -476,7 +476,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool finished_parsing_constval: if (state == RTLIL::State::Sa) state = RTLIL::State::S0; - if (output_sig.as_wire()->name == ID($undef)) + if (output_sig.as_wire()->name == "$undef") state = RTLIL::State::Sx; module->connect(RTLIL::SigSig(output_sig, state)); goto continue_without_read; @@ -484,23 +484,23 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool if (sop_mode) { - sopcell = module->addCell(NEW_ID, ID($sop)); - sopcell->parameters[ID::WIDTH] = RTLIL::Const(input_sig.size()); - sopcell->parameters[ID::DEPTH] = 0; - sopcell->parameters[ID::TABLE] = RTLIL::Const(); - sopcell->setPort(ID::A, input_sig); - sopcell->setPort(ID::Y, output_sig); + sopcell = module->addCell(NEW_ID, "$sop"); + sopcell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size()); + sopcell->parameters["\\DEPTH"] = 0; + sopcell->parameters["\\TABLE"] = RTLIL::Const(); + sopcell->setPort("\\A", input_sig); + sopcell->setPort("\\Y", output_sig); sopmode = -1; lastcell = sopcell; } else { - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($lut)); - cell->parameters[ID::WIDTH] = RTLIL::Const(input_sig.size()); - cell->parameters[ID::LUT] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size()); - cell->setPort(ID::A, input_sig); - cell->setPort(ID::Y, output_sig); - lutptr = &cell->parameters.at(ID::LUT); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut"); + cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size()); + cell->parameters["\\LUT"] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size()); + cell->setPort("\\A", input_sig); + cell->setPort("\\Y", output_sig); + lutptr = &cell->parameters.at("\\LUT"); lut_default_state = RTLIL::State::Sx; lastcell = cell; } @@ -523,32 +523,32 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool if (sopcell) { - log_assert(sopcell->parameters[ID::WIDTH].as_int() == input_len); - sopcell->parameters[ID::DEPTH] = sopcell->parameters[ID::DEPTH].as_int() + 1; + log_assert(sopcell->parameters["\\WIDTH"].as_int() == input_len); + sopcell->parameters["\\DEPTH"] = sopcell->parameters["\\DEPTH"].as_int() + 1; for (int i = 0; i < input_len; i++) switch (input[i]) { case '0': - sopcell->parameters[ID::TABLE].bits.push_back(State::S1); - sopcell->parameters[ID::TABLE].bits.push_back(State::S0); + sopcell->parameters["\\TABLE"].bits.push_back(State::S1); + sopcell->parameters["\\TABLE"].bits.push_back(State::S0); break; case '1': - sopcell->parameters[ID::TABLE].bits.push_back(State::S0); - sopcell->parameters[ID::TABLE].bits.push_back(State::S1); + sopcell->parameters["\\TABLE"].bits.push_back(State::S0); + sopcell->parameters["\\TABLE"].bits.push_back(State::S1); break; default: - sopcell->parameters[ID::TABLE].bits.push_back(State::S0); - sopcell->parameters[ID::TABLE].bits.push_back(State::S0); + sopcell->parameters["\\TABLE"].bits.push_back(State::S0); + sopcell->parameters["\\TABLE"].bits.push_back(State::S0); break; } if (sopmode == -1) { sopmode = (*output == '1'); if (!sopmode) { - SigSpec outnet = sopcell->getPort(ID::Y); + SigSpec outnet = sopcell->getPort("\\Y"); SigSpec tempnet = module->addWire(NEW_ID); module->addNotGate(NEW_ID, tempnet, outnet); - sopcell->setPort(ID::Y, tempnet); + sopcell->setPort("\\Y", tempnet); } } else log_assert(sopmode == (*output == '1')); @@ -586,7 +586,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool struct BlifFrontend : public Frontend { BlifFrontend() : Frontend("blif", "read BLIF file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -602,7 +602,7 @@ struct BlifFrontend : public Frontend { log(" multi-bit port 'name'.\n"); log("\n"); } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool sop_mode = false; bool wideports = false; diff --git a/frontends/ilang/ilang_frontend.cc b/frontends/ilang/ilang_frontend.cc index 973e62f2ce1..30d9ff79d9e 100644 --- a/frontends/ilang/ilang_frontend.cc +++ b/frontends/ilang/ilang_frontend.cc @@ -35,7 +35,7 @@ YOSYS_NAMESPACE_BEGIN struct IlangFrontend : public Frontend { IlangFrontend() : Frontend("ilang", "read modules from ilang file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -56,7 +56,7 @@ struct IlangFrontend : public Frontend { log(" only create empty blackbox modules\n"); log("\n"); } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { ILANG_FRONTEND::flag_nooverwrite = false; ILANG_FRONTEND::flag_overwrite = false; diff --git a/frontends/ilang/ilang_lexer.l b/frontends/ilang/ilang_lexer.l index 3362ed641a5..4fd0ae855a5 100644 --- a/frontends/ilang/ilang_lexer.l +++ b/frontends/ilang/ilang_lexer.l @@ -29,7 +29,6 @@ #pragma clang diagnostic ignored "-Wdeprecated-register" #endif -#include #include "frontends/ilang/ilang_frontend.h" #include "ilang_parser.tab.hh" @@ -89,18 +88,7 @@ USING_YOSYS_NAMESPACE "."[0-9]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; } [0-9]+'[01xzm-]* { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_VALUE; } --?[0-9]+ { - char *end = nullptr; - errno = 0; - long value = strtol(yytext, &end, 10); - log_assert(end == yytext + strlen(yytext)); - if (errno == ERANGE) - return TOK_INVALID; // literal out of range of long - if (value < INT_MIN || value > INT_MAX) - return TOK_INVALID; // literal out of range of int (relevant mostly for LP64 platforms) - rtlil_frontend_ilang_yylval.integer = value; - return TOK_INT; -} +-?[0-9]+ { rtlil_frontend_ilang_yylval.integer = atoi(yytext); return TOK_INT; } \" { BEGIN(STRING); } \\. { yymore(); } @@ -148,3 +136,4 @@ USING_YOSYS_NAMESPACE void *rtlil_frontend_ilang_avoid_input_warnings() { return (void*)&yyinput; } + diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index 879ef4af94c..4e0b62edd94 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -107,16 +107,16 @@ module: delete_current_module = false; if (current_design->has($2)) { RTLIL::Module *existing_mod = current_design->module($2); - if (!flag_overwrite && (flag_lib || (attrbuf.count(ID::blackbox) && attrbuf.at(ID::blackbox).as_bool()))) { + if (!flag_overwrite && (flag_lib || (attrbuf.count("\\blackbox") && attrbuf.at("\\blackbox").as_bool()))) { log("Ignoring blackbox re-definition of module %s.\n", $2); delete_current_module = true; - } else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) { + } else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) { rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str()); } else if (flag_nooverwrite) { log("Ignoring re-definition of module %s.\n", $2); delete_current_module = true; } else { - log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", $2); + log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "", $2); current_design->remove(existing_mod); } } @@ -143,18 +143,11 @@ module_body: /* empty */; module_stmt: - param_stmt | param_defval_stmt | attr_stmt | wire_stmt | memory_stmt | cell_stmt | proc_stmt | conn_stmt; + param_stmt | attr_stmt | wire_stmt | memory_stmt | cell_stmt | proc_stmt | conn_stmt; param_stmt: TOK_PARAMETER TOK_ID EOL { - current_module->avail_parameters($2); - free($2); - }; - -param_defval_stmt: - TOK_PARAMETER TOK_ID constant EOL { - current_module->avail_parameters($2); - current_module->parameter_default_values[$2] = *$3; + current_module->avail_parameters.insert($2); free($2); }; @@ -176,7 +169,7 @@ wire_stmt: current_wire->attributes = attrbuf; attrbuf.clear(); } wire_options TOK_ID EOL { - if (current_module->wire($4) != nullptr) + if (current_module->wires_.count($4) != 0) rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of wire %s.", $4).c_str()); current_module->rename(current_wire, $4); free($4); @@ -186,15 +179,9 @@ wire_options: wire_options TOK_WIDTH TOK_INT { current_wire->width = $3; } | - wire_options TOK_WIDTH TOK_INVALID { - rtlil_frontend_ilang_yyerror("ilang error: invalid wire width"); - } | wire_options TOK_UPTO { current_wire->upto = true; } | - wire_options TOK_SIGNED { - current_wire->is_signed = true; - } | wire_options TOK_OFFSET TOK_INT { current_wire->start_offset = $3; } | @@ -242,7 +229,7 @@ memory_options: cell_stmt: TOK_CELL TOK_ID TOK_ID EOL { - if (current_module->cell($3) != nullptr) + if (current_module->cells_.count($3) != 0) rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell %s.", $3).c_str()); current_cell = current_module->addCell($3, $2); current_cell->attributes = attrbuf; @@ -437,9 +424,9 @@ sigspec: delete $1; } | TOK_ID { - if (current_module->wire($1) == nullptr) + if (current_module->wires_.count($1) == 0) rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str()); - $$ = new RTLIL::SigSpec(current_module->wire($1)); + $$ = new RTLIL::SigSpec(current_module->wires_[$1]); free($1); } | sigspec '[' TOK_INT ']' { diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index 1b34aaf3af7..7aceffbfce4 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -309,12 +309,6 @@ void json_import(Design *design, string &modname, JsonNode *node) port_wire->upto = val->data_number != 0; } - if (port_node->data_dict.count("signed") != 0) { - JsonNode *val = port_node->data_dict.at("signed"); - if (val->type == 'N') - port_wire->is_signed = val->data_number != 0; - } - if (port_node->data_dict.count("offset") != 0) { JsonNode *val = port_node->data_dict.at("offset"); if (val->type == 'N') @@ -535,7 +529,7 @@ void json_import(Design *design, string &modname, JsonNode *node) struct JsonFrontend : public Frontend { JsonFrontend() : Frontend("json", "read JSON file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -545,7 +539,7 @@ struct JsonFrontend : public Frontend { log("for a description of the file format.\n"); log("\n"); } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing JSON frontend.\n"); @@ -579,3 +573,4 @@ struct JsonFrontend : public Frontend { } JsonFrontend; YOSYS_NAMESPACE_END + diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index f77d7da5601..14de95e07cb 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -55,37 +55,37 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *& static RTLIL::SigSpec create_inv_cell(RTLIL::Module *module, RTLIL::SigSpec A) { - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_)); - cell->setPort(ID::A, A); - cell->setPort(ID::Y, module->addWire(NEW_ID)); - return cell->getPort(ID::Y); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$_NOT_"); + cell->setPort("\\A", A); + cell->setPort("\\Y", module->addWire(NEW_ID)); + return cell->getPort("\\Y"); } static RTLIL::SigSpec create_xor_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B) { - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_XOR_)); - cell->setPort(ID::A, A); - cell->setPort(ID::B, B); - cell->setPort(ID::Y, module->addWire(NEW_ID)); - return cell->getPort(ID::Y); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$_XOR_"); + cell->setPort("\\A", A); + cell->setPort("\\B", B); + cell->setPort("\\Y", module->addWire(NEW_ID)); + return cell->getPort("\\Y"); } static RTLIL::SigSpec create_and_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B) { - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_AND_)); - cell->setPort(ID::A, A); - cell->setPort(ID::B, B); - cell->setPort(ID::Y, module->addWire(NEW_ID)); - return cell->getPort(ID::Y); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$_AND_"); + cell->setPort("\\A", A); + cell->setPort("\\B", B); + cell->setPort("\\Y", module->addWire(NEW_ID)); + return cell->getPort("\\Y"); } static RTLIL::SigSpec create_or_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B) { - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_OR_)); - cell->setPort(ID::A, A); - cell->setPort(ID::B, B); - cell->setPort(ID::Y, module->addWire(NEW_ID)); - return cell->getPort(ID::Y); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$_OR_"); + cell->setPort("\\A", A); + cell->setPort("\\B", B); + cell->setPort("\\Y", module->addWire(NEW_ID)); + return cell->getPort("\\Y"); } static bool parse_func_reduce(RTLIL::Module *module, std::vector &stack, token_t next_token) @@ -241,32 +241,32 @@ static void create_ff(RTLIL::Module *module, LibertyAst *node) rerun_invert_rollback = false; for (auto &it : module->cells_) { - if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == clk_sig) { - clk_sig = it.second->getPort(ID::A); + if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == clk_sig) { + clk_sig = it.second->getPort("\\A"); clk_polarity = !clk_polarity; rerun_invert_rollback = true; } - if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == clear_sig) { - clear_sig = it.second->getPort(ID::A); + if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == clear_sig) { + clear_sig = it.second->getPort("\\A"); clear_polarity = !clear_polarity; rerun_invert_rollback = true; } - if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == preset_sig) { - preset_sig = it.second->getPort(ID::A); + if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == preset_sig) { + preset_sig = it.second->getPort("\\A"); preset_polarity = !preset_polarity; rerun_invert_rollback = true; } } } - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_)); - cell->setPort(ID::A, iq_sig); - cell->setPort(ID::Y, iqn_sig); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$_NOT_"); + cell->setPort("\\A", iq_sig); + cell->setPort("\\Y", iqn_sig); cell = module->addCell(NEW_ID, ""); - cell->setPort(ID::D, data_sig); - cell->setPort(ID::Q, iq_sig); - cell->setPort(ID::C, clk_sig); + cell->setPort("\\D", data_sig); + cell->setPort("\\Q", iq_sig); + cell->setPort("\\C", clk_sig); if (clear_sig.size() == 0 && preset_sig.size() == 0) { cell->type = stringf("$_DFF_%c_", clk_polarity ? 'P' : 'N'); @@ -274,18 +274,18 @@ static void create_ff(RTLIL::Module *module, LibertyAst *node) if (clear_sig.size() == 1 && preset_sig.size() == 0) { cell->type = stringf("$_DFF_%c%c0_", clk_polarity ? 'P' : 'N', clear_polarity ? 'P' : 'N'); - cell->setPort(ID::R, clear_sig); + cell->setPort("\\R", clear_sig); } if (clear_sig.size() == 0 && preset_sig.size() == 1) { cell->type = stringf("$_DFF_%c%c1_", clk_polarity ? 'P' : 'N', preset_polarity ? 'P' : 'N'); - cell->setPort(ID::R, preset_sig); + cell->setPort("\\R", preset_sig); } if (clear_sig.size() == 1 && preset_sig.size() == 1) { cell->type = stringf("$_DFFSR_%c%c%c_", clk_polarity ? 'P' : 'N', preset_polarity ? 'P' : 'N', clear_polarity ? 'P' : 'N'); - cell->setPort(ID::S, preset_sig); - cell->setPort(ID::R, clear_sig); + cell->setPort("\\S", preset_sig); + cell->setPort("\\R", clear_sig); } log_assert(!cell->type.empty()); @@ -324,27 +324,27 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno rerun_invert_rollback = false; for (auto &it : module->cells_) { - if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == enable_sig) { - enable_sig = it.second->getPort(ID::A); + if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == enable_sig) { + enable_sig = it.second->getPort("\\A"); enable_polarity = !enable_polarity; rerun_invert_rollback = true; } - if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == clear_sig) { - clear_sig = it.second->getPort(ID::A); + if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == clear_sig) { + clear_sig = it.second->getPort("\\A"); clear_polarity = !clear_polarity; rerun_invert_rollback = true; } - if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == preset_sig) { - preset_sig = it.second->getPort(ID::A); + if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == preset_sig) { + preset_sig = it.second->getPort("\\A"); preset_polarity = !preset_polarity; rerun_invert_rollback = true; } } } - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_)); - cell->setPort(ID::A, iq_sig); - cell->setPort(ID::Y, iqn_sig); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$_NOT_"); + cell->setPort("\\A", iq_sig); + cell->setPort("\\Y", iqn_sig); if (clear_sig.size() == 1) { @@ -353,25 +353,25 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno if (clear_polarity == true || clear_polarity != enable_polarity) { - RTLIL::Cell *inv = module->addCell(NEW_ID, ID($_NOT_)); - inv->setPort(ID::A, clear_sig); - inv->setPort(ID::Y, module->addWire(NEW_ID)); + RTLIL::Cell *inv = module->addCell(NEW_ID, "$_NOT_"); + inv->setPort("\\A", clear_sig); + inv->setPort("\\Y", module->addWire(NEW_ID)); if (clear_polarity == true) - clear_negative = inv->getPort(ID::Y); + clear_negative = inv->getPort("\\Y"); if (clear_polarity != enable_polarity) - clear_enable = inv->getPort(ID::Y); + clear_enable = inv->getPort("\\Y"); } - RTLIL::Cell *data_gate = module->addCell(NEW_ID, ID($_AND_)); - data_gate->setPort(ID::A, data_sig); - data_gate->setPort(ID::B, clear_negative); - data_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID)); + RTLIL::Cell *data_gate = module->addCell(NEW_ID, "$_AND_"); + data_gate->setPort("\\A", data_sig); + data_gate->setPort("\\B", clear_negative); + data_gate->setPort("\\Y", data_sig = module->addWire(NEW_ID)); - RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? ID($_OR_) : ID($_AND_)); - enable_gate->setPort(ID::A, enable_sig); - enable_gate->setPort(ID::B, clear_enable); - enable_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID)); + RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? "$_OR_" : "$_AND_"); + enable_gate->setPort("\\A", enable_sig); + enable_gate->setPort("\\B", clear_enable); + enable_gate->setPort("\\Y", data_sig = module->addWire(NEW_ID)); } if (preset_sig.size() == 1) @@ -381,31 +381,31 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno if (preset_polarity == false || preset_polarity != enable_polarity) { - RTLIL::Cell *inv = module->addCell(NEW_ID, ID($_NOT_)); - inv->setPort(ID::A, preset_sig); - inv->setPort(ID::Y, module->addWire(NEW_ID)); + RTLIL::Cell *inv = module->addCell(NEW_ID, "$_NOT_"); + inv->setPort("\\A", preset_sig); + inv->setPort("\\Y", module->addWire(NEW_ID)); if (preset_polarity == false) - preset_positive = inv->getPort(ID::Y); + preset_positive = inv->getPort("\\Y"); if (preset_polarity != enable_polarity) - preset_enable = inv->getPort(ID::Y); + preset_enable = inv->getPort("\\Y"); } - RTLIL::Cell *data_gate = module->addCell(NEW_ID, ID($_OR_)); - data_gate->setPort(ID::A, data_sig); - data_gate->setPort(ID::B, preset_positive); - data_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID)); + RTLIL::Cell *data_gate = module->addCell(NEW_ID, "$_OR_"); + data_gate->setPort("\\A", data_sig); + data_gate->setPort("\\B", preset_positive); + data_gate->setPort("\\Y", data_sig = module->addWire(NEW_ID)); - RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? ID($_OR_) : ID($_AND_)); - enable_gate->setPort(ID::A, enable_sig); - enable_gate->setPort(ID::B, preset_enable); - enable_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID)); + RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? "$_OR_" : "$_AND_"); + enable_gate->setPort("\\A", enable_sig); + enable_gate->setPort("\\B", preset_enable); + enable_gate->setPort("\\Y", data_sig = module->addWire(NEW_ID)); } cell = module->addCell(NEW_ID, stringf("$_DLATCH_%c_", enable_polarity ? 'P' : 'N')); - cell->setPort(ID::D, data_sig); - cell->setPort(ID::Q, iq_sig); - cell->setPort(ID::E, enable_sig); + cell->setPort("\\D", data_sig); + cell->setPort("\\Q", iq_sig); + cell->setPort("\\E", enable_sig); return true; } @@ -453,7 +453,7 @@ void parse_type_map(std::map> &type_map, struct LibertyFrontend : public Frontend { LibertyFrontend() : Frontend("liberty", "read cells from liberty file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -486,7 +486,7 @@ struct LibertyFrontend : public Frontend { log(" set the specified attribute (to the value 1) on all loaded modules\n"); log("\n"); } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_lib = false; bool flag_nooverwrite = false; @@ -550,13 +550,13 @@ struct LibertyFrontend : public Frontend { if (design->has(cell_name)) { Module *existing_mod = design->module(cell_name); - if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) { + if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) { log_error("Re-definition of cell/module %s!\n", log_id(cell_name)); } else if (flag_nooverwrite) { log("Ignoring re-definition of module %s.\n", log_id(cell_name)); continue; } else { - log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", log_id(cell_name)); + log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "", log_id(cell_name)); design->remove(existing_mod); } } @@ -570,7 +570,7 @@ struct LibertyFrontend : public Frontend { module->name = cell_name; if (flag_lib) - module->set_bool_attribute(ID::blackbox); + module->set_bool_attribute("\\blackbox"); for (auto &attr : attributes) module->attributes[attr] = 1; diff --git a/frontends/rpc/Makefile.inc b/frontends/rpc/Makefile.inc index fa1d068f941..9af50509891 100644 --- a/frontends/rpc/Makefile.inc +++ b/frontends/rpc/Makefile.inc @@ -1,3 +1,2 @@ -ifeq ($(DISABLE_SPAWN),0) + OBJS += frontends/rpc/rpc_frontend.o -endif diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index 6d72cbff551..add17c243d2 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -157,7 +157,7 @@ struct RpcServer { struct RpcModule : RTLIL::Module { std::shared_ptr server; - RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, bool /*mayfail*/) override { + RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool /*mayfail*/) YS_OVERRIDE { std::string stripped_name = name.str(); if (stripped_name.compare(0, 9, "$abstract") == 0) stripped_name = stripped_name.substr(9); @@ -216,9 +216,7 @@ struct RpcModule : RTLIL::Module { module.second->name = mangled_name; module.second->design = design; - module.second->attributes.erase(ID::top); - if (!module.second->has_attribute(ID::hdlname)) - module.second->set_string_attribute(ID::hdlname, module.first.str()); + module.second->attributes.erase("\\top"); design->modules_[mangled_name] = module.second; derived_design->modules_.erase(module.first); } @@ -229,7 +227,7 @@ struct RpcModule : RTLIL::Module { return derived_name; } - RTLIL::Module *clone() const override { + RTLIL::Module *clone() const YS_OVERRIDE { RpcModule *new_mod = new RpcModule; new_mod->server = server; cloneInto(new_mod); @@ -250,7 +248,7 @@ struct HandleRpcServer : RpcServer { HandleRpcServer(const std::string &name, HANDLE hsend, HANDLE hrecv) : RpcServer(name), hsend(hsend), hrecv(hrecv) { } - void write(const std::string &data) override { + void write(const std::string &data) YS_OVERRIDE { log_assert(data.length() >= 1 && data.find('\n') == data.length() - 1); ssize_t offset = 0; do { @@ -261,7 +259,7 @@ struct HandleRpcServer : RpcServer { } while(offset < (ssize_t)data.length()); } - std::string read() override { + std::string read() YS_OVERRIDE { std::string data; ssize_t offset = 0; while (data.length() == 0 || data[data.length() - 1] != '\n') { @@ -304,7 +302,7 @@ struct FdRpcServer : RpcServer { log_cmd_error("RPC frontend terminated unexpectedly\n"); } - void write(const std::string &data) override { + void write(const std::string &data) YS_OVERRIDE { log_assert(data.length() >= 1 && data.find('\n') == data.length() - 1); ssize_t offset = 0; do { @@ -316,7 +314,7 @@ struct FdRpcServer : RpcServer { } while(offset < (ssize_t)data.length()); } - std::string read() override { + std::string read() YS_OVERRIDE { std::string data; ssize_t offset = 0; while (data.length() == 0 || data[data.length() - 1] != '\n') { @@ -346,7 +344,7 @@ struct FdRpcServer : RpcServer { // RpcFrontend does not inherit from Frontend since it does not read files. struct RpcFrontend : public Pass { RpcFrontend() : Pass("connect_rpc", "connect to RPC frontend") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -390,7 +388,7 @@ struct RpcFrontend : public Pass { log(" so the response should be the same whenever the same set of parameters\n"); log(" is provided.\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Connecting to RPC frontend.\n"); diff --git a/frontends/verific/README b/frontends/verific/README index c37d7634346..89584f2e855 100644 --- a/frontends/verific/README +++ b/frontends/verific/README @@ -1,11 +1,7 @@ -This directory contains Verific bindings for Yosys. - -Use Symbiotic EDA Suite if you need Yosys+Verifc. -https://www.symbioticeda.com/seda-suite -Contact office@symbioticeda.com for free evaluation -binaries of Symbiotic EDA Suite. +This directory contains Verific bindings for Yosys. +See http://www.verific.com/ for details. Verific Features that should be enabled in your Verific library diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index ccd13e92f7c..843e7b9b4a3 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -149,13 +149,13 @@ RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj) return s; } -void VerificImporter::import_attributes(dict &attributes, DesignObj *obj, Netlist *nl) +void VerificImporter::import_attributes(dict &attributes, DesignObj *obj) { MapIter mi; Att *attr; if (obj->Linefile()) - attributes[ID::src] = stringf("%s:%d", LineFile::GetFileName(obj->Linefile()), LineFile::GetLineNo(obj->Linefile())); + attributes["\\src"] = stringf("%s:%d", LineFile::GetFileName(obj->Linefile()), LineFile::GetLineNo(obj->Linefile())); // FIXME: Parse numeric attributes FOREACH_ATTRIBUTE(obj, mi, attr) { @@ -163,68 +163,6 @@ void VerificImporter::import_attributes(dict &att continue; attributes[RTLIL::escape_id(attr->Key())] = RTLIL::Const(std::string(attr->Value())); } - - if (nl) { - auto type_range = nl->GetTypeRange(obj->Name()); - if (!type_range) - return; - if (!type_range->IsTypeEnum()) - return; - if (nl->IsFromVhdl() && strcmp(type_range->GetTypeName(), "STD_LOGIC") == 0) - return; - auto type_name = type_range->GetTypeName(); - if (!type_name) - return; - attributes.emplace(ID::wiretype, RTLIL::escape_id(type_name)); - - MapIter mi; - const char *k, *v; - FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mi, &k, &v) { - if (nl->IsFromVerilog()) { - // Expect 'b - auto p = strchr(v, '\''); - if (p) { - if (*(p+1) != 'b') - p = nullptr; - else - for (auto q = p+2; *q != '\0'; q++) - if (*q != '0' && *q != '1') { - p = nullptr; - break; - } - } - if (p == nullptr) - log_error("Expected TypeRange value '%s' to be of form 'b.\n", v); - attributes.emplace(stringf("\\enum_value_%s", p+2), RTLIL::escape_id(k)); - } - else if (nl->IsFromVhdl()) { - // Expect "" - auto p = v; - if (p) { - if (*p != '"') - p = nullptr; - else { - auto *q = p+1; - for (; *q != '"'; q++) - if (*q != '0' && *q != '1') { - p = nullptr; - break; - } - if (p && *(q+1) != '\0') - p = nullptr; - } - } - if (p == nullptr) - log_error("Expected TypeRange value '%s' to be of form \"\".\n", v); - auto l = strlen(p); - auto q = (char*)malloc(l+1-2); - strncpy(q, p+1, l-2); - q[l-2] = '\0'; - attributes.emplace(stringf("\\enum_value_%s", q), RTLIL::escape_id(k)); - free(q); - } - } - } } RTLIL::SigSpec VerificImporter::operatorInput(Instance *inst) @@ -601,14 +539,6 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr return true; } - if (inst->Type() == OPER_REDUCE_NAND) { - Wire *tmp = module->addWire(NEW_ID); - cell = module->addReduceAnd(inst_name, IN, tmp, SIGNED); - module->addNot(NEW_ID, tmp, net_map_at(inst->GetOutput())); - import_attributes(cell->attributes, inst); - return true; - } - if (inst->Type() == OPER_REDUCE_OR) { cell = module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); import_attributes(cell->attributes, inst); @@ -800,7 +730,7 @@ void VerificImporter::merge_past_ffs_clock(pool &candidates, SigBi SigSpec dbits; for (auto cell : candidates) { - SigBit bit = sigmap(cell->getPort(ID::D)); + SigBit bit = sigmap(cell->getPort("\\D")); dbits_db[bit].insert(cell); dbits.append(bit); } @@ -826,7 +756,7 @@ void VerificImporter::merge_past_ffs_clock(pool &candidates, SigBi if (verific_verbose) log(" replacing old ff %s on bit %d.\n", log_id(old_ff), i); - SigBit old_q = old_ff->getPort(ID::Q); + SigBit old_q = old_ff->getPort("\\Q"); SigBit new_q = sig_q[i]; sigmap.add(old_q, new_q); @@ -845,8 +775,8 @@ void VerificImporter::merge_past_ffs(pool &candidates) for (auto cell : candidates) { - SigBit clock = cell->getPort(ID::CLK); - bool clock_pol = cell->getParam(ID::CLK_POLARITY).as_bool(); + SigBit clock = cell->getPort("\\CLK"); + bool clock_pol = cell->getParam("\\CLK_POLARITY").as_bool(); database[make_pair(clock, int(clock_pol))].insert(cell); } @@ -884,7 +814,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se if (is_blackbox(nl)) { log("Importing blackbox module %s.\n", RTLIL::id2cstr(module->name)); - module->set_bool_attribute(ID::blackbox); + module->set_bool_attribute("\\blackbox"); } else { log("Importing module %s.\n", RTLIL::id2cstr(module->name)); } @@ -907,7 +837,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log(" importing port %s.\n", port->Name()); RTLIL::Wire *wire = module->addWire(RTLIL::escape_id(port->Name())); - import_attributes(wire->attributes, port, nl); + import_attributes(wire->attributes, port); wire->port_id = nl->IndexOf(port) + 1; @@ -934,7 +864,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se RTLIL::Wire *wire = module->addWire(RTLIL::escape_id(portbus->Name()), portbus->Size()); wire->start_offset = min(portbus->LeftIndex(), portbus->RightIndex()); - import_attributes(wire->attributes, portbus, nl); + import_attributes(wire->attributes, portbus); if (portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_IN) wire->port_input = true; @@ -974,7 +904,6 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se module->memories[memory->name] = memory; int number_of_bits = net->Size(); - number_of_bits = 1 << ceil_log2(number_of_bits); int bits_in_word = number_of_bits; FOREACH_PORTREF_OF_NET(net, si, pr) { if (pr->GetInst()->Type() == OPER_READ_PORT) { @@ -1015,17 +944,17 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se ascii_initdata++; } if (initval_valid) { - RTLIL::Cell *cell = module->addCell(new_verific_id(net), ID($meminit)); - cell->parameters[ID::WORDS] = 1; + RTLIL::Cell *cell = module->addCell(new_verific_id(net), "$meminit"); + cell->parameters["\\WORDS"] = 1; if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound()) - cell->setPort(ID::ADDR, word_idx); + cell->setPort("\\ADDR", word_idx); else - cell->setPort(ID::ADDR, memory->size - word_idx - 1); - cell->setPort(ID::DATA, initval); - cell->parameters[ID::MEMID] = RTLIL::Const(memory->name.str()); - cell->parameters[ID::ABITS] = 32; - cell->parameters[ID::WIDTH] = memory->width; - cell->parameters[ID::PRIORITY] = RTLIL::Const(autoidx-1); + cell->setPort("\\ADDR", memory->size - word_idx - 1); + cell->setPort("\\DATA", initval); + cell->parameters["\\MEMID"] = RTLIL::Const(memory->name.str()); + cell->parameters["\\ABITS"] = 32; + cell->parameters["\\WIDTH"] = memory->width; + cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1); } } } @@ -1084,7 +1013,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log(" importing net %s as %s.\n", net->Name(), log_id(wire_name)); RTLIL::Wire *wire = module->addWire(wire_name); - import_attributes(wire->attributes, net, nl); + import_attributes(wire->attributes, net); net_map[net] = wire; } @@ -1109,12 +1038,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se RTLIL::Wire *wire = module->addWire(wire_name, netbus->Size()); wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex()); - MapIter mibus; - FOREACH_NET_OF_NETBUS(netbus, mibus, net) { - if (net) - import_attributes(wire->attributes, net, nl); - break; - } + import_attributes(wire->attributes, netbus); RTLIL::Const initval = Const(State::Sx, GetSize(wire)); bool initval_valid = false; @@ -1147,7 +1071,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se } if (initval_valid) - wire->attributes[ID::init] = initval; + wire->attributes["\\init"] = initval; } else { @@ -1201,8 +1125,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se SigBit bit = net_map_at(it.first); log_assert(bit.wire); - if (bit.wire->attributes.count(ID::init)) - initval = bit.wire->attributes.at(ID::init); + if (bit.wire->attributes.count("\\init")) + initval = bit.wire->attributes.at("\\init"); while (GetSize(initval) < GetSize(bit.wire)) initval.bits.push_back(State::Sx); @@ -1212,7 +1136,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se if (it.second == '1') initval.bits.at(bit.offset) = State::S1; - bit.wire->attributes[ID::init] = initval; + bit.wire->attributes["\\init"] = initval; } for (auto net : anyconst_nets) @@ -1267,63 +1191,64 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se if (inst->Type() == OPER_READ_PORT) { - RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetInput()->Name()), nullptr); - if (!memory) - log_error("Memory net '%s' missing, possibly no driver, use verific -flatten.\n", inst->GetInput()->Name()); - + RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetInput()->Name())); int numchunks = int(inst->OutputSize()) / memory->width; int chunksbits = ceil_log2(numchunks); + if ((numchunks * memory->width) != int(inst->OutputSize()) || (numchunks & (numchunks - 1)) != 0) + log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name()); + for (int i = 0; i < numchunks; i++) { RTLIL::SigSpec addr = {operatorInput1(inst), RTLIL::Const(i, chunksbits)}; RTLIL::SigSpec data = operatorOutput(inst).extract(i * memory->width, memory->width); RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name : - RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), ID($memrd)); - cell->parameters[ID::MEMID] = memory->name.str(); - cell->parameters[ID::CLK_ENABLE] = false; - cell->parameters[ID::CLK_POLARITY] = true; - cell->parameters[ID::TRANSPARENT] = false; - cell->parameters[ID::ABITS] = GetSize(addr); - cell->parameters[ID::WIDTH] = GetSize(data); - cell->setPort(ID::CLK, RTLIL::State::Sx); - cell->setPort(ID::EN, RTLIL::State::Sx); - cell->setPort(ID::ADDR, addr); - cell->setPort(ID::DATA, data); + RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), "$memrd"); + cell->parameters["\\MEMID"] = memory->name.str(); + cell->parameters["\\CLK_ENABLE"] = false; + cell->parameters["\\CLK_POLARITY"] = true; + cell->parameters["\\TRANSPARENT"] = false; + cell->parameters["\\ABITS"] = GetSize(addr); + cell->parameters["\\WIDTH"] = GetSize(data); + cell->setPort("\\CLK", RTLIL::State::Sx); + cell->setPort("\\EN", RTLIL::State::Sx); + cell->setPort("\\ADDR", addr); + cell->setPort("\\DATA", data); } continue; } if (inst->Type() == OPER_WRITE_PORT || inst->Type() == OPER_CLOCKED_WRITE_PORT) { - RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetOutput()->Name()), nullptr); - if (!memory) - log_error("Memory net '%s' missing, possibly no driver, use verific -flatten.\n", inst->GetInput()->Name()); + RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetOutput()->Name())); int numchunks = int(inst->Input2Size()) / memory->width; int chunksbits = ceil_log2(numchunks); + if ((numchunks * memory->width) != int(inst->Input2Size()) || (numchunks & (numchunks - 1)) != 0) + log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetOutput()->Name()); + for (int i = 0; i < numchunks; i++) { RTLIL::SigSpec addr = {operatorInput1(inst), RTLIL::Const(i, chunksbits)}; RTLIL::SigSpec data = operatorInput2(inst).extract(i * memory->width, memory->width); RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name : - RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), ID($memwr)); - cell->parameters[ID::MEMID] = memory->name.str(); - cell->parameters[ID::CLK_ENABLE] = false; - cell->parameters[ID::CLK_POLARITY] = true; - cell->parameters[ID::PRIORITY] = 0; - cell->parameters[ID::ABITS] = GetSize(addr); - cell->parameters[ID::WIDTH] = GetSize(data); - cell->setPort(ID::EN, RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data))); - cell->setPort(ID::CLK, RTLIL::State::S0); - cell->setPort(ID::ADDR, addr); - cell->setPort(ID::DATA, data); + RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), "$memwr"); + cell->parameters["\\MEMID"] = memory->name.str(); + cell->parameters["\\CLK_ENABLE"] = false; + cell->parameters["\\CLK_POLARITY"] = true; + cell->parameters["\\PRIORITY"] = 0; + cell->parameters["\\ABITS"] = GetSize(addr); + cell->parameters["\\WIDTH"] = GetSize(data); + cell->setPort("\\EN", RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data))); + cell->setPort("\\CLK", RTLIL::State::S0); + cell->setPort("\\ADDR", addr); + cell->setPort("\\DATA", data); if (inst->Type() == OPER_CLOCKED_WRITE_PORT) { - cell->parameters[ID::CLK_ENABLE] = true; - cell->setPort(ID::CLK, net_map_at(inst->GetClock())); + cell->parameters["\\CLK_ENABLE"] = true; + cell->setPort("\\CLK", net_map_at(inst->GetClock())); } } continue; @@ -1498,7 +1423,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se RTLIL::Cell *cell = module->addCell(inst_name, inst_type); if (inst->IsPrimitive() && mode_keep) - cell->attributes[ID::keep] = 1; + cell->attributes["\\keep"] = 1; dict> cell_port_conns; @@ -1581,10 +1506,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se for (auto wire : module->wires()) { - if (!wire->attributes.count(ID::init)) + if (!wire->attributes.count("\\init")) continue; - Const &initval = wire->attributes.at(ID::init); + Const &initval = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(initval); i++) { if (initval[i] != State::S0 && initval[i] != State::S1) @@ -1595,7 +1520,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se } if (initval.is_fully_undef()) - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); } } } @@ -1719,10 +1644,10 @@ Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const if (GetSize(init_value) != 0) { log_assert(GetSize(sig_q) == GetSize(init_value)); if (sig_q.is_wire()) { - sig_q.as_wire()->attributes[ID::init] = init_value; + sig_q.as_wire()->attributes["\\init"] = init_value; } else { Wire *w = module->addWire(NEW_ID, GetSize(sig_q)); - w->attributes[ID::init] = init_value; + w->attributes["\\init"] = init_value; module->connect(sig_q, w); sig_q = w; } @@ -1887,7 +1812,7 @@ struct VerificExtNets new_net = new Net(name.c_str()); nl->Add(new_net); - Net *n = route_up(new_net, port->IsOutput(), ca_nl, ca_net); + Net *n YS_ATTRIBUTE(unused) = route_up(new_net, port->IsOutput(), ca_nl, ca_net); log_assert(n == ca_net); } @@ -1966,9 +1891,6 @@ void verific_import(Design *design, const std::map &par if (!verific_error_msg.empty()) log_error("%s\n", verific_error_msg.c_str()); - for (auto nl : nl_todo) - nl->ChangePortBusStructures(1 /* hierarchical */); - VerificExtNets worker; for (auto nl : nl_todo) worker.run(nl); @@ -2013,7 +1935,7 @@ bool check_noverific_env() struct VerificPass : public Pass { VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -2143,27 +2065,16 @@ struct VerificPass : public Pass { log(" -d \n"); log(" Dump the Verific netlist as a verilog file.\n"); log("\n"); - log("\n"); - log("Use Symbiotic EDA Suite if you need Yosys+Verifc.\n"); - log("https://www.symbioticeda.com/seda-suite\n"); - log("\n"); - log("Contact office@symbioticeda.com for free evaluation\n"); - log("binaries of Symbiotic EDA Suite.\n"); + log("Visit http://verific.com/ for more information on Verific.\n"); log("\n"); } #ifdef YOSYS_ENABLE_VERIFIC - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { static bool set_verific_global_flags = true; if (check_noverific_env()) - log_cmd_error("This version of Yosys is built without Verific support.\n" - "\n" - "Use Symbiotic EDA Suite if you need Yosys+Verifc.\n" - "https://www.symbioticeda.com/seda-suite\n" - "\n" - "Contact office@symbioticeda.com for free evaluation\n" - "binaries of Symbiotic EDA Suite.\n"); + log_cmd_error("This version of Yosys is built without Verific support.\n"); log_header(design, "Executing VERIFIC (loading SystemVerilog and VHDL designs using Verific).\n"); @@ -2185,9 +2096,6 @@ struct VerificPass : public Pass { RuntimeFlags::SetVar("vhdl_support_variable_slice", 1); RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0); - RuntimeFlags::SetVar("veri_preserve_assignments", 1); - RuntimeFlags::SetVar("vhdl_preserve_assignments", 1); - // Workaround for VIPER #13851 RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1); @@ -2489,7 +2397,7 @@ struct VerificPass : public Pass { else { if (argidx == GetSize(args)) - cmd_error(args, argidx, "No top module specified.\n"); + log_cmd_error("No top module specified.\n"); Array veri_modules, vhdl_units; for (; argidx < GetSize(args); argidx++) @@ -2551,9 +2459,6 @@ struct VerificPass : public Pass { worker.run(nl); } - for (auto nl : nl_todo) - nl->ChangePortBusStructures(1 /* hierarchical */); - if (!dumpfile.empty()) { VeriWrite veri_writer; veri_writer.WriteFile(dumpfile.c_str(), Netlist::PresentDesign()); @@ -2579,7 +2484,7 @@ struct VerificPass : public Pass { goto check_error; } - cmd_error(args, argidx, "Missing or unsupported mode parameter.\n"); + log_cmd_error("Missing or unsupported mode parameter.\n"); check_error: if (!verific_error_msg.empty()) @@ -2587,21 +2492,15 @@ struct VerificPass : public Pass { } #else /* YOSYS_ENABLE_VERIFIC */ - void execute(std::vector, RTLIL::Design *) override { - log_cmd_error("This version of Yosys is built without Verific support.\n" - "\n" - "Use Symbiotic EDA Suite if you need Yosys+Verifc.\n" - "https://www.symbioticeda.com/seda-suite\n" - "\n" - "Contact office@symbioticeda.com for free evaluation\n" - "binaries of Symbiotic EDA Suite.\n"); + void execute(std::vector, RTLIL::Design *) YS_OVERRIDE { + log_cmd_error("This version of Yosys is built without Verific support.\n"); } #endif } VerificPass; struct ReadPass : public Pass { ReadPass() : Pass("read", "load HDL designs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -2642,7 +2541,7 @@ struct ReadPass : public Pass { log("Verific support. The default is to use Verific if it is available.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { #ifdef YOSYS_ENABLE_VERIFIC static bool verific_available = !check_noverific_env(); @@ -2652,14 +2551,14 @@ struct ReadPass : public Pass { static bool use_verific = verific_available; if (args.size() < 2 || args[1][0] != '-') - cmd_error(args, 1, "Missing mode parameter.\n"); + log_cmd_error("Missing mode parameter.\n"); if (args[1] == "-verific" || args[1] == "-noverific") { if (args.size() != 2) - cmd_error(args, 1, "Additional arguments to -verific/-noverific.\n"); + log_cmd_error("Additional arguments to -verific/-noverific.\n"); if (args[1] == "-verific") { if (!verific_available) - cmd_error(args, 1, "This version of Yosys is built without Verific support.\n"); + log_cmd_error("This version of Yosys is built without Verific support.\n"); use_verific = true; } else { use_verific = false; @@ -2668,7 +2567,7 @@ struct ReadPass : public Pass { } if (args.size() < 3) - cmd_error(args, 3, "Missing file name parameter.\n"); + log_cmd_error("Missing file name parameter.\n"); if (args[1] == "-vlog95" || args[1] == "-vlog2k") { if (use_verific) { @@ -2700,7 +2599,7 @@ struct ReadPass : public Pass { args[0] = "verific"; Pass::call(design, args); } else { - cmd_error(args, 1, "This version of Yosys is built without Verific support.\n"); + log_cmd_error("This version of Yosys is built without Verific support.\n"); } return; } @@ -2747,7 +2646,7 @@ struct ReadPass : public Pass { return; } - cmd_error(args, 1, "Missing or unsupported mode parameter.\n"); + log_cmd_error("Missing or unsupported mode parameter.\n"); } } ReadPass; diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h index f168a25887f..2ccfcd42cb2 100644 --- a/frontends/verific/verific.h +++ b/frontends/verific/verific.h @@ -79,7 +79,7 @@ struct VerificImporter RTLIL::SigBit net_map_at(Verific::Net *net); RTLIL::IdString new_verific_id(Verific::DesignObj *obj); - void import_attributes(dict &attributes, Verific::DesignObj *obj, Verific::Netlist *nl = nullptr); + void import_attributes(dict &attributes, Verific::DesignObj *obj); RTLIL::SigSpec operatorInput(Verific::Instance *inst); RTLIL::SigSpec operatorInput1(Verific::Instance *inst); diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc index cf9b9531e49..6a8462b4189 100644 --- a/frontends/verilog/Makefile.inc +++ b/frontends/verilog/Makefile.inc @@ -10,7 +10,7 @@ frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc -frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l frontends/verilog/verilog_parser.tab.cc +frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l $(Q) mkdir -p $(dir $@) $(P) flex -o frontends/verilog/verilog_lexer.cc $< diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 230dfadbfb2..49281f7e79e 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -139,9 +139,6 @@ static void my_strtobin(std::vector &data, const char *str, int le data.resize(len_in_bits, msb); } - if (len_in_bits == 0) - log_file_error(current_filename, get_line_num(), "Illegal integer constant size of zero (IEEE 1800-2012, 5.7).\n"); - if (len > len_in_bits) log_warning("Literal has a width of %d bit, but value requires %d bit. (%s:%d)\n", len_in_bits, len, current_filename.c_str(), get_line_num()); diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index ea23139e23a..7e107dc267b 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -28,14 +28,12 @@ * * Ad-hoc implementation of a Verilog preprocessor. The directives `define, * `include, `ifdef, `ifndef, `else and `endif are handled here. All other - * directives are handled by the lexer (see verilog_lexer.l). + * directives are handled by the lexer (see lexer.l). * */ -#include "preproc.h" #include "verilog_frontend.h" #include "kernel/log.h" -#include #include #include #include @@ -201,175 +199,6 @@ static std::string next_token(bool pass_newline = false) return token; } -struct macro_arg_t -{ - macro_arg_t(const std::string &name_, const char *default_value_) - : name(name_), - has_default(default_value_ != nullptr), - default_value(default_value_ ? default_value_ : "") - {} - - std::string name; - bool has_default; - std::string default_value; -}; - -static bool all_white(const std::string &str) -{ - for (char c : str) - if (!isspace(c)) - return false; - return true; -} - -struct arg_map_t -{ - arg_map_t() - {} - - void add_arg(const std::string &name, const char *default_value) - { - if (find(name)) { - log_error("Duplicate macro arguments with name `%s'.\n", name.c_str()); - } - - name_to_pos[name] = args.size(); - args.push_back(macro_arg_t(name, default_value)); - } - - // Find an argument by name; return nullptr if it doesn't exist. If pos is not null, write - // the argument's position to it on success. - const macro_arg_t *find(const std::string &name, int *pos = nullptr) const - { - auto it = name_to_pos.find(name); - if (it == name_to_pos.end()) - return nullptr; - - if (pos) *pos = it->second; - return &args[it->second]; - } - - // Construct the name for the local macro definition we use for the given argument - // (something like macro_foobar_arg2). This doesn't include the leading backtick. - static std::string str_token(const std::string ¯o_name, int pos) - { - return stringf("macro_%s_arg%d", macro_name.c_str(), pos); - } - - // Return definitions for the macro arguments (so that substituting in the macro body and - // then performing macro expansion will do argument substitution properly). - std::vector> - get_vals(const std::string ¯o_name, const std::vector &arg_vals) const - { - std::vector> ret; - for (int i = 0; i < GetSize(args); ++ i) { - // The SystemVerilog rules are: - // - // - If the call site specifies an argument and it's not whitespace, use - // it. - // - // - Otherwise, if the argument has a default value, use it. - // - // - Otherwise, if the call site specified whitespace, use that. - // - // - Otherwise, error. - const std::string *dflt = nullptr; - if (args[i].has_default) - dflt = &args[i].default_value; - - const std::string *given = nullptr; - if (i < GetSize(arg_vals)) - given = &arg_vals[i]; - - const std::string *val = nullptr; - if (given && (! (dflt && all_white(*given)))) - val = given; - else if (dflt) - val = dflt; - else if (given) - val = given; - else - log_error("Cannot expand macro `%s by giving only %d argument%s " - "(argument %d has no default).\n", - macro_name.c_str(), GetSize(arg_vals), - (GetSize(arg_vals) == 1 ? "" : "s"), i + 1); - - assert(val); - ret.push_back(std::make_pair(str_token(macro_name, i), * val)); - } - return ret; - } - - - std::vector args; - std::map name_to_pos; -}; - -struct define_body_t -{ - define_body_t(const std::string &body, const arg_map_t *args = nullptr) - : body(body), - has_args(args != nullptr), - args(args ? *args : arg_map_t()) - {} - - std::string body; - bool has_args; - arg_map_t args; -}; - -define_map_t::define_map_t() -{ - add("YOSYS", "1"); - add(formal_mode ? "FORMAL" : "SYNTHESIS", "1"); -} - -// We must define this destructor here (rather than relying on the default), because we need to -// define it somewhere we've got a complete definition of define_body_t. -define_map_t::~define_map_t() -{} - -void -define_map_t::add(const std::string &name, const std::string &txt, const arg_map_t *args) -{ - defines[name] = std::unique_ptr(new define_body_t(txt, args)); -} - -void define_map_t::merge(const define_map_t &map) -{ - for (const auto &pr : map.defines) { - // These contortions are so that we take a copy of each definition body in - // map.defines. - defines[pr.first] = std::unique_ptr(new define_body_t(*pr.second)); - } -} - -const define_body_t *define_map_t::find(const std::string &name) const -{ - auto it = defines.find(name); - return (it == defines.end()) ? nullptr : it->second.get(); -} - -void define_map_t::erase(const std::string &name) -{ - defines.erase(name); -} - -void define_map_t::clear() -{ - defines.clear(); -} - -void define_map_t::log() const -{ - for (auto &it : defines) { - const std::string &name = it.first; - const define_body_t &body = *it.second; - Yosys::log("`define %s%s %s\n", - name.c_str(), body.has_args ? "()" : "", body.body.c_str()); - } -} - static void input_file(std::istream &f, std::string filename) { char buffer[513]; @@ -386,59 +215,11 @@ static void input_file(std::istream &f, std::string filename) input_buffer.insert(it, "\n`file_pop\n"); } -// Read tokens to get one argument (either a macro argument at a callsite or a default argument in a -// macro definition). Writes the argument to dest. Returns true if we finished with ')' (the end of -// the argument list); false if we finished with ','. -static bool read_argument(std::string &dest) -{ - std::vector openers; - for (;;) { - skip_spaces(); - std::string tok = next_token(true); - if (tok == ")") { - if (openers.empty()) - return true; - if (openers.back() != '(') - log_error("Mismatched brackets in macro argument: %c and %c.\n", - openers.back(), tok[0]); - - openers.pop_back(); - dest += tok; - continue; - } - if (tok == "]") { - char opener = openers.empty() ? '(' : openers.back(); - if (opener != '[') - log_error("Mismatched brackets in macro argument: %c and %c.\n", - opener, tok[0]); - - openers.pop_back(); - dest += tok; - continue; - } - if (tok == "}") { - char opener = openers.empty() ? '(' : openers.back(); - if (opener != '{') - log_error("Mismatched brackets in macro argument: %c and %c.\n", - opener, tok[0]); - - openers.pop_back(); - dest += tok; - continue; - } - - if (tok == "," && openers.empty()) { - return false; - } - - if (tok == "(" || tok == "[" || tok == "{") - openers.push_back(tok[0]); - dest += tok; - } -} - -static bool try_expand_macro(define_map_t &defines, std::string &tok) +static bool try_expand_macro(std::set &defines_with_args, + std::map &defines_map, + std::string &tok + ) { if (tok == "`\"") { std::string literal("\""); @@ -448,272 +229,54 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok) if (ntok == "`\"") { insert_input(literal+"\""); return true; - } else if (!try_expand_macro(defines, ntok)) { + } else if (!try_expand_macro(defines_with_args, defines_map, ntok)) { literal += ntok; } } return false; // error - unmatched `" - } - - if (tok == "``") { - // Swallow `` in macro expansion - return true; - } - - if (tok.size() <= 1 || tok[0] != '`') - return false; - - // This token looks like a macro name (`foo). - std::string macro_name = tok.substr(1); - const define_body_t *body = defines.find(tok.substr(1)); - - if (! body) { - // Apparently not a name we know. - return false; - } - - std::string name = tok.substr(1); - std::string skipped_spaces = skip_spaces(); - tok = next_token(false); - if (tok == "(" && body->has_args) { - std::vector args; - bool done = false; - while (!done) { - std::string arg; - done = read_argument(arg); - args.push_back(arg); - } - for (const auto &pr : body->args.get_vals(name, args)) { - defines.add(pr.first, pr.second); - } - } else { - insert_input(tok); - insert_input(skipped_spaces); - } - insert_input(body->body); - return true; -} - -// Read the arguments for a `define preprocessor directive with formal arguments. This is called -// just after reading the token containing "(". Returns the number of newlines to emit afterwards to -// keep line numbers in sync, together with the map from argument name to data (pos and default -// value). -static std::pair -read_define_args() -{ - // Each argument looks like one of the following: - // - // identifier - // identifier = default_text - // identifier = - // - // The first example is an argument with no default value. The second is an argument whose - // default value is default_text. The third is an argument with default value the empty - // string. - - int newline_count = 0; - arg_map_t args; - - // FSM state. - // - // 0: At start of identifier - // 1: After identifier (stored in arg_name) - // 2: After closing paren - int state = 0; - - std::string arg_name, default_val; - - skip_spaces(); - for (;;) { - if (state == 2) - // We've read the closing paren. - break; - - std::string tok = next_token(); - - // Cope with escaped EOLs - if (tok == "\\") { - char ch = next_char(); - if (ch == '\n') { - // Eat the \, the \n and any trailing space and keep going. - skip_spaces(); - continue; - } else { - // There aren't any other situations where a backslash makes sense. - log_error("Backslash in macro arguments (not at end of line).\n"); - } - } - - switch (state) { - case 0: - // At start of argument. If the token is ')', we've presumably just seen - // something like "`define foo() ...". Set state to 2 to finish. Otherwise, - // the token should be a valid simple identifier, but we'll allow anything - // here. - if (tok == ")") { - state = 2; - } else { - arg_name = tok; - state = 1; - } - skip_spaces(); - break; - - case 1: - // After argument. The token should either be an equals sign or a comma or - // closing paren. - if (tok == "=") { - std::string default_val; - //Read an argument into default_val and set state to 2 if we're at - // the end; 0 if we hit a comma. - state = read_argument(default_val) ? 2 : 0; - args.add_arg(arg_name, default_val.c_str()); - skip_spaces(); - break; - } - if (tok == ",") { - // Take the identifier as an argument with no default value. - args.add_arg(arg_name, nullptr); - state = 0; - skip_spaces(); - break; - } - if (tok == ")") { - // As with comma, but set state to 2 (end of args) - args.add_arg(arg_name, nullptr); - state = 2; - skip_spaces(); - break; - } - log_error("Trailing contents after identifier in macro argument `%s': " - "expected '=', ',' or ')'.\n", - arg_name.c_str()); - - default: - // The only FSM states are 0-2 and we dealt with 2 at the start of the loop. - log_assert(false); - } - } - - return std::make_pair(newline_count, args); -} - -// Read a `define preprocessor directive. This is called just after reading the token containing -// "`define". -static void -read_define(const std::string &filename, - define_map_t &defines_map, - define_map_t &global_defines_cache) -{ - std::string name, value; - arg_map_t args; - - skip_spaces(); - name = next_token(true); - - bool here_doc_mode = false; - int newline_count = 0; - - // The FSM state starts at 0. If it sees space (or enters here_doc_mode), it assumes this is - // a macro without formal arguments and jumps to state 1. - // - // In state 0, if it sees an opening parenthesis, it assumes this is a macro with formal - // arguments. It reads the arguments with read_define_args() and then jumps to state 2. - // - // In states 1 or 2, the FSM reads tokens to the end of line (or end of here_doc): this is - // the body of the macro definition. - int state = 0; - - if (skip_spaces() != "") - state = 1; - - for (;;) { - std::string tok = next_token(); - if (tok.empty()) - break; - - // printf("define-tok: >>%s<<\n", tok != "\n" ? tok.c_str() : "NEWLINE"); - - if (tok == "\"\"\"") { - here_doc_mode = !here_doc_mode; - continue; - } - - if (state == 0 && tok == "(") { - auto pr = read_define_args(); - newline_count += pr.first; - args = pr.second; - - state = 2; - continue; - } - - // This token isn't an opening parenthesis immediately following the macro name, so - // it's presumably at or after the start of the macro body. If state isn't already 2 - // (which would mean we'd parsed an argument list), set it to 1. - if (state == 0) { - state = 1; - } - - if (tok == "\n") { - if (here_doc_mode) { - value += " "; - newline_count++; + } else if (tok.size() > 1 && tok[0] == '`' && defines_map.count(tok.substr(1)) > 0) { + std::string name = tok.substr(1); + // printf("expand: >>%s<< -> >>%s<<\n", name.c_str(), defines_map[name].c_str()); + std::string skipped_spaces = skip_spaces(); + tok = next_token(false); + if (tok == "(" && defines_with_args.count(name) > 0) { + int level = 1; + std::vector args; + args.push_back(std::string()); + while (1) + { + skip_spaces(); + tok = next_token(true); + if (tok == ")" || tok == "}" || tok == "]") + level--; + if (level == 0) + break; + if (level == 1 && tok == ",") + args.push_back(std::string()); + else + args.back() += tok; + if (tok == "(" || tok == "{" || tok == "[") + level++; + } + for (int i = 0; i < GetSize(args); i++) + defines_map[stringf("macro_%s_arg%d", name.c_str(), i+1)] = args[i]; } else { - return_char('\n'); - break; + insert_input(tok); + insert_input(skipped_spaces); } - continue; - } - - if (tok == "\\") { - char ch = next_char(); - if (ch == '\n') { - value += " "; - newline_count++; - } else { - value += std::string("\\"); - return_char(ch); - } - continue; - } - - // Is this token the name of a macro argument? If so, replace it with a magic symbol - // that we'll replace with the argument value. - int arg_pos; - if (args.find(tok, &arg_pos)) { - value += '`' + args.str_token(name, arg_pos); - continue; - } - - // This token is nothing special. Insert it verbatim into the macro body. - value += tok; - } - - // Append some newlines so that we don't mess up line counts in error messages. - while (newline_count-- > 0) - return_char('\n'); - - if (strchr("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789", name[0])) { - // printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str()); - defines_map.add(name, value, (state == 2) ? &args : nullptr); - global_defines_cache.add(name, value, (state == 2) ? &args : nullptr); - } else { - log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name.c_str()); - } + insert_input(defines_map[name]); + return true; + } else if (tok == "``") { + // Swallow `` in macro expansion + return true; + } else return false; } -std::string -frontend_verilog_preproc(std::istream &f, - std::string filename, - const define_map_t &pre_defines, - define_map_t &global_defines_cache, - const std::list &include_dirs) +std::string frontend_verilog_preproc(std::istream &f, std::string filename, const std::map &pre_defines_map, + dict> &global_defines_cache, const std::list &include_dirs) { - define_map_t defines; - defines.merge(pre_defines); - defines.merge(global_defines_cache); - + std::set defines_with_args; + std::map defines_map(pre_defines_map); std::vector filename_stack; int ifdef_fail_level = 0; bool in_elseif = false; @@ -724,6 +287,18 @@ frontend_verilog_preproc(std::istream &f, input_file(f, filename); + defines_map["YOSYS"] = "1"; + defines_map[formal_mode ? "FORMAL" : "SYNTHESIS"] = "1"; + + for (auto &it : pre_defines_map) + defines_map[it.first] = it.second; + + for (auto &it : global_defines_cache) { + if (it.second.second) + defines_with_args.insert(it.first); + defines_map[it.first] = it.second.first; + } + while (!input_buffer.empty()) { std::string tok = next_token(); @@ -750,7 +325,7 @@ frontend_verilog_preproc(std::istream &f, std::string name = next_token(true); if (ifdef_fail_level == 0) ifdef_fail_level = 1, in_elseif = true; - else if (ifdef_fail_level == 1 && defines.find(name)) + else if (ifdef_fail_level == 1 && defines_map.count(name) != 0) ifdef_fail_level = 0, in_elseif = true; continue; } @@ -758,7 +333,7 @@ frontend_verilog_preproc(std::istream &f, if (tok == "`ifdef") { skip_spaces(); std::string name = next_token(true); - if (ifdef_fail_level > 0 || !defines.find(name)) + if (ifdef_fail_level > 0 || defines_map.count(name) == 0) ifdef_fail_level++; continue; } @@ -766,7 +341,7 @@ frontend_verilog_preproc(std::istream &f, if (tok == "`ifndef") { skip_spaces(); std::string name = next_token(true); - if (ifdef_fail_level > 0 || defines.find(name)) + if (ifdef_fail_level > 0 || defines_map.count(name) != 0) ifdef_fail_level++; continue; } @@ -780,7 +355,7 @@ frontend_verilog_preproc(std::istream &f, if (tok == "`include") { skip_spaces(); std::string fn = next_token(true); - while (try_expand_macro(defines, fn)) { + while (try_expand_macro(defines_with_args, defines_map, fn)) { fn = next_token(); } while (1) { @@ -858,7 +433,74 @@ frontend_verilog_preproc(std::istream &f, } if (tok == "`define") { - read_define(filename, defines, global_defines_cache); + std::string name, value; + std::map args; + skip_spaces(); + name = next_token(true); + bool here_doc_mode = false; + int newline_count = 0; + int state = 0; + if (skip_spaces() != "") + state = 3; + while (!tok.empty()) { + tok = next_token(); + if (tok == "\"\"\"") { + here_doc_mode = !here_doc_mode; + continue; + } + if (state == 0 && tok == "(") { + state = 1; + skip_spaces(); + } else + if (state == 1) { + if (tok == ")") + state = 2; + else if (tok != ",") { + int arg_idx = args.size()+1; + args[tok] = arg_idx; + } + skip_spaces(); + } else { + if (state != 2) + state = 3; + if (tok == "\n") { + if (here_doc_mode) { + value += " "; + newline_count++; + } else { + return_char('\n'); + break; + } + } else + if (tok == "\\") { + char ch = next_char(); + if (ch == '\n') { + value += " "; + newline_count++; + } else { + value += std::string("\\"); + return_char(ch); + } + } else + if (args.count(tok) > 0) + value += stringf("`macro_%s_arg%d", name.c_str(), args.at(tok)); + else + value += tok; + } + } + while (newline_count-- > 0) + return_char('\n'); + if (strchr("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789", name[0])) { + // printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str()); + defines_map[name] = value; + if (state == 2) + defines_with_args.insert(name); + else + defines_with_args.erase(name); + global_defines_cache[name] = std::pair(value, state == 2); + } else { + log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name.c_str()); + } continue; } @@ -867,7 +509,8 @@ frontend_verilog_preproc(std::istream &f, skip_spaces(); name = next_token(true); // printf("undef: >>%s<<\n", name.c_str()); - defines.erase(name); + defines_map.erase(name); + defines_with_args.erase(name); global_defines_cache.erase(name); continue; } @@ -882,12 +525,13 @@ frontend_verilog_preproc(std::istream &f, } if (tok == "`resetall") { - defines.clear(); + defines_map.clear(); + defines_with_args.clear(); global_defines_cache.clear(); continue; } - if (try_expand_macro(defines, tok)) + if (try_expand_macro(defines_with_args, defines_map, tok)) continue; output_code.push_back(tok); diff --git a/frontends/verilog/preproc.h b/frontends/verilog/preproc.h deleted file mode 100644 index 673d633c0b6..00000000000 --- a/frontends/verilog/preproc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * 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. - * - * --- - * - * The Verilog preprocessor. - * - */ -#ifndef VERILOG_PREPROC_H -#define VERILOG_PREPROC_H - -#include "kernel/yosys.h" - -#include -#include -#include -#include - -YOSYS_NAMESPACE_BEGIN - -struct define_body_t; -struct arg_map_t; - -struct define_map_t -{ - define_map_t(); - ~ define_map_t(); - - // Add a definition, overwriting any existing definition for name. - void add(const std::string &name, const std::string &txt, const arg_map_t *args = nullptr); - - // Merge in another map of definitions (which take precedence - // over anything currently defined). - void merge(const define_map_t &map); - - // Find a definition by name. If no match, returns null. - const define_body_t *find(const std::string &name) const; - - // Erase a definition by name (no effect if not defined). - void erase(const std::string &name); - - // Clear any existing definitions - void clear(); - - // Print a list of definitions, using the log function - void log() const; - - std::map> defines; -}; - - -struct define_map_t; - -std::string -frontend_verilog_preproc(std::istream &f, - std::string filename, - const define_map_t &pre_defines, - define_map_t &global_defines_cache, - const std::list &include_dirs); - -YOSYS_NAMESPACE_END - -#endif diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 2e9c9b2e2e9..058d750c394 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -27,7 +27,6 @@ */ #include "verilog_frontend.h" -#include "preproc.h" #include "kernel/yosys.h" #include "libs/sha1/sha1.h" #include @@ -43,31 +42,14 @@ static std::list> verilog_defaults_stack; static void error_on_dpi_function(AST::AstNode *node) { if (node->type == AST::AST_DPI_FUNCTION) - log_file_error(node->filename, node->location.first_line, "Found DPI function %s.\n", node->str.c_str()); + log_file_error(node->filename, node->linenum, "Found DPI function %s.\n", node->str.c_str()); for (auto child : node->children) error_on_dpi_function(child); } -static void add_package_types(dict &user_types, std::vector &package_list) -{ - // prime the parser's user type lookup table with the package qualified names - // of typedefed names in the packages seen so far. - for (const auto &pkg : package_list) { - log_assert(pkg->type==AST::AST_PACKAGE); - for (const auto &node: pkg->children) { - if (node->type == AST::AST_TYPEDEF) { - std::string s = pkg->str + "::" + node->str.substr(1); - user_types[s] = node; - } - } - } - user_type_stack.clear(); - user_type_stack.push_back(new UserTypeMap()); -} - struct VerilogFrontend : public Frontend { VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -232,7 +214,7 @@ struct VerilogFrontend : public Frontend { log("supported by the Yosys Verilog front-end.\n"); log("\n"); } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_dump_ast1 = false; bool flag_dump_ast2 = false; @@ -255,8 +237,7 @@ struct VerilogFrontend : public Frontend { bool flag_defer = false; bool flag_noblackbox = false; bool flag_nowb = false; - define_map_t defines_map; - + std::map defines_map; std::list include_dirs; std::list attributes; @@ -372,7 +353,7 @@ struct VerilogFrontend : public Frontend { } if (arg == "-lib") { lib_mode = true; - defines_map.add("BLACKBOX", ""); + defines_map["BLACKBOX"] = string(); continue; } if (arg == "-nowb") { @@ -424,7 +405,7 @@ struct VerilogFrontend : public Frontend { value = name.substr(equal+1); name = name.substr(0, equal); } - defines_map.add(name, value); + defines_map[name] = value; continue; } if (arg.compare(0, 2, "-D") == 0) { @@ -433,7 +414,7 @@ struct VerilogFrontend : public Frontend { std::string value; if (equal != std::string::npos) value = arg.substr(equal+1); - defines_map.add(name, value); + defines_map[name] = value; continue; } if (arg == "-I" && argidx+1 < args.size()) { @@ -463,15 +444,12 @@ struct VerilogFrontend : public Frontend { std::string code_after_preproc; if (!flag_nopp) { - code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, *design->verilog_defines, include_dirs); + code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, design->verilog_defines, include_dirs); if (flag_ppdump) log("-- Verilog code after preprocessor --\n%s-- END OF DUMP --\n", code_after_preproc.c_str()); lexin = new std::istringstream(code_after_preproc); } - // make package typedefs available to parser - add_package_types(pkg_user_types, design->verilog_packages); - frontend_verilog_yyset_lineno(1); frontend_verilog_yyrestart(NULL); frontend_verilog_yyparse(); @@ -490,7 +468,6 @@ struct VerilogFrontend : public Frontend { AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire); - if (!flag_nopp) delete lexin; @@ -503,7 +480,7 @@ struct VerilogFrontend : public Frontend { struct VerilogDefaults : public Pass { VerilogDefaults() : Pass("verilog_defaults", "set default options for read_verilog") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -524,7 +501,7 @@ struct VerilogDefaults : public Pass { log("not imply -clear.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design*) override + void execute(std::vector args, RTLIL::Design*) YS_OVERRIDE { if (args.size() < 2) cmd_error(args, 1, "Missing argument."); @@ -561,7 +538,7 @@ struct VerilogDefaults : public Pass { struct VerilogDefines : public Pass { VerilogDefines() : Pass("verilog_defines", "define and undefine verilog defines") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -583,7 +560,7 @@ struct VerilogDefines : public Pass { log(" list currently defined preprocessor symbols\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -595,7 +572,7 @@ struct VerilogDefines : public Pass { value = name.substr(equal+1); name = name.substr(0, equal); } - design->verilog_defines->add(name, value); + design->verilog_defines[name] = std::pair(value, false); continue; } if (arg.compare(0, 2, "-D") == 0) { @@ -604,25 +581,27 @@ struct VerilogDefines : public Pass { std::string value; if (equal != std::string::npos) value = arg.substr(equal+1); - design->verilog_defines->add(name, value); + design->verilog_defines[name] = std::pair(value, false); continue; } if (arg == "-U" && argidx+1 < args.size()) { std::string name = args[++argidx]; - design->verilog_defines->erase(name); + design->verilog_defines.erase(name); continue; } if (arg.compare(0, 2, "-U") == 0) { std::string name = arg.substr(2); - design->verilog_defines->erase(name); + design->verilog_defines.erase(name); continue; } if (arg == "-reset") { - design->verilog_defines->clear(); + design->verilog_defines.clear(); continue; } if (arg == "-list") { - design->verilog_defines->log(); + for (auto &it : design->verilog_defines) { + log("`define %s%s %s\n", it.first.c_str(), it.second.second ? "()" : "", it.second.first.c_str()); + } continue; } break; diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index aa78810388c..a7c9b2fe6ab 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -45,13 +45,6 @@ namespace VERILOG_FRONTEND // this function converts a Verilog constant to an AST_CONSTANT node AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false); - // names of locally typedef'ed types in a stack - typedef std::map UserTypeMap; - extern std::vector user_type_stack; - - // names of package typedef'ed types - extern dict pkg_user_types; - // state of `default_nettype extern bool default_nettype_wire; @@ -86,10 +79,15 @@ namespace VERILOG_FRONTEND extern std::istream *lexin; } +// the pre-processor +std::string frontend_verilog_preproc(std::istream &f, std::string filename, const std::map &pre_defines_map, + dict> &global_defines_cache, const std::list &include_dirs); + YOSYS_NAMESPACE_END // the usual bison/flex stuff extern int frontend_verilog_yydebug; +int frontend_verilog_yylex(void); void frontend_verilog_yyerror(char const *fmt, ...); void frontend_verilog_yyrestart(FILE *f); int frontend_verilog_yyparse(void); diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 0281063812e..c8984c2c41a 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -28,7 +28,7 @@ * * A simple lexer for Verilog code. Non-preprocessor compiler directives are * handled here. The preprocessor stuff is handled in preproc.cc. Everything - * else is left to the bison parser (see verilog_parser.y). + * else is left to the bison parser (see parser.y). * */ @@ -48,15 +48,10 @@ USING_YOSYS_NAMESPACE using namespace AST; using namespace VERILOG_FRONTEND; -#define YYSTYPE FRONTEND_VERILOG_YYSTYPE -#define YYLTYPE FRONTEND_VERILOG_YYLTYPE - YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { std::vector fn_stack; std::vector ln_stack; - YYLTYPE real_location; - YYLTYPE old_location; } YOSYS_NAMESPACE_END @@ -65,58 +60,24 @@ YOSYS_NAMESPACE_END log("Lexer warning: The SystemVerilog keyword `%s' (at %s:%d) is not "\ "recognized unless read_verilog is called with -sv!\n", yytext, \ AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); \ - yylval->string = new std::string(std::string("\\") + yytext); \ + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); \ return TOK_ID; #define NON_KEYWORD() \ - yylval->string = new std::string(std::string("\\") + yytext); \ + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); \ return TOK_ID; #define YY_INPUT(buf,result,max_size) \ result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size) -#define YY_USER_ACTION \ - old_location = real_location; \ - real_location.first_line = real_location.last_line; \ - real_location.first_column = real_location.last_column; \ - for(int i = 0; yytext[i] != '\0'; ++i){ \ - if(yytext[i] == '\n') { \ - real_location.last_line++; \ - real_location.last_column = 1; \ - } \ - else { \ - real_location.last_column++; \ - } \ - } \ - (*yylloc) = real_location; - -#define YY_BREAK \ - (*yylloc) = old_location; \ - break; - #undef YY_BUF_SIZE #define YY_BUF_SIZE 65536 -extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); - -static bool isUserType(std::string &s) -{ - // check current scope then outer scopes for a name - for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) { - if ((*it)->count(s) > 0) { - return true; - } - } - return false; -} - %} %option yylineno %option noyywrap %option nounput -%option bison-locations -%option bison-bridge %option prefix="frontend_verilog_yy" %x COMMENT @@ -124,12 +85,8 @@ static bool isUserType(std::string &s) %x SYNOPSYS_TRANSLATE_OFF %x SYNOPSYS_FLAGS %x IMPORT_DPI -%x BASED_CONST %% - // Initialise comment_caller to something to avoid a "maybe undefined" - // warning from GCC. - int comment_caller = INITIAL; "`file_push "[^\n]* { fn_stack.push_back(current_filename); @@ -140,16 +97,12 @@ static bool isUserType(std::string &s) if (!current_filename.empty() && current_filename.back() == '"') current_filename = current_filename.substr(0, current_filename.size()-1); frontend_verilog_yyset_lineno(0); - yylloc->first_line = yylloc->last_line = 0; - real_location.first_line = real_location.last_line = 0; } "`file_pop"[^\n]*\n { current_filename = fn_stack.back(); fn_stack.pop_back(); frontend_verilog_yyset_lineno(ln_stack.back()); - yylloc->first_line = yylloc->last_line = ln_stack.back(); - real_location.first_line = real_location.last_line = ln_stack.back(); ln_stack.pop_back(); } @@ -157,8 +110,6 @@ static bool isUserType(std::string &s) char *p = yytext + 5; while (*p == ' ' || *p == '\t') p++; frontend_verilog_yyset_lineno(atoi(p)); - yylloc->first_line = yylloc->last_line = atoi(p); - real_location.first_line = real_location.last_line = atoi(p); while (*p && *p != ' ' && *p != '\t') p++; while (*p == ' ' || *p == '\t') p++; char *q = *p ? p + 1 : p; @@ -247,7 +198,7 @@ static bool isUserType(std::string &s) [a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] { if (!strcmp(yytext, "default")) return TOK_DEFAULT; - yylval->string = new std::string(std::string("\\") + yytext); + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); return TOK_SVA_LABEL; } @@ -263,10 +214,7 @@ static bool isUserType(std::string &s) "final" { SV_KEYWORD(TOK_FINAL); } "logic" { SV_KEYWORD(TOK_LOGIC); } "var" { SV_KEYWORD(TOK_VAR); } -"bit" { SV_KEYWORD(TOK_LOGIC); } -"int" { SV_KEYWORD(TOK_INT); } -"byte" { SV_KEYWORD(TOK_BYTE); } -"shortint" { SV_KEYWORD(TOK_SHORTINT); } +"bit" { SV_KEYWORD(TOK_REG); } "eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); } "s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); } @@ -280,50 +228,34 @@ static bool isUserType(std::string &s) "reg" { return TOK_REG; } "integer" { return TOK_INTEGER; } "signed" { return TOK_SIGNED; } -"unsigned" { SV_KEYWORD(TOK_UNSIGNED); } "genvar" { return TOK_GENVAR; } "real" { return TOK_REAL; } "enum" { SV_KEYWORD(TOK_ENUM); } "typedef" { SV_KEYWORD(TOK_TYPEDEF); } -"struct" { SV_KEYWORD(TOK_STRUCT); } -"union" { SV_KEYWORD(TOK_UNION); } -"packed" { SV_KEYWORD(TOK_PACKED); } [0-9][0-9_]* { - yylval->string = new std::string(yytext); + frontend_verilog_yylval.string = new std::string(yytext); return TOK_CONSTVAL; } -\'[01zxZX] { - yylval->string = new std::string(yytext); - return TOK_UNBASED_UNSIZED_CONSTVAL; -} - -\'[sS]?[bodhBODH] { - BEGIN(BASED_CONST); - yylval->string = new std::string(yytext); - return TOK_BASE; -} - -[0-9a-fA-FzxZX?][0-9a-fA-FzxZX?_]* { - BEGIN(0); - yylval->string = new std::string(yytext); - return TOK_BASED_CONSTVAL; +[0-9]*[ \t]*\'[sS]?[bodhBODH]?[ \t\r\n]*[0-9a-fA-FzxZX?_]+ { + frontend_verilog_yylval.string = new std::string(yytext); + return TOK_CONSTVAL; } [0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)? { - yylval->string = new std::string(yytext); + frontend_verilog_yylval.string = new std::string(yytext); return TOK_REALVAL; } [0-9][0-9_]*[eE][-+]?[0-9_]+ { - yylval->string = new std::string(yytext); + frontend_verilog_yylval.string = new std::string(yytext); return TOK_REALVAL; } \" { BEGIN(STRING); } -\\. { yymore(); real_location = old_location; } +\\. { yymore(); } \" { BEGIN(0); char *yystr = strdup(yytext); @@ -359,14 +291,14 @@ static bool isUserType(std::string &s) yystr[j++] = yystr[i++]; } yystr[j] = 0; - yylval->string = new std::string(yystr, j); + frontend_verilog_yylval.string = new std::string(yystr, j); free(yystr); return TOK_STRING; } -. { yymore(); real_location = old_location; } +. { yymore(); } and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 { - yylval->string = new std::string(yytext); + frontend_verilog_yylval.string = new std::string(yytext); return TOK_PRIMITIVE; } @@ -374,56 +306,31 @@ supply0 { return TOK_SUPPLY0; } supply1 { return TOK_SUPPLY1; } "$"(display|write|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) { - yylval->string = new std::string(yytext); + frontend_verilog_yylval.string = new std::string(yytext); return TOK_ID; } "$"(setup|hold|setuphold|removal|recovery|recrem|skew|timeskew|fullskew|nochange) { if (!specify_mode) REJECT; - yylval->string = new std::string(yytext); + frontend_verilog_yylval.string = new std::string(yytext); return TOK_ID; } "$"(info|warning|error|fatal) { - yylval->string = new std::string(yytext); + frontend_verilog_yylval.string = new std::string(yytext); return TOK_MSG_TASKS; } "$signed" { return TOK_TO_SIGNED; } "$unsigned" { return TOK_TO_UNSIGNED; } -[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* { - // package qualifier - auto s = std::string("\\") + yytext; - if (pkg_user_types.count(s) > 0) { - // package qualified typedefed name - yylval->string = new std::string(s); - return TOK_PKG_USER_TYPE; - } - else { - // backup before :: just return first part - size_t len = strchr(yytext, ':') - yytext; - yyless(len); - yylval->string = new std::string(std::string("\\") + yytext); - return TOK_ID; - } -} - [a-zA-Z_$][a-zA-Z0-9_$]* { - auto s = std::string("\\") + yytext; - if (isUserType(s)) { - // previously typedefed name - yylval->string = new std::string(s); - return TOK_USER_TYPE; - } - else { - yylval->string = new std::string(std::string("\\") + yytext); - return TOK_ID; - } + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + return TOK_ID; } [a-zA-Z_$][a-zA-Z0-9_$\.]* { - yylval->string = new std::string(std::string("\\") + yytext); + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); return TOK_ID; } @@ -470,7 +377,7 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { } [a-zA-Z_$][a-zA-Z0-9_$]* { - yylval->string = new std::string(std::string("\\") + yytext); + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); return TOK_ID; } @@ -486,7 +393,7 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { } "\\"[^ \t\r\n]+ { - yylval->string = new std::string(yytext); + frontend_verilog_yylval.string = new std::string(yytext); return TOK_ID; } @@ -524,36 +431,27 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { "+:" { return TOK_POS_INDEXED; } "-:" { return TOK_NEG_INDEXED; } -".*" { return TOK_WILDCARD_CONNECT; } - -"|=" { SV_KEYWORD(TOK_OR_ASSIGN); } -"&=" { SV_KEYWORD(TOK_AND_ASSIGN); } -"+=" { SV_KEYWORD(TOK_PLUS_ASSIGN); } -"-=" { SV_KEYWORD(TOK_SUB_ASSIGN); } -"^=" { SV_KEYWORD(TOK_XOR_ASSIGN); } - [-+]?[=*]> { if (!specify_mode) REJECT; - yylval->string = new std::string(yytext); + frontend_verilog_yylval.string = new std::string(yytext); return TOK_SPECIFY_OPER; } "&&&" { - if (!specify_mode) return TOK_IGNORED_SPECIFY_AND; + if (!specify_mode) REJECT; return TOK_SPECIFY_AND; } -"/*" { comment_caller=YY_START; BEGIN(COMMENT); } +"/*" { BEGIN(COMMENT); } . /* ignore comment body */ \n /* ignore comment body */ -"*/" { BEGIN(comment_caller); } +"*/" { BEGIN(0); } -[ \t\r\n] /* ignore whitespaces */ -\\[\r\n] /* ignore continuation sequence */ -"//"[^\r\n]* /* ignore one-line comments */ +[ \t\r\n] /* ignore whitespaces */ +\\[\r\n] /* ignore continuation sequence */ +"//"[^\r\n]* /* ignore one-line comments */ -. { return *yytext; } -<*>. { BEGIN(0); return *yytext; } +. { return *yytext; } %% diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 96d9299fec4..a30935e0a3d 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -38,11 +38,8 @@ #include #include #include "frontends/verilog/verilog_frontend.h" -#include "frontends/verilog/verilog_parser.tab.hh" #include "kernel/log.h" -#define YYLEX_PARAM &yylval, &yylloc - USING_YOSYS_NAMESPACE using namespace AST; using namespace VERILOG_FRONTEND; @@ -50,12 +47,10 @@ using namespace VERILOG_FRONTEND; YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { int port_counter; - dict port_stubs; - dict *attr_list, default_attr_list; - std::stack *> attr_list_stack; - dict *albuf; - std::vector user_type_stack; - dict pkg_user_types; + std::map port_stubs; + std::map *attr_list, default_attr_list; + std::stack *> attr_list_stack; + std::map *albuf; std::vector ast_stack; struct AstNode *astbuf1, *astbuf2, *astbuf3; struct AstNode *current_function_or_task; @@ -73,21 +68,7 @@ namespace VERILOG_FRONTEND { } YOSYS_NAMESPACE_END -#define SET_AST_NODE_LOC(WHICH, BEGIN, END) \ - do { (WHICH)->location.first_line = (BEGIN).first_line; \ - (WHICH)->location.first_column = (BEGIN).first_column; \ - (WHICH)->location.last_line = (END).last_line; \ - (WHICH)->location.last_column = (END).last_column; } while(0) - -#define SET_RULE_LOC(LHS, BEGIN, END) \ - do { (LHS).first_line = (BEGIN).first_line; \ - (LHS).first_column = (BEGIN).first_column; \ - (LHS).last_line = (END).last_line; \ - (LHS).last_column = (END).last_column; } while(0) - -int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); - -static void append_attr(AstNode *ast, dict *al) +static void append_attr(AstNode *ast, std::map *al) { for (auto &it : *al) { if (ast->attributes.count(it.first) > 0) @@ -97,7 +78,7 @@ static void append_attr(AstNode *ast, dict *al) delete al; } -static void append_attr_clone(AstNode *ast, dict *al) +static void append_attr_clone(AstNode *ast, std::map *al) { for (auto &it : *al) { if (ast->attributes.count(it.first) > 0) @@ -106,7 +87,7 @@ static void append_attr_clone(AstNode *ast, dict *al) } } -static void free_attr(dict *al) +static void free_attr(std::map *al) { for (auto &it : *al) delete it.second; @@ -127,104 +108,9 @@ struct specify_rise_fall { specify_triple fall; }; -static void addTypedefNode(std::string *name, AstNode *node) -{ - log_assert(node); - auto *tnode = new AstNode(AST_TYPEDEF, node); - tnode->str = *name; - auto user_types = user_type_stack.back(); - (*user_types)[*name] = tnode; - if (current_ast_mod && current_ast_mod->type == AST_PACKAGE) { - // typedef inside a package so we need the qualified name - auto qname = current_ast_mod->str + "::" + (*name).substr(1); - pkg_user_types[qname] = tnode; - } - delete name; - ast_stack.back()->children.push_back(tnode); -} - -static void enterTypeScope() -{ - auto user_types = new UserTypeMap(); - user_type_stack.push_back(user_types); -} - -static void exitTypeScope() -{ - user_type_stack.pop_back(); -} - -static bool isInLocalScope(const std::string *name) -{ - // tests if a name was declared in the current block scope - auto user_types = user_type_stack.back(); - return (user_types->count(*name) > 0); -} - -static AstNode *getTypeDefinitionNode(std::string type_name) -{ - // return the definition nodes from the typedef statement - auto user_types = user_type_stack.back(); - log_assert(user_types->count(type_name) > 0); - auto typedef_node = (*user_types)[type_name]; - log_assert(typedef_node->type == AST_TYPEDEF); - return typedef_node->children[0]; -} - -static AstNode *copyTypeDefinition(std::string type_name) -{ - // return a copy of the template from a typedef definition - auto typedef_node = getTypeDefinitionNode(type_name); - return typedef_node->clone(); -} - -static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true) -{ - auto range = new AstNode(AST_RANGE); - range->children.push_back(AstNode::mkconst_int(msb, true)); - range->children.push_back(AstNode::mkconst_int(lsb, true)); - range->is_signed = isSigned; - return range; -} - -static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned = true) -{ - auto range = makeRange(msb, lsb, isSigned); - parent->children.push_back(range); -} - -static AstNode *checkRange(AstNode *type_node, AstNode *range_node) -{ - if (type_node->range_left >= 0 && type_node->range_right >= 0) { - // type already restricts the range - if (range_node) { - frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); - } - else { - range_node = makeRange(type_node->range_left, type_node->range_right, false); - } - } - if (range_node && range_node->children.size() != 2) { - frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [:], [+:], or [-:]"); - } - return range_node; -} - -static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) -{ - node->type = AST_MEMORY; - if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { - // SV array size [n], rewrite as [n-1:0] - rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); - rangeNode->children.push_back(AstNode::mkconst_int(0, false)); - } - node->children.push_back(rangeNode); -} - %} %define api.prefix {frontend_verilog_yy} -%define api.pure /* The union is defined in the header, so we need to provide all the * includes it requires @@ -238,7 +124,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %union { std::string *string; struct YOSYS_NAMESPACE_PREFIX AST::AstNode *ast; - YOSYS_NAMESPACE_PREFIX dict *al; + std::map *al; struct specify_target *specify_target_ptr; struct specify_triple *specify_triple_ptr; struct specify_rise_fall *specify_rise_fall_ptr; @@ -248,43 +134,36 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE %token TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS -%token TOK_BASE TOK_BASED_CONSTVAL TOK_UNBASED_UNSIZED_CONSTVAL -%token TOK_USER_TYPE TOK_PKG_USER_TYPE %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP -%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR TOK_WILDCARD_CONNECT +%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR TOK_REG TOK_LOGIC -%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_PLUS_ASSIGN TOK_ALWAYS TOK_INITIAL +%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL %token TOK_ALWAYS_FF TOK_ALWAYS_COMB TOK_ALWAYS_LATCH %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC %token TOK_CASE TOK_CASEX TOK_CASEZ TOK_ENDCASE TOK_DEFAULT %token TOK_FUNCTION TOK_ENDFUNCTION TOK_TASK TOK_ENDTASK TOK_SPECIFY -%token TOK_IGNORED_SPECIFY TOK_ENDSPECIFY TOK_SPECPARAM TOK_SPECIFY_AND TOK_IGNORED_SPECIFY_AND +%token TOK_IGNORED_SPECIFY TOK_ENDSPECIFY TOK_SPECPARAM TOK_SPECIFY_AND %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY -%token TOK_STRUCT TOK_PACKED TOK_UNSIGNED TOK_INT TOK_BYTE TOK_SHORTINT TOK_UNION -%token TOK_OR_ASSIGN TOK_XOR_ASSIGN TOK_AND_ASSIGN TOK_SUB_ASSIGN %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number -%type type_name -%type opt_enum_init enum_type struct_type non_wire_data_type +%type opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id %type opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff %type attr case_attr -%type struct_union %type specify_target -%type specify_triple specify_opt_triple +%type specify_triple %type specify_rise_fall -%type specify_if specify_condition +%type specify_if specify_condition specify_opt_arg %type specify_edge // operator precedence from low to high @@ -308,7 +187,6 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %nonassoc TOK_ELSE %debug -%locations %% @@ -338,7 +216,7 @@ attr: { if (attr_list != nullptr) attr_list_stack.push(attr_list); - attr_list = new dict; + attr_list = new std::map; for (auto &it : default_attr_list) (*attr_list)[it.first] = it.second->clone(); } attr_opt { @@ -351,16 +229,14 @@ attr: }; attr_opt: - attr_opt ATTR_BEGIN opt_attr_list ATTR_END { - SET_RULE_LOC(@$, @2, @$); - }| + attr_opt ATTR_BEGIN opt_attr_list ATTR_END | /* empty */; defattr: DEFATTR_BEGIN { if (attr_list != nullptr) attr_list_stack.push(attr_list); - attr_list = new dict; + attr_list = new std::map; for (auto &it : default_attr_list) delete it.second; default_attr_list.clear(); @@ -417,15 +293,10 @@ hierarchical_id: }; hierarchical_type_id: - TOK_USER_TYPE - | TOK_PKG_USER_TYPE // package qualified type name - | '(' TOK_USER_TYPE ')' { $$ = $2; } // non-standard grammar - ; + '(' hierarchical_id ')' { $$ = $2; }; module: - attr TOK_MODULE { - enterTypeScope(); - } TOK_ID { + attr TOK_MODULE TOK_ID { do_not_require_port_stubs = false; AstNode *mod = new AstNode(AST_MODULE); ast_stack.back()->children.push_back(mod); @@ -433,18 +304,16 @@ module: current_ast_mod = mod; port_stubs.clear(); port_counter = 0; - mod->str = *$4; + mod->str = *$3; append_attr(mod, $1); - delete $4; - } module_para_opt module_args_opt ';' module_body TOK_ENDMODULE opt_label { + delete $3; + } module_para_opt module_args_opt ';' module_body TOK_ENDMODULE { if (port_stubs.size() != 0) frontend_verilog_yyerror("Missing details for module port `%s'.", port_stubs.begin()->first.c_str()); - SET_AST_NODE_LOC(ast_stack.back(), @2, @$); ast_stack.pop_back(); log_assert(ast_stack.size() == 1); current_ast_mod = NULL; - exitTypeScope(); }; module_para_opt: @@ -485,9 +354,9 @@ module_arg_opt_assignment: wire->str = ast_stack.back()->children.back()->str; if (ast_stack.back()->children.back()->is_input) { AstNode *n = ast_stack.back()->children.back(); - if (n->attributes.count(ID::defaultvalue)) - delete n->attributes.at(ID::defaultvalue); - n->attributes[ID::defaultvalue] = $2; + if (n->attributes.count("\\defaultvalue")) + delete n->attributes.at("\\defaultvalue"); + n->attributes["\\defaultvalue"] = $2; } else if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic) ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2)))); @@ -505,7 +374,6 @@ module_arg: node->str = *$1; node->port_id = ++port_counter; ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @1, @1); } else { if (port_stubs.count(*$1) != 0) frontend_verilog_yyerror("Duplicate module port `%s'.", $1->c_str()); @@ -531,7 +399,6 @@ module_arg: attr wire_type range TOK_ID { AstNode *node = $2; node->str = *$4; - SET_AST_NODE_LOC(node, @4, @4); node->port_id = ++port_counter; if ($3 != NULL) node->children.push_back($3); @@ -548,36 +415,27 @@ module_arg: }; package: - attr TOK_PACKAGE { - enterTypeScope(); - } TOK_ID { + attr TOK_PACKAGE TOK_ID { AstNode *mod = new AstNode(AST_PACKAGE); ast_stack.back()->children.push_back(mod); ast_stack.push_back(mod); current_ast_mod = mod; - mod->str = *$4; + mod->str = *$3; append_attr(mod, $1); - } ';' package_body TOK_ENDPACKAGE opt_label { + } ';' package_body TOK_ENDPACKAGE { ast_stack.pop_back(); current_ast_mod = NULL; - exitTypeScope(); }; package_body: - package_body package_body_stmt - | // optional - ; + package_body package_body_stmt |; package_body_stmt: - typedef_decl - | localparam_decl - | param_decl - ; + typedef_decl | + localparam_decl; interface: - TOK_INTERFACE { - enterTypeScope(); - } TOK_ID { + TOK_INTERFACE TOK_ID { do_not_require_port_stubs = false; AstNode *intf = new AstNode(AST_INTERFACE); ast_stack.back()->children.push_back(intf); @@ -585,8 +443,8 @@ interface: current_ast_mod = intf; port_stubs.clear(); port_counter = 0; - intf->str = *$3; - delete $3; + intf->str = *$2; + delete $2; } module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE { if (port_stubs.size() != 0) frontend_verilog_yyerror("Missing details for module port `%s'.", @@ -594,7 +452,6 @@ interface: ast_stack.pop_back(); log_assert(ast_stack.size() == 1); current_ast_mod = NULL; - exitTypeScope(); }; interface_body: @@ -619,9 +476,8 @@ wire_type: astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; - } wire_type_token_list { + } wire_type_token_list delay { $$ = astbuf3; - SET_RULE_LOC(@$, @2, @$); }; wire_type_token_list: @@ -632,7 +488,6 @@ wire_type_token_list: astbuf3->is_custom_type = true; astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); astbuf3->children.back()->str = *$1; - delete $1; }; wire_type_token_io: @@ -696,15 +551,13 @@ non_opt_range: } | '[' expr TOK_POS_INDEXED expr ']' { $$ = new AstNode(AST_RANGE); - AstNode *expr = new AstNode(AST_SELFSZ, $2); - $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), $4), AstNode::mkconst_int(1, true))); - $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); + $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, $2->clone(), $4), AstNode::mkconst_int(1, true))); + $$->children.push_back(new AstNode(AST_ADD, $2, AstNode::mkconst_int(0, true))); } | '[' expr TOK_NEG_INDEXED expr ']' { $$ = new AstNode(AST_RANGE); - AstNode *expr = new AstNode(AST_SELFSZ, $2); - $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); - $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), AstNode::mkconst_int(1, true)), $4)); + $$->children.push_back(new AstNode(AST_ADD, $2, AstNode::mkconst_int(0, true))); + $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, $2->clone(), AstNode::mkconst_int(1, true)), $4)); } | '[' expr ']' { $$ = new AstNode(AST_RANGE); @@ -733,9 +586,15 @@ range_or_multirange: non_opt_multirange { $$ = $1; }; range_or_signed_int: - range { $$ = $1; } - | TOK_INTEGER { $$ = makeRange(); } - ; + range { + $$ = $1; + } | + TOK_INTEGER { + $$ = new AstNode(AST_RANGE); + $$->children.push_back(AstNode::mkconst_int(31, true)); + $$->children.push_back(AstNode::mkconst_int(0, true)); + $$->is_signed = true; + }; module_body: module_body module_body_stmt | @@ -745,7 +604,6 @@ module_body: module_body_stmt: task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | - enum_decl | struct_decl | always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block; checker_decl: @@ -886,20 +744,19 @@ task_func_port: } albuf = $1; astbuf1 = $2; - astbuf2 = checkRange(astbuf1, $3); - } wire_name | - { - if (!astbuf1) { - if (!sv_mode) - frontend_verilog_yyerror("task/function argument direction missing"); - albuf = new dict; - astbuf1 = new AstNode(AST_WIRE); - current_wire_rand = false; - current_wire_const = false; - astbuf1->is_input = true; - astbuf2 = NULL; + astbuf2 = $3; + if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { + if (astbuf2) { + frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions (task/function arguments)"); + } else { + astbuf2 = new AstNode(AST_RANGE); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); + } } - } wire_name; + if (astbuf2 && astbuf2->children.size() != 2) + frontend_verilog_yyerror("task/function argument range must be of the form: [:], [+:], or [-:]"); + } wire_name | wire_name; task_func_body: task_func_body behavioral_stmt | @@ -931,7 +788,6 @@ specify_item: cell->str = stringf("$specify$%d", autoidx++); cell->children.push_back(new AstNode(AST_CELLTYPE)); cell->children.back()->str = target->dat ? "$specify3" : "$specify2"; - SET_AST_NODE_LOC(cell, en_expr ? @1 : @2, @10); char oper_polarity = 0; char oper_type = oper->at(0); @@ -999,7 +855,7 @@ specify_item: delete target; delete timing; } | - TOK_ID '(' specify_edge expr specify_condition ',' specify_edge expr specify_condition ',' specify_triple specify_opt_triple ')' ';' { + TOK_ID '(' specify_edge expr specify_condition ',' specify_edge expr specify_condition ',' expr specify_opt_arg ')' ';' { if (*$1 != "$setup" && *$1 != "$hold" && *$1 != "$setuphold" && *$1 != "$removal" && *$1 != "$recovery" && *$1 != "$recrem" && *$1 != "$skew" && *$1 != "$timeskew" && *$1 != "$fullskew" && *$1 != "$nochange") frontend_verilog_yyerror("Unsupported specify rule type: %s\n", $1->c_str()); @@ -1012,36 +868,23 @@ specify_item: AstNode *dst_pol = AstNode::mkconst_int($7 == 'p', false, 1); AstNode *dst_expr = $8, *dst_en = $9 ? $9 : AstNode::mkconst_int(1, false, 1); - specify_triple *limit = $11; - specify_triple *limit2 = $12; + AstNode *limit = $11; + AstNode *limit2 = $12; AstNode *cell = new AstNode(AST_CELL); ast_stack.back()->children.push_back(cell); cell->str = stringf("$specify$%d", autoidx++); cell->children.push_back(new AstNode(AST_CELLTYPE)); cell->children.back()->str = "$specrule"; - SET_AST_NODE_LOC(cell, @1, @14); cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_str(*$1))); cell->children.back()->str = "\\TYPE"; - cell->children.push_back(new AstNode(AST_PARASET, limit->t_min)); - cell->children.back()->str = "\\T_LIMIT_MIN"; - - cell->children.push_back(new AstNode(AST_PARASET, limit->t_avg)); - cell->children.back()->str = "\\T_LIMIT_TYP"; + cell->children.push_back(new AstNode(AST_PARASET, limit)); + cell->children.back()->str = "\\T_LIMIT"; - cell->children.push_back(new AstNode(AST_PARASET, limit->t_max)); - cell->children.back()->str = "\\T_LIMIT_MAX"; - - cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2->t_min : AstNode::mkconst_int(0, true))); - cell->children.back()->str = "\\T_LIMIT2_MIN"; - - cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2->t_avg : AstNode::mkconst_int(0, true))); - cell->children.back()->str = "\\T_LIMIT2_TYP"; - - cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2->t_max : AstNode::mkconst_int(0, true))); - cell->children.back()->str = "\\T_LIMIT2_MAX"; + cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2 : AstNode::mkconst_int(0, true))); + cell->children.back()->str = "\\T_LIMIT2"; cell->children.push_back(new AstNode(AST_PARASET, src_pen)); cell->children.back()->str = "\\SRC_PEN"; @@ -1070,8 +913,8 @@ specify_item: delete $1; }; -specify_opt_triple: - ',' specify_triple { +specify_opt_arg: + ',' expr { $$ = $2; } | /* empty */ { @@ -1140,46 +983,7 @@ specify_rise_fall: $$->fall = *$4; delete $2; delete $4; - } | - '(' specify_triple ',' specify_triple ',' specify_triple ')' { - $$ = new specify_rise_fall; - $$->rise = *$2; - $$->fall = *$4; - delete $2; - delete $4; - delete $6; - log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); - } | - '(' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ')' { - $$ = new specify_rise_fall; - $$->rise = *$2; - $$->fall = *$4; - delete $2; - delete $4; - delete $6; - delete $8; - delete $10; - delete $12; - log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); - } | - '(' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ')' { - $$ = new specify_rise_fall; - $$->rise = *$2; - $$->fall = *$4; - delete $2; - delete $4; - delete $6; - delete $8; - delete $10; - delete $12; - delete $14; - delete $16; - delete $18; - delete $20; - delete $22; - delete $24; - log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); - } + }; specify_triple: expr { @@ -1227,7 +1031,7 @@ list_of_specparam_assignments: specparam_assignment | list_of_specparam_assignments ',' specparam_assignment; specparam_assignment: - ignspec_id '=' ignspec_expr ; + ignspec_id '=' constant_mintypmax_expression ; ignspec_opt_cond: TOK_IF '(' ignspec_expr ')' | /* empty */; @@ -1244,15 +1048,13 @@ simple_path_declaration : ; path_delay_value : - '(' ignspec_expr list_of_path_delay_extra_expressions ')' - | ignspec_expr - | ignspec_expr list_of_path_delay_extra_expressions + '(' path_delay_expression list_of_path_delay_extra_expressions ')' + | path_delay_expression + | path_delay_expression list_of_path_delay_extra_expressions ; list_of_path_delay_extra_expressions : - ',' ignspec_expr - | ',' ignspec_expr list_of_path_delay_extra_expressions - ; + ',' path_delay_expression | ',' path_delay_expression list_of_path_delay_extra_expressions; specify_edge_identifier : TOK_POSEDGE | TOK_NEGEDGE ; @@ -1303,9 +1105,16 @@ system_timing_arg : system_timing_args : system_timing_arg | - system_timing_args TOK_IGNORED_SPECIFY_AND system_timing_arg | system_timing_args ',' system_timing_arg ; +path_delay_expression : + ignspec_constant_expression; + +constant_mintypmax_expression : + ignspec_constant_expression + | ignspec_constant_expression ':' ignspec_constant_expression ':' ignspec_constant_expression + ; + // for the time being this is OK, but we may write our own expr here. // as I'm not sure it is legal to use a full expr here (probably not) // On the other hand, other rules requiring constant expressions also use 'expr' @@ -1314,16 +1123,10 @@ ignspec_constant_expression: expr { delete $1; }; ignspec_expr: - expr { delete $1; } | - expr ':' expr ':' expr { - delete $1; - delete $3; - delete $5; - }; + expr { delete $1; }; ignspec_id: - TOK_ID { delete $1; } - range_or_multirange { delete $3; }; + TOK_ID { delete $1; }; /**********************************************************************/ @@ -1421,206 +1224,23 @@ single_defparam_decl: ast_stack.back()->children.push_back(node); }; -///////// -// enum -///////// - -enum_type: TOK_ENUM { - static int enum_count; - // create parent node for the enum - astbuf2 = new AstNode(AST_ENUM); - ast_stack.back()->children.push_back(astbuf2); - astbuf2->str = std::string("$enum"); - astbuf2->str += std::to_string(enum_count++); - // create the template for the names - astbuf1 = new AstNode(AST_ENUM_ITEM); - astbuf1->children.push_back(AstNode::mkconst_int(0, true)); - } enum_base_type '{' enum_name_list '}' { // create template for the enum vars - auto tnode = astbuf1->clone(); - delete astbuf1; - astbuf1 = tnode; - tnode->type = AST_WIRE; - tnode->attributes[ID::enum_type] = AstNode::mkconst_str(astbuf2->str); - // drop constant but keep any range - delete tnode->children[0]; - tnode->children.erase(tnode->children.begin()); - $$ = astbuf1; } - ; - -enum_base_type: type_atom type_signing - | type_vec type_signing range { if ($3) astbuf1->children.push_back($3); } - | /* nothing */ { astbuf1->is_reg = true; addRange(astbuf1); } - ; - -type_atom: TOK_INTEGER { astbuf1->is_reg = true; addRange(astbuf1); } // 4-state signed - | TOK_INT { astbuf1->is_reg = true; addRange(astbuf1); } // 2-state signed - | TOK_SHORTINT { astbuf1->is_reg = true; addRange(astbuf1, 15, 0); } // 2-state signed - | TOK_BYTE { astbuf1->is_reg = true; addRange(astbuf1, 7, 0); } // 2-state signed - ; - -type_vec: TOK_REG { astbuf1->is_reg = true; } // unsigned - | TOK_LOGIC { astbuf1->is_logic = true; } // unsigned - ; - -type_signing: - TOK_SIGNED { astbuf1->is_signed = true; } - | TOK_UNSIGNED { astbuf1->is_signed = false; } - | // optional - ; - -enum_name_list: enum_name_decl - | enum_name_list ',' enum_name_decl - ; - -enum_name_decl: - TOK_ID opt_enum_init { - // put in fn - log_assert(astbuf1); - log_assert(astbuf2); - auto node = astbuf1->clone(); - node->str = *$1; - delete $1; - SET_AST_NODE_LOC(node, @1, @1); - delete node->children[0]; - node->children[0] = $2 ? $2 : new AstNode(AST_NONE); - astbuf2->children.push_back(node); - } - ; - -opt_enum_init: - '=' basic_expr { $$ = $2; } // TODO: restrict this - | /* optional */ { $$ = NULL; } - ; - -enum_var_list: - enum_var - | enum_var_list ',' enum_var - ; - -enum_var: TOK_ID { - log_assert(astbuf1); - log_assert(astbuf2); - auto node = astbuf1->clone(); - ast_stack.back()->children.push_back(node); - node->str = *$1; - delete $1; - SET_AST_NODE_LOC(node, @1, @1); - node->is_enum = true; - } - ; - -enum_decl: enum_type enum_var_list ';' { delete $1; } - ; - -////////////////// -// struct or union -////////////////// - -struct_decl: struct_type struct_var_list ';' { delete astbuf2; } - ; - -struct_type: struct_union { astbuf2 = $1; } struct_body { $$ = astbuf2; } - ; - -struct_union: - TOK_STRUCT { $$ = new AstNode(AST_STRUCT); } - | TOK_UNION { $$ = new AstNode(AST_UNION); } - ; - -struct_body: opt_packed '{' struct_member_list '}' - ; - -opt_packed: TOK_PACKED opt_signed_struct - | { frontend_verilog_yyerror("Only PACKED supported at this time"); } - ; - -opt_signed_struct: - TOK_SIGNED { astbuf2->is_signed = true; } - | TOK_UNSIGNED { astbuf2->is_signed = false; } - | // default is unsigned - ; - -struct_member_list: struct_member - | struct_member_list struct_member - ; - -struct_member: struct_member_type member_name_list ';' { delete astbuf1; } - ; - -member_name_list: - member_name - | member_name_list ',' member_name - ; - -member_name: TOK_ID { - astbuf1->str = $1->substr(1); - delete $1; - astbuf3 = astbuf1->clone(); - SET_AST_NODE_LOC(astbuf3, @1, @1); - astbuf2->children.push_back(astbuf3); - } range { if ($3) astbuf3->children.push_back($3); } - ; - -struct_member_type: { astbuf1 = new AstNode(AST_STRUCT_ITEM); } member_type_token - ; - -member_type_token: - member_type - | hierarchical_type_id { - // use a clone of the typedef definition nodes - auto template_node = copyTypeDefinition(*$1); - delete $1; - switch (template_node->type) { - case AST_WIRE: - template_node->type = AST_STRUCT_ITEM; - break; - case AST_STRUCT: - case AST_UNION: - break; - default: - frontend_verilog_yyerror("Invalid type for struct member: %s", type2str(template_node->type).c_str()); - } - delete astbuf1; - astbuf1 = template_node; - } - | struct_union { - // stash state on ast_stack - ast_stack.push_back(astbuf2); - astbuf2 = $1; - } struct_body { - astbuf1 = astbuf2; - // recover state - astbuf2 = ast_stack.back(); - ast_stack.pop_back(); - } - ; - -member_type: type_atom type_signing - | type_vec type_signing range_or_multirange { if ($3) astbuf1->children.push_back($3); } - ; - -struct_var_list: struct_var - | struct_var_list ',' struct_var - ; - -struct_var: TOK_ID { auto *var_node = astbuf2->clone(); - var_node->str = *$1; - delete $1; - SET_AST_NODE_LOC(var_node, @1, @1); - ast_stack.back()->children.push_back(var_node); - } - ; - -///////// -// wire -///////// - wire_decl: attr wire_type range { albuf = $1; astbuf1 = $2; - astbuf2 = checkRange(astbuf1, $3); - } delay wire_name_list { + astbuf2 = $3; + if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { + if (astbuf2) { + frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); + } else { + astbuf2 = new AstNode(AST_RANGE); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); + } + } + if (astbuf2 && astbuf2->children.size() != 2) + frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [:], [+:], or [-:]"); + } wire_name_list { delete astbuf1; if (astbuf2 != NULL) delete astbuf2; @@ -1664,24 +1284,24 @@ wire_name_and_opt_assign: bool attr_anyseq = false; bool attr_allconst = false; bool attr_allseq = false; - if (ast_stack.back()->children.back()->get_bool_attribute(ID::anyconst)) { - delete ast_stack.back()->children.back()->attributes.at(ID::anyconst); - ast_stack.back()->children.back()->attributes.erase(ID::anyconst); + if (ast_stack.back()->children.back()->get_bool_attribute("\\anyconst")) { + delete ast_stack.back()->children.back()->attributes.at("\\anyconst"); + ast_stack.back()->children.back()->attributes.erase("\\anyconst"); attr_anyconst = true; } - if (ast_stack.back()->children.back()->get_bool_attribute(ID::anyseq)) { - delete ast_stack.back()->children.back()->attributes.at(ID::anyseq); - ast_stack.back()->children.back()->attributes.erase(ID::anyseq); + if (ast_stack.back()->children.back()->get_bool_attribute("\\anyseq")) { + delete ast_stack.back()->children.back()->attributes.at("\\anyseq"); + ast_stack.back()->children.back()->attributes.erase("\\anyseq"); attr_anyseq = true; } - if (ast_stack.back()->children.back()->get_bool_attribute(ID::allconst)) { - delete ast_stack.back()->children.back()->attributes.at(ID::allconst); - ast_stack.back()->children.back()->attributes.erase(ID::allconst); + if (ast_stack.back()->children.back()->get_bool_attribute("\\allconst")) { + delete ast_stack.back()->children.back()->attributes.at("\\allconst"); + ast_stack.back()->children.back()->attributes.erase("\\allconst"); attr_allconst = true; } - if (ast_stack.back()->children.back()->get_bool_attribute(ID::allseq)) { - delete ast_stack.back()->children.back()->attributes.at(ID::allseq); - ast_stack.back()->children.back()->attributes.erase(ID::allseq); + if (ast_stack.back()->children.back()->get_bool_attribute("\\allseq")) { + delete ast_stack.back()->children.back()->attributes.at("\\allseq"); + ast_stack.back()->children.back()->attributes.erase("\\allseq"); attr_allseq = true; } if (current_wire_rand || attr_anyconst || attr_anyseq || attr_allconst || attr_allseq) { @@ -1697,7 +1317,7 @@ wire_name_and_opt_assign: fcall->str = "\\$allconst"; if (attr_allseq) fcall->str = "\\$allseq"; - fcall->attributes[ID::reg] = AstNode::mkconst_str(RTLIL::unescape_id(wire->str)); + fcall->attributes["\\reg"] = AstNode::mkconst_str(RTLIL::unescape_id(wire->str)); ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, fcall)); } } | @@ -1705,27 +1325,14 @@ wire_name_and_opt_assign: AstNode *wire = new AstNode(AST_IDENTIFIER); wire->str = ast_stack.back()->children.back()->str; if (astbuf1->is_input) { - if (astbuf1->attributes.count(ID::defaultvalue)) - delete astbuf1->attributes.at(ID::defaultvalue); - astbuf1->attributes[ID::defaultvalue] = $3; - } - else if (astbuf1->is_reg || astbuf1->is_logic){ - AstNode *assign = new AstNode(AST_ASSIGN_LE, wire, $3); - AstNode *block = new AstNode(AST_BLOCK, assign); - AstNode *init = new AstNode(AST_INITIAL, block); - - SET_AST_NODE_LOC(assign, @1, @3); - SET_AST_NODE_LOC(block, @1, @3); - SET_AST_NODE_LOC(init, @1, @3); - - ast_stack.back()->children.push_back(init); - } - else { - AstNode *assign = new AstNode(AST_ASSIGN, wire, $3); - SET_AST_NODE_LOC(assign, @1, @3); - ast_stack.back()->children.push_back(assign); - } - + if (astbuf1->attributes.count("\\defaultvalue")) + delete astbuf1->attributes.at("\\defaultvalue"); + astbuf1->attributes["\\defaultvalue"] = $3; + } else + if (astbuf1->is_reg || astbuf1->is_logic) + ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3)))); + else + ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3)); }; wire_name: @@ -1741,9 +1348,19 @@ wire_name: if (node->is_input || node->is_output) frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); if (!astbuf2 && !node->is_custom_type) { - addRange(node, 0, 0, false); + AstNode *rng = new AstNode(AST_RANGE); + rng->children.push_back(AstNode::mkconst_int(0, true)); + rng->children.push_back(AstNode::mkconst_int(0, true)); + node->children.push_back(rng); } - rewriteAsMemoryNode(node, $2); + node->type = AST_MEMORY; + auto *rangeNode = $2; + if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { + // SV array size [n], rewrite as [n-1:0] + rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); + rangeNode->children.push_back(AstNode::mkconst_int(0, false)); + } + node->children.push_back(rangeNode); } if (current_function_or_task == NULL) { if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) { @@ -1764,8 +1381,6 @@ wire_name: if (node->is_input || node->is_output) node->port_id = current_function_or_task_port_id++; } - //FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column... - SET_AST_NODE_LOC(node, @1, @1); ast_stack.back()->children.push_back(node); delete $1; @@ -1779,36 +1394,47 @@ assign_expr_list: assign_expr: lvalue '=' expr { - AstNode *node = new AstNode(AST_ASSIGN, $1, $3); - SET_AST_NODE_LOC(node, @$, @$); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3)); }; -type_name: TOK_ID // first time seen - | TOK_USER_TYPE { if (isInLocalScope($1)) frontend_verilog_yyerror("Duplicate declaration of TYPEDEF '%s'", $1->c_str()+1); } - ; - typedef_decl: - TOK_TYPEDEF wire_type range type_name range_or_multirange ';' { + TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' { astbuf1 = $2; - astbuf2 = checkRange(astbuf1, $3); + astbuf2 = $3; + if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { + if (astbuf2) { + frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); + } else { + astbuf2 = new AstNode(AST_RANGE); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); + } + } + if (astbuf2 && astbuf2->children.size() != 2) + frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [:], [+:], or [-:]"); if (astbuf2) astbuf1->children.push_back(astbuf2); if ($5 != NULL) { if (!astbuf2) { - addRange(astbuf1, 0, 0, false); + AstNode *rng = new AstNode(AST_RANGE); + rng->children.push_back(AstNode::mkconst_int(0, true)); + rng->children.push_back(AstNode::mkconst_int(0, true)); + astbuf1->children.push_back(rng); } - rewriteAsMemoryNode(astbuf1, $5); + astbuf1->type = AST_MEMORY; + auto *rangeNode = $5; + if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { + // SV array size [n], rewrite as [n-1:0] + rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); + rangeNode->children.push_back(AstNode::mkconst_int(0, false)); + } + astbuf1->children.push_back(rangeNode); } - addTypedefNode($4, astbuf1); } - | TOK_TYPEDEF non_wire_data_type type_name ';' { addTypedefNode($3, $2); } - ; -non_wire_data_type: - enum_type - | struct_type - ; + ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); + ast_stack.back()->children.back()->str = *$4; + }; cell_stmt: attr TOK_ID { @@ -1848,18 +1474,14 @@ single_cell: astbuf2->str = *$1; delete $1; ast_stack.back()->children.push_back(astbuf2); - } '(' cell_port_list ')' { - SET_AST_NODE_LOC(astbuf2, @1, @$); - } | + } '(' cell_port_list ')' | TOK_ID non_opt_range { astbuf2 = astbuf1->clone(); if (astbuf2->type != AST_PRIMITIVE) astbuf2->str = *$1; delete $1; ast_stack.back()->children.push_back(new AstNode(AST_CELLARRAY, $2, astbuf2)); - } '(' cell_port_list ')'{ - SET_AST_NODE_LOC(astbuf2, @1, @$); - }; + } '(' cell_port_list ')'; prim_list: single_prim | @@ -1870,9 +1492,7 @@ single_prim: /* no name */ { astbuf2 = astbuf1->clone(); ast_stack.back()->children.push_back(astbuf2); - } '(' cell_port_list ')' { - SET_AST_NODE_LOC(astbuf2, @1, @$); - } + } '(' cell_port_list ')'; cell_parameter_list_opt: '#' '(' cell_parameter_list ')' | /* empty */; @@ -1960,11 +1580,6 @@ cell_port: node->children.back()->str = *$3; delete $3; free_attr($1); - } | - attr TOK_WILDCARD_CONNECT { - if (!sv_mode) - frontend_verilog_yyerror("Wildcard port connections are only supported in SystemVerilog mode."); - astbuf2->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(1, false); }; always_comb_or_latch: @@ -1988,7 +1603,7 @@ always_stmt: AstNode *node = new AstNode(AST_ALWAYS); append_attr(node, $1); if ($2) - node->attributes[ID::always_ff] = AstNode::mkconst_int(1, false); + node->attributes[ID(always_ff)] = AstNode::mkconst_int(1, false); ast_stack.back()->children.push_back(node); ast_stack.push_back(node); } always_cond { @@ -1996,21 +1611,16 @@ always_stmt: ast_stack.back()->children.push_back(block); ast_stack.push_back(block); } behavioral_stmt { - SET_AST_NODE_LOC(ast_stack.back(), @6, @6); ast_stack.pop_back(); - - SET_AST_NODE_LOC(ast_stack.back(), @2, @$); ast_stack.pop_back(); - - SET_RULE_LOC(@$, @2, @$); } | attr always_comb_or_latch { AstNode *node = new AstNode(AST_ALWAYS); append_attr(node, $1); if ($2) - node->attributes[ID::always_latch] = AstNode::mkconst_int(1, false); + node->attributes[ID(always_latch)] = AstNode::mkconst_int(1, false); else - node->attributes[ID::always_comb] = AstNode::mkconst_int(1, false); + node->attributes[ID(always_comb)] = AstNode::mkconst_int(1, false); ast_stack.back()->children.push_back(node); ast_stack.push_back(node); AstNode *block = new AstNode(AST_BLOCK); @@ -2049,13 +1659,11 @@ always_events: always_event: TOK_POSEDGE expr { AstNode *node = new AstNode(AST_POSEDGE); - SET_AST_NODE_LOC(node, @1, @1); ast_stack.back()->children.push_back(node); node->children.push_back($2); } | TOK_NEGEDGE expr { AstNode *node = new AstNode(AST_NEGEDGE); - SET_AST_NODE_LOC(node, @1, @1); ast_stack.back()->children.push_back(node); node->children.push_back($2); } | @@ -2133,7 +1741,6 @@ assert: delete $5; } else { AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); - SET_AST_NODE_LOC(node, @1, @6); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -2146,7 +1753,6 @@ assert: delete $5; } else { AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); - SET_AST_NODE_LOC(node, @1, @6); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -2159,7 +1765,6 @@ assert: delete $6; } else { AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); - SET_AST_NODE_LOC(node, @1, @7); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -2172,7 +1777,6 @@ assert: delete $6; } else { AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6); - SET_AST_NODE_LOC(node, @1, @7); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -2182,7 +1786,6 @@ assert: } | opt_sva_label TOK_COVER opt_property '(' expr ')' ';' { AstNode *node = new AstNode(AST_COVER, $5); - SET_AST_NODE_LOC(node, @1, @6); if ($1 != nullptr) { node->str = *$1; delete $1; @@ -2191,7 +1794,6 @@ assert: } | opt_sva_label TOK_COVER opt_property '(' ')' ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); - SET_AST_NODE_LOC(node, @1, @5); if ($1 != nullptr) { node->str = *$1; delete $1; @@ -2200,7 +1802,6 @@ assert: } | opt_sva_label TOK_COVER ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); - SET_AST_NODE_LOC(node, @1, @2); if ($1 != nullptr) { node->str = *$1; delete $1; @@ -2212,7 +1813,6 @@ assert: delete $5; } else { AstNode *node = new AstNode(AST_ASSUME, $5); - SET_AST_NODE_LOC(node, @1, @6); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -2227,7 +1827,6 @@ assert: delete $6; } else { AstNode *node = new AstNode(AST_FAIR, $6); - SET_AST_NODE_LOC(node, @1, @7); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -2240,45 +1839,35 @@ assert: assert_property: opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { - AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); - SET_AST_NODE_LOC(node, @1, @6); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { - AstNode *node = new AstNode(AST_ASSUME, $5); - SET_AST_NODE_LOC(node, @1, @6); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); - SET_AST_NODE_LOC(node, @1, @7); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - AstNode *node = new AstNode(AST_FAIR, $6); - SET_AST_NODE_LOC(node, @1, @7); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' { - AstNode *node = new AstNode(AST_COVER, $5); - SET_AST_NODE_LOC(node, @1, @6); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; @@ -2288,9 +1877,7 @@ assert_property: if (norestrict_mode) { delete $5; } else { - AstNode *node = new AstNode(AST_ASSUME, $5); - SET_AST_NODE_LOC(node, @1, @6); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; @@ -2301,9 +1888,7 @@ assert_property: if (norestrict_mode) { delete $6; } else { - AstNode *node = new AstNode(AST_FAIR, $6); - SET_AST_NODE_LOC(node, @1, @7); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; @@ -2312,115 +1897,62 @@ assert_property: }; simple_behavioral_stmt: - attr lvalue '=' delay expr { - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, $5); - ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @2, @5); - append_attr(node, $1); - } | - attr lvalue TOK_INCREMENT { - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, new AstNode(AST_ADD, $2->clone(), AstNode::mkconst_int(1, true))); - ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @2, @3); - append_attr(node, $1); - } | - attr lvalue TOK_DECREMENT { - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, new AstNode(AST_SUB, $2->clone(), AstNode::mkconst_int(1, true))); - ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @2, @3); - append_attr(node, $1); - } | - attr lvalue OP_LE delay expr { - AstNode *node = new AstNode(AST_ASSIGN_LE, $2, $5); - ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @2, @5); - append_attr(node, $1); - } | - attr lvalue TOK_XOR_ASSIGN delay expr { - AstNode *xor_node = new AstNode(AST_BIT_XOR, $2->clone(), $5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, xor_node); - SET_AST_NODE_LOC(xor_node, @2, @5); - SET_AST_NODE_LOC(node, @2, @5); - ast_stack.back()->children.push_back(node); - append_attr(node, $1); - } | - attr lvalue TOK_OR_ASSIGN delay expr { - AstNode *or_node = new AstNode(AST_BIT_OR, $2->clone(), $5); - SET_AST_NODE_LOC(or_node, @2, @5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, or_node); - SET_AST_NODE_LOC(node, @2, @5); + lvalue '=' delay expr { + AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4); ast_stack.back()->children.push_back(node); - append_attr(node, $1); } | - attr lvalue TOK_PLUS_ASSIGN delay expr { - AstNode *add_node = new AstNode(AST_ADD, $2->clone(), $5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, add_node); - SET_AST_NODE_LOC(node, @2, @5); - SET_AST_NODE_LOC(add_node, @2, @5); + lvalue TOK_INCREMENT { + AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_ADD, $1->clone(), AstNode::mkconst_int(1, true))); ast_stack.back()->children.push_back(node); - append_attr(node, $1); } | - attr lvalue TOK_SUB_ASSIGN delay expr { - AstNode *sub_node = new AstNode(AST_SUB, $2->clone(), $5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, sub_node); - SET_AST_NODE_LOC(node, @2, @5); - SET_AST_NODE_LOC(sub_node, @2, @5); + lvalue TOK_DECREMENT { + AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_SUB, $1->clone(), AstNode::mkconst_int(1, true))); ast_stack.back()->children.push_back(node); - append_attr(node, $1); } | - attr lvalue TOK_AND_ASSIGN delay expr { - AstNode *and_node = new AstNode(AST_BIT_AND, $2->clone(), $5); - AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, and_node); - SET_AST_NODE_LOC(node, @2, @5); - SET_AST_NODE_LOC(and_node, @2, @5); + lvalue OP_LE delay expr { + AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4); ast_stack.back()->children.push_back(node); - append_attr(node, $1); }; // this production creates the obligatory if-else shift/reduce conflict behavioral_stmt: defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | non_opt_delay behavioral_stmt | - simple_behavioral_stmt ';' | - attr ';' { - free_attr($1); - } | - attr hierarchical_id { + simple_behavioral_stmt ';' | ';' | + hierarchical_id attr { AstNode *node = new AstNode(AST_TCALL); - node->str = *$2; - delete $2; + node->str = *$1; + delete $1; ast_stack.back()->children.push_back(node); ast_stack.push_back(node); - append_attr(node, $1); + append_attr(node, $2); } opt_arg_list ';'{ ast_stack.pop_back(); } | - attr TOK_MSG_TASKS { + TOK_MSG_TASKS attr { AstNode *node = new AstNode(AST_TCALL); - node->str = *$2; - delete $2; + node->str = *$1; + delete $1; ast_stack.back()->children.push_back(node); ast_stack.push_back(node); - append_attr(node, $1); + append_attr(node, $2); } opt_arg_list ';'{ ast_stack.pop_back(); } | - attr TOK_BEGIN { - enterTypeScope(); - } opt_label { + attr TOK_BEGIN opt_label { AstNode *node = new AstNode(AST_BLOCK); ast_stack.back()->children.push_back(node); ast_stack.push_back(node); append_attr(node, $1); - if ($4 != NULL) - node->str = *$4; + if ($3 != NULL) + node->str = *$3; } behavioral_stmt_list TOK_END opt_label { - exitTypeScope(); - if ($4 != NULL && $8 != NULL && *$4 != *$8) - frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $4->c_str()+1, $8->c_str()+1); - SET_AST_NODE_LOC(ast_stack.back(), @2, @8); - delete $4; - delete $8; + if ($3 != NULL && $7 != NULL && *$3 != *$7) + frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1); + if ($3 != NULL) + delete $3; + if ($7 != NULL) + delete $7; ast_stack.pop_back(); } | attr TOK_FOR '(' { @@ -2435,9 +1967,7 @@ behavioral_stmt: ast_stack.back()->children.push_back(block); ast_stack.push_back(block); } behavioral_stmt { - SET_AST_NODE_LOC(ast_stack.back(), @13, @13); ast_stack.pop_back(); - SET_AST_NODE_LOC(ast_stack.back(), @2, @13); ast_stack.pop_back(); } | attr TOK_WHILE '(' expr ')' { @@ -2450,7 +1980,6 @@ behavioral_stmt: ast_stack.back()->children.push_back(block); ast_stack.push_back(block); } behavioral_stmt { - SET_AST_NODE_LOC(ast_stack.back(), @7, @7); ast_stack.pop_back(); ast_stack.pop_back(); } | @@ -2464,7 +1993,6 @@ behavioral_stmt: ast_stack.back()->children.push_back(block); ast_stack.push_back(block); } behavioral_stmt { - SET_AST_NODE_LOC(ast_stack.back(), @7, @7); ast_stack.pop_back(); ast_stack.pop_back(); } | @@ -2472,18 +2000,14 @@ behavioral_stmt: AstNode *node = new AstNode(AST_CASE); AstNode *block = new AstNode(AST_BLOCK); AstNode *cond = new AstNode(AST_COND, AstNode::mkconst_int(1, false, 1), block); - SET_AST_NODE_LOC(cond, @4, @4); ast_stack.back()->children.push_back(node); node->children.push_back(new AstNode(AST_REDUCE_BOOL, $4)); node->children.push_back(cond); ast_stack.push_back(node); ast_stack.push_back(block); append_attr(node, $1); - } behavioral_stmt { - SET_AST_NODE_LOC(ast_stack.back(), @7, @7); - } optional_else { + } behavioral_stmt optional_else { ast_stack.pop_back(); - SET_AST_NODE_LOC(ast_stack.back(), @2, @9); ast_stack.pop_back(); } | case_attr case_type '(' expr ')' { @@ -2491,9 +2015,7 @@ behavioral_stmt: ast_stack.back()->children.push_back(node); ast_stack.push_back(node); append_attr(node, $1); - SET_AST_NODE_LOC(ast_stack.back(), @4, @4); } opt_synopsys_attr case_body TOK_ENDCASE { - SET_AST_NODE_LOC(ast_stack.back(), @2, @9); case_type_stack.pop_back(); ast_stack.pop_back(); }; @@ -2511,7 +2033,7 @@ unique_case_attr: case_attr: attr unique_case_attr { - if ($2) (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false); + if ($2) (*$1)["\\parallel_case"] = AstNode::mkconst_int(1, false); $$ = $1; }; @@ -2528,12 +2050,12 @@ case_type: opt_synopsys_attr: opt_synopsys_attr TOK_SYNOPSYS_FULL_CASE { - if (ast_stack.back()->attributes.count(ID::full_case) == 0) - ast_stack.back()->attributes[ID::full_case] = AstNode::mkconst_int(1, false); + if (ast_stack.back()->attributes.count("\\full_case") == 0) + ast_stack.back()->attributes["\\full_case"] = AstNode::mkconst_int(1, false); } | opt_synopsys_attr TOK_SYNOPSYS_PARALLEL_CASE { - if (ast_stack.back()->attributes.count(ID::parallel_case) == 0) - ast_stack.back()->attributes[ID::parallel_case] = AstNode::mkconst_int(1, false); + if (ast_stack.back()->attributes.count("\\parallel_case") == 0) + ast_stack.back()->attributes["\\parallel_case"] = AstNode::mkconst_int(1, false); } | /* empty */; @@ -2545,14 +2067,10 @@ optional_else: TOK_ELSE { AstNode *block = new AstNode(AST_BLOCK); AstNode *cond = new AstNode(AST_COND, new AstNode(AST_DEFAULT), block); - SET_AST_NODE_LOC(cond, @1, @1); - ast_stack.pop_back(); ast_stack.back()->children.push_back(cond); ast_stack.push_back(block); - } behavioral_stmt { - SET_AST_NODE_LOC(ast_stack.back(), @3, @3); - } | + } behavioral_stmt | /* empty */ %prec FAKE_THEN; case_body: @@ -2573,7 +2091,6 @@ case_item: case_type_stack.push_back(0); } behavioral_stmt { case_type_stack.pop_back(); - SET_AST_NODE_LOC(ast_stack.back(), @4, @4); ast_stack.pop_back(); ast_stack.pop_back(); }; @@ -2591,8 +2108,7 @@ gen_case_item: ast_stack.push_back(node); } case_select { case_type_stack.push_back(0); - SET_AST_NODE_LOC(ast_stack.back(), @2, @2); - } gen_stmt_block { + } gen_stmt_or_null { case_type_stack.pop_back(); ast_stack.pop_back(); }; @@ -2603,14 +2119,10 @@ case_select: case_expr_list: TOK_DEFAULT { - AstNode *node = new AstNode(AST_DEFAULT); - SET_AST_NODE_LOC(node, @1, @1); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT)); } | TOK_SVA_LABEL { - AstNode *node = new AstNode(AST_IDENTIFIER); - SET_AST_NODE_LOC(node, @1, @1); - ast_stack.back()->children.push_back(node); + ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER)); ast_stack.back()->children.back()->str = *$1; delete $1; } | @@ -2630,7 +2142,6 @@ rvalue: hierarchical_id range { $$ = new AstNode(AST_IDENTIFIER, $2); $$->str = *$1; - SET_AST_NODE_LOC($$, @1, @1); delete $1; if ($2 == nullptr && ($$->str == "\\$initstate" || $$->str == "\\$anyconst" || $$->str == "\\$anyseq" || @@ -2640,7 +2151,6 @@ rvalue: hierarchical_id non_opt_multirange { $$ = new AstNode(AST_IDENTIFIER, $2); $$->str = *$1; - SET_AST_NODE_LOC($$, @1, @1); delete $1; }; @@ -2684,10 +2194,7 @@ module_gen_body: /* empty */; gen_stmt_or_module_body_stmt: - gen_stmt | module_body_stmt | - attr ';' { - free_attr($1); - }; + gen_stmt | module_body_stmt; // this production creates the obligatory if-else shift/reduce conflict gen_stmt: @@ -2698,7 +2205,6 @@ gen_stmt: } simple_behavioral_stmt ';' expr { ast_stack.back()->children.push_back($6); } ';' simple_behavioral_stmt ')' gen_stmt_block { - SET_AST_NODE_LOC(ast_stack.back(), @1, @11); ast_stack.pop_back(); } | TOK_IF '(' expr ')' { @@ -2706,13 +2212,7 @@ gen_stmt: ast_stack.back()->children.push_back(node); ast_stack.push_back(node); ast_stack.back()->children.push_back($3); - AstNode *block = new AstNode(AST_GENBLOCK); - ast_stack.back()->children.push_back(block); - ast_stack.push_back(block); - } gen_stmt_block { - ast_stack.pop_back(); - } opt_gen_else { - SET_AST_NODE_LOC(ast_stack.back(), @1, @7); + } gen_stmt_block opt_gen_else { ast_stack.pop_back(); } | case_type '(' expr ')' { @@ -2721,21 +2221,18 @@ gen_stmt: ast_stack.push_back(node); } gen_case_body TOK_ENDCASE { case_type_stack.pop_back(); - SET_AST_NODE_LOC(ast_stack.back(), @1, @7); ast_stack.pop_back(); } | - TOK_BEGIN { - enterTypeScope(); - } opt_label { + TOK_BEGIN opt_label { AstNode *node = new AstNode(AST_GENBLOCK); - node->str = $3 ? *$3 : std::string(); + node->str = $2 ? *$2 : std::string(); ast_stack.back()->children.push_back(node); ast_stack.push_back(node); } module_gen_body TOK_END opt_label { - exitTypeScope(); - delete $3; - delete $7; - SET_AST_NODE_LOC(ast_stack.back(), @1, @7); + if ($2 != NULL) + delete $2; + if ($6 != NULL) + delete $6; ast_stack.pop_back(); } | TOK_MSG_TASKS { @@ -2745,7 +2242,6 @@ gen_stmt: ast_stack.back()->children.push_back(node); ast_stack.push_back(node); } opt_arg_list ';'{ - SET_AST_NODE_LOC(ast_stack.back(), @1, @3); ast_stack.pop_back(); }; @@ -2755,12 +2251,14 @@ gen_stmt_block: ast_stack.back()->children.push_back(node); ast_stack.push_back(node); } gen_stmt_or_module_body_stmt { - SET_AST_NODE_LOC(ast_stack.back(), @2, @2); ast_stack.pop_back(); }; +gen_stmt_or_null: + gen_stmt_block | ';'; + opt_gen_else: - TOK_ELSE gen_stmt_block | /* empty */ %prec FAKE_THEN; + TOK_ELSE gen_stmt_or_null | /* empty */ %prec FAKE_THEN; expr: basic_expr { @@ -2771,7 +2269,6 @@ expr: $$->children.push_back($1); $$->children.push_back($4); $$->children.push_back($6); - SET_AST_NODE_LOC($$, @1, @$); append_attr($$, $3); }; @@ -2779,7 +2276,7 @@ basic_expr: rvalue { $$ = $1; } | - '(' expr ')' integral_number { + '(' expr ')' TOK_CONSTVAL { if ($4->compare(0, 1, "'") != 0) frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. () , while %s is not a sized constant.", $4->c_str()); AstNode *bits = $2; @@ -2789,23 +2286,27 @@ basic_expr: $$ = new AstNode(AST_TO_BITS, bits, val); delete $4; } | - hierarchical_id integral_number { + hierarchical_id TOK_CONSTVAL { if ($2->compare(0, 1, "'") != 0) frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. \'d0, while %s is not a sized constant.", $2->c_str()); AstNode *bits = new AstNode(AST_IDENTIFIER); bits->str = *$1; - SET_AST_NODE_LOC(bits, @1, @1); AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); - SET_AST_NODE_LOC(val, @2, @2); if (val == NULL) log_error("Value conversion failed: `%s'\n", $2->c_str()); $$ = new AstNode(AST_TO_BITS, bits, val); delete $1; delete $2; } | - integral_number { + TOK_CONSTVAL TOK_CONSTVAL { + $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); + if ($$ == NULL || (*$2)[0] != '\'') + log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str()); + delete $1; + delete $2; + } | + TOK_CONSTVAL { $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); - SET_AST_NODE_LOC($$, @1, @1); if ($$ == NULL) log_error("Value conversion failed: `%s'\n", $1->c_str()); delete $1; @@ -2817,14 +2318,12 @@ basic_expr: if ((*$1)[j] != '_') p[i++] = (*$1)[j], p[i] = 0; $$->realvalue = strtod(p, &q); - SET_AST_NODE_LOC($$, @1, @1); log_assert(*q == 0); delete $1; free(p); } | TOK_STRING { $$ = AstNode::mkconst_str(*$1); - SET_AST_NODE_LOC($$, @1, @1); delete $1; } | hierarchical_id attr { @@ -2832,7 +2331,6 @@ basic_expr: node->str = *$1; delete $1; ast_stack.push_back(node); - SET_AST_NODE_LOC(node, @1, @1); append_attr(node, $2); } '(' arg_list optional_comma ')' { $$ = ast_stack.back(); @@ -2862,185 +2360,148 @@ basic_expr: } | '~' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_BIT_NOT, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | basic_expr '&' attr basic_expr { $$ = new AstNode(AST_BIT_AND, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_NAND attr basic_expr { $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_AND, $1, $4)); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '|' attr basic_expr { $$ = new AstNode(AST_BIT_OR, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_NOR attr basic_expr { $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_OR, $1, $4)); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '^' attr basic_expr { $$ = new AstNode(AST_BIT_XOR, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_XNOR attr basic_expr { $$ = new AstNode(AST_BIT_XNOR, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | '&' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_AND, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | OP_NAND attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_AND, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); $$ = new AstNode(AST_LOGIC_NOT, $$); } | '|' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_OR, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | OP_NOR attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_OR, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); $$ = new AstNode(AST_LOGIC_NOT, $$); - SET_AST_NODE_LOC($$, @1, @3); } | '^' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_XOR, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | OP_XNOR attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_XNOR, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | basic_expr OP_SHL attr basic_expr { $$ = new AstNode(AST_SHIFT_LEFT, $1, new AstNode(AST_TO_UNSIGNED, $4)); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_SHR attr basic_expr { $$ = new AstNode(AST_SHIFT_RIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4)); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_SSHL attr basic_expr { $$ = new AstNode(AST_SHIFT_SLEFT, $1, new AstNode(AST_TO_UNSIGNED, $4)); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_SSHR attr basic_expr { $$ = new AstNode(AST_SHIFT_SRIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4)); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '<' attr basic_expr { $$ = new AstNode(AST_LT, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_LE attr basic_expr { $$ = new AstNode(AST_LE, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_EQ attr basic_expr { $$ = new AstNode(AST_EQ, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_NE attr basic_expr { $$ = new AstNode(AST_NE, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_EQX attr basic_expr { $$ = new AstNode(AST_EQX, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_NEX attr basic_expr { $$ = new AstNode(AST_NEX, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_GE attr basic_expr { $$ = new AstNode(AST_GE, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '>' attr basic_expr { $$ = new AstNode(AST_GT, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '+' attr basic_expr { $$ = new AstNode(AST_ADD, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '-' attr basic_expr { $$ = new AstNode(AST_SUB, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '*' attr basic_expr { $$ = new AstNode(AST_MUL, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '/' attr basic_expr { $$ = new AstNode(AST_DIV, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '%' attr basic_expr { $$ = new AstNode(AST_MOD, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_POW attr basic_expr { $$ = new AstNode(AST_POW, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | '+' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_POS, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | '-' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_NEG, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | basic_expr OP_LAND attr basic_expr { $$ = new AstNode(AST_LOGIC_AND, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_LOR attr basic_expr { $$ = new AstNode(AST_LOGIC_OR, $1, $4); - SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | '!' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_LOGIC_NOT, $3); - SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); }; @@ -3052,18 +2513,3 @@ concat_list: $$ = $3; $$->children.push_back($1); }; - -integral_number: - TOK_CONSTVAL { $$ = $1; } | - TOK_UNBASED_UNSIZED_CONSTVAL { $$ = $1; } | - TOK_BASE TOK_BASED_CONSTVAL { - $1->append(*$2); - $$ = $1; - delete $2; - } | - TOK_CONSTVAL TOK_BASE TOK_BASED_CONSTVAL { - $1->append(*$2).append(*$3); - $$ = $1; - delete $2; - delete $3; - }; diff --git a/kernel/calc.cc b/kernel/calc.cc index ae18809d3f6..4a48407717f 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -489,7 +489,6 @@ RTLIL::Const RTLIL::const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2 return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); } -// truncating division RTLIL::Const RTLIL::const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { int undef_bit_pos = -1; @@ -503,7 +502,6 @@ RTLIL::Const RTLIL::const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2 return big2const(result_neg ? -(a / b) : (a / b), result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); } -// truncating modulo RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { int undef_bit_pos = -1; @@ -517,51 +515,6 @@ RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2 return big2const(result_neg ? -(a % b) : (a % b), result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); } -RTLIL::Const RTLIL::const_divfloor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) -{ - int undef_bit_pos = -1; - BigInteger a = const2big(arg1, signed1, undef_bit_pos); - BigInteger b = const2big(arg2, signed2, undef_bit_pos); - if (b.isZero()) - return RTLIL::Const(RTLIL::State::Sx, result_len); - - bool result_pos = (a.getSign() == BigInteger::negative) == (b.getSign() == BigInteger::negative); - a = a.getSign() == BigInteger::negative ? -a : a; - b = b.getSign() == BigInteger::negative ? -b : b; - BigInteger result; - - if (result_pos || a == 0) { - result = a / b; - } else { - // bigint division with negative numbers is wonky, make sure we only negate at the very end - result = -((a + b - 1) / b); - } - return big2const(result, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); -} - -RTLIL::Const RTLIL::const_modfloor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) -{ - int undef_bit_pos = -1; - BigInteger a = const2big(arg1, signed1, undef_bit_pos); - BigInteger b = const2big(arg2, signed2, undef_bit_pos); - if (b.isZero()) - return RTLIL::Const(RTLIL::State::Sx, result_len); - - BigInteger::Sign a_sign = a.getSign(); - BigInteger::Sign b_sign = b.getSign(); - a = a_sign == BigInteger::negative ? -a : a; - b = b_sign == BigInteger::negative ? -b : b; - BigInteger truncated = a_sign == BigInteger::negative ? -(a % b) : (a % b); - BigInteger modulo; - - if (truncated == 0 || (a_sign == b_sign)) { - modulo = truncated; - } else { - modulo = b_sign == BigInteger::negative ? truncated - b : truncated + b; - } - return big2const(modulo, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); -} - RTLIL::Const RTLIL::const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { int undef_bit_pos = -1; diff --git a/kernel/cellaigs.cc b/kernel/cellaigs.cc index 2c82b1bca78..02854edb2c0 100644 --- a/kernel/cellaigs.cc +++ b/kernel/cellaigs.cc @@ -268,9 +268,9 @@ Aig::Aig(Cell *cell) cell->parameters.sort(); for (auto p : cell->parameters) { - if (p.first == ID::A_WIDTH && mkname_a_signed) { + if (p.first == ID(A_WIDTH) && mkname_a_signed) { name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U'); - } else if (p.first == ID::B_WIDTH && mkname_b_signed) { + } else if (p.first == ID(B_WIDTH) && mkname_b_signed) { name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U'); } else { mkname_last = name; @@ -280,11 +280,11 @@ Aig::Aig(Cell *cell) mkname_a_signed = false; mkname_b_signed = false; mkname_is_signed = false; - if (p.first == ID::A_SIGNED) { + if (p.first == ID(A_SIGNED)) { mkname_a_signed = true; mkname_is_signed = p.second.as_bool(); } - if (p.first == ID::B_SIGNED) { + if (p.first == ID(B_SIGNED)) { mkname_b_signed = true; mkname_is_signed = p.second.as_bool(); } @@ -320,7 +320,7 @@ Aig::Aig(Cell *cell) if (cell->type.in(ID($mux), ID($_MUX_))) { - int S = mk.inport(ID::S); + int S = mk.inport(ID(S)); for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) { int A = mk.inport(ID::A, i); int B = mk.inport(ID::B, i); @@ -390,8 +390,8 @@ Aig::Aig(Cell *cell) int width = GetSize(cell->getPort(ID::Y)); vector A = mk.inport_vec(ID::A, width); vector B = mk.inport_vec(ID::B, width); - int carry = mk.inport(ID::CI); - int binv = mk.inport(ID::BI); + int carry = mk.inport(ID(CI)); + int binv = mk.inport(ID(BI)); for (auto &n : B) n = mk.xor_gate(n, binv); vector X(width), CO(width); @@ -399,8 +399,8 @@ Aig::Aig(Cell *cell) for (int i = 0; i < width; i++) X[i] = mk.xor_gate(A[i], B[i]); mk.outport_vec(Y, ID::Y); - mk.outport_vec(X, ID::X); - mk.outport_vec(CO, ID::CO); + mk.outport_vec(X, ID(X)); + mk.outport_vec(CO, ID(CO)); goto optimize; } @@ -422,7 +422,7 @@ Aig::Aig(Cell *cell) { int A = mk.inport(ID::A); int B = mk.inport(ID::B); - int C = mk.inport(ID::C); + int C = mk.inport(ID(C)); int Y = mk.nor_gate(mk.and_gate(A, B), C); mk.outport(Y, ID::Y); goto optimize; @@ -432,7 +432,7 @@ Aig::Aig(Cell *cell) { int A = mk.inport(ID::A); int B = mk.inport(ID::B); - int C = mk.inport(ID::C); + int C = mk.inport(ID(C)); int Y = mk.nand_gate(mk.or_gate(A, B), C); mk.outport(Y, ID::Y); goto optimize; @@ -442,8 +442,8 @@ Aig::Aig(Cell *cell) { int A = mk.inport(ID::A); int B = mk.inport(ID::B); - int C = mk.inport(ID::C); - int D = mk.inport(ID::D); + int C = mk.inport(ID(C)); + int D = mk.inport(ID(D)); int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D)); mk.outport(Y, ID::Y); goto optimize; @@ -453,8 +453,8 @@ Aig::Aig(Cell *cell) { int A = mk.inport(ID::A); int B = mk.inport(ID::B); - int C = mk.inport(ID::C); - int D = mk.inport(ID::D); + int C = mk.inport(ID(C)); + int D = mk.inport(ID(D)); int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D)); mk.outport(Y, ID::Y); goto optimize; diff --git a/kernel/celledges.cc b/kernel/celledges.cc index 314e7c77e76..d0bb99e8397 100644 --- a/kernel/celledges.cc +++ b/kernel/celledges.cc @@ -24,25 +24,29 @@ PRIVATE_NAMESPACE_BEGIN void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) { - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); - int a_width = GetSize(cell->getPort(ID::A)); - int y_width = GetSize(cell->getPort(ID::Y)); + IdString A = ID::A, Y = ID::Y; + + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); + int a_width = GetSize(cell->getPort(A)); + int y_width = GetSize(cell->getPort(Y)); for (int i = 0; i < y_width; i++) { if (i < a_width) - db->add_edge(cell, ID::A, i, ID::Y, i, -1); + db->add_edge(cell, A, i, Y, i, -1); else if (is_signed && a_width > 0) - db->add_edge(cell, ID::A, a_width-1, ID::Y, i, -1); + db->add_edge(cell, A, a_width-1, Y, i, -1); } } void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) { - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); - int a_width = GetSize(cell->getPort(ID::A)); - int b_width = GetSize(cell->getPort(ID::B)); - int y_width = GetSize(cell->getPort(ID::Y)); + IdString A = ID::A, B = ID::B, Y = ID::Y; + + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); + int a_width = GetSize(cell->getPort(A)); + int b_width = GetSize(cell->getPort(B)); + int y_width = GetSize(cell->getPort(Y)); if (cell->type == ID($and) && !is_signed) { if (a_width > b_width) @@ -54,37 +58,41 @@ void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) for (int i = 0; i < y_width; i++) { if (i < a_width) - db->add_edge(cell, ID::A, i, ID::Y, i, -1); + db->add_edge(cell, A, i, Y, i, -1); else if (is_signed && a_width > 0) - db->add_edge(cell, ID::A, a_width-1, ID::Y, i, -1); + db->add_edge(cell, A, a_width-1, Y, i, -1); if (i < b_width) - db->add_edge(cell, ID::B, i, ID::Y, i, -1); + db->add_edge(cell, B, i, Y, i, -1); else if (is_signed && b_width > 0) - db->add_edge(cell, ID::B, b_width-1, ID::Y, i, -1); + db->add_edge(cell, B, b_width-1, Y, i, -1); } } void arith_neg_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) { - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); - int a_width = GetSize(cell->getPort(ID::A)); - int y_width = GetSize(cell->getPort(ID::Y)); + IdString A = ID::A, Y = ID::Y; + + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); + int a_width = GetSize(cell->getPort(A)); + int y_width = GetSize(cell->getPort(Y)); if (is_signed && a_width == 1) y_width = std::min(y_width, 1); for (int i = 0; i < y_width; i++) for (int k = 0; k <= i && k < a_width; k++) - db->add_edge(cell, ID::A, k, ID::Y, i, -1); + db->add_edge(cell, A, k, Y, i, -1); } void arith_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) { - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); - int a_width = GetSize(cell->getPort(ID::A)); - int b_width = GetSize(cell->getPort(ID::B)); - int y_width = GetSize(cell->getPort(ID::Y)); + IdString A = ID::A, B = ID::B, Y = ID::Y; + + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); + int a_width = GetSize(cell->getPort(A)); + int b_width = GetSize(cell->getPort(B)); + int y_width = GetSize(cell->getPort(Y)); if (!is_signed && cell->type != ID($sub)) { int ab_width = std::max(a_width, b_width); @@ -96,49 +104,55 @@ void arith_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) for (int k = 0; k <= i; k++) { if (k < a_width) - db->add_edge(cell, ID::A, k, ID::Y, i, -1); + db->add_edge(cell, A, k, Y, i, -1); if (k < b_width) - db->add_edge(cell, ID::B, k, ID::Y, i, -1); + db->add_edge(cell, B, k, Y, i, -1); } } } void reduce_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) { - int a_width = GetSize(cell->getPort(ID::A)); + IdString A = ID::A, Y = ID::Y; + + int a_width = GetSize(cell->getPort(A)); for (int i = 0; i < a_width; i++) - db->add_edge(cell, ID::A, i, ID::Y, 0, -1); + db->add_edge(cell, A, i, Y, 0, -1); } void compare_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) { - int a_width = GetSize(cell->getPort(ID::A)); - int b_width = GetSize(cell->getPort(ID::B)); + IdString A = ID::A, B = ID::B, Y = ID::Y; + + int a_width = GetSize(cell->getPort(A)); + int b_width = GetSize(cell->getPort(B)); for (int i = 0; i < a_width; i++) - db->add_edge(cell, ID::A, i, ID::Y, 0, -1); + db->add_edge(cell, A, i, Y, 0, -1); for (int i = 0; i < b_width; i++) - db->add_edge(cell, ID::B, i, ID::Y, 0, -1); + db->add_edge(cell, B, i, Y, 0, -1); } void mux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) { - int a_width = GetSize(cell->getPort(ID::A)); - int b_width = GetSize(cell->getPort(ID::B)); - int s_width = GetSize(cell->getPort(ID::S)); + IdString A = ID::A, B = ID::B, S = ID(S), Y = ID::Y; + + int a_width = GetSize(cell->getPort(A)); + int b_width = GetSize(cell->getPort(B)); + int s_width = GetSize(cell->getPort(S)); for (int i = 0; i < a_width; i++) { - db->add_edge(cell, ID::A, i, ID::Y, i, -1); + db->add_edge(cell, A, i, Y, i, -1); for (int k = i; k < b_width; k += a_width) - db->add_edge(cell, ID::B, k, ID::Y, i, -1); + db->add_edge(cell, B, k, Y, i, -1); for (int k = 0; k < s_width; k++) - db->add_edge(cell, ID::S, k, ID::Y, i, -1); + db->add_edge(cell, S, k, Y, i, -1); } } @@ -187,7 +201,7 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL return true; } - // FIXME: $mul $div $mod $divfloor $modfloor $slice $concat + // FIXME: $mul $div $mod $slice $concat // FIXME: $lut $sop $alu $lcu $macc $fa return false; diff --git a/kernel/celledges.h b/kernel/celledges.h index d105e4009d1..2cc297cb28c 100644 --- a/kernel/celledges.h +++ b/kernel/celledges.h @@ -38,7 +38,7 @@ struct FwdCellEdgesDatabase : AbstractCellEdgesDatabase dict> db; FwdCellEdgesDatabase(SigMap &sigmap) : sigmap(sigmap) { } - void add_edge(RTLIL::Cell *cell, RTLIL::IdString from_port, int from_bit, RTLIL::IdString to_port, int to_bit, int) override { + void add_edge(RTLIL::Cell *cell, RTLIL::IdString from_port, int from_bit, RTLIL::IdString to_port, int to_bit, int) YS_OVERRIDE { SigBit from_sigbit = sigmap(cell->getPort(from_port)[from_bit]); SigBit to_sigbit = sigmap(cell->getPort(to_port)[to_bit]); db[from_sigbit].insert(to_sigbit); @@ -51,7 +51,7 @@ struct RevCellEdgesDatabase : AbstractCellEdgesDatabase dict> db; RevCellEdgesDatabase(SigMap &sigmap) : sigmap(sigmap) { } - void add_edge(RTLIL::Cell *cell, RTLIL::IdString from_port, int from_bit, RTLIL::IdString to_port, int to_bit, int) override { + void add_edge(RTLIL::Cell *cell, RTLIL::IdString from_port, int from_bit, RTLIL::IdString to_port, int to_bit, int) YS_OVERRIDE { SigBit from_sigbit = sigmap(cell->getPort(from_port)[from_bit]); SigBit to_sigbit = sigmap(cell->getPort(to_port)[to_bit]); db[to_sigbit].insert(from_sigbit); diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 12dea93b8bf..bc96fd602bb 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -84,22 +84,26 @@ struct CellTypes { setup_internals_eval(); - setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}, true); - - setup_type(ID($assert), {ID::A, ID::EN}, pool(), true); - setup_type(ID($assume), {ID::A, ID::EN}, pool(), true); - setup_type(ID($live), {ID::A, ID::EN}, pool(), true); - setup_type(ID($fair), {ID::A, ID::EN}, pool(), true); - setup_type(ID($cover), {ID::A, ID::EN}, pool(), true); - setup_type(ID($initstate), pool(), {ID::Y}, true); - setup_type(ID($anyconst), pool(), {ID::Y}, true); - setup_type(ID($anyseq), pool(), {ID::Y}, true); - setup_type(ID($allconst), pool(), {ID::Y}, true); - setup_type(ID($allseq), pool(), {ID::Y}, true); - setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, pool(), true); - setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool(), true); - setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool(), true); + IdString A = ID::A, B = ID::B, EN = ID(EN), Y = ID::Y; + IdString SRC = ID(SRC), DST = ID(DST), DAT = ID(DAT); + IdString EN_SRC = ID(EN_SRC), EN_DST = ID(EN_DST); + + setup_type(ID($tribuf), {A, EN}, {Y}, true); + + setup_type(ID($assert), {A, EN}, pool(), true); + setup_type(ID($assume), {A, EN}, pool(), true); + setup_type(ID($live), {A, EN}, pool(), true); + setup_type(ID($fair), {A, EN}, pool(), true); + setup_type(ID($cover), {A, EN}, pool(), true); + setup_type(ID($initstate), pool(), {Y}, true); + setup_type(ID($anyconst), pool(), {Y}, true); + setup_type(ID($anyseq), pool(), {Y}, true); + setup_type(ID($allconst), pool(), {Y}, true); + setup_type(ID($allseq), pool(), {Y}, true); + setup_type(ID($equiv), {A, B}, {Y}, true); + setup_type(ID($specify2), {EN, SRC, DST}, pool(), true); + setup_type(ID($specify3), {EN, SRC, DST, DAT}, pool(), true); + setup_type(ID($specrule), {EN_SRC, EN_DST, SRC, DST}, pool(), true); } void setup_internals_eval() @@ -114,152 +118,137 @@ struct CellTypes ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), - ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow), + ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow), ID($logic_and), ID($logic_or), ID($concat), ID($macc) }; + IdString A = ID::A, B = ID::B, S = ID(S), Y = ID::Y; + IdString P = ID(P), G = ID(G), C = ID(C), X = ID(X); + IdString BI = ID(BI), CI = ID(CI), CO = ID(CO), EN = ID(EN); for (auto type : unary_ops) - setup_type(type, {ID::A}, {ID::Y}, true); + setup_type(type, {A}, {Y}, true); for (auto type : binary_ops) - setup_type(type, {ID::A, ID::B}, {ID::Y}, true); + setup_type(type, {A, B}, {Y}, true); for (auto type : std::vector({ID($mux), ID($pmux)})) - setup_type(type, {ID::A, ID::B, ID::S}, {ID::Y}, true); + setup_type(type, {A, B, S}, {Y}, true); - setup_type(ID($lcu), {ID::P, ID::G, ID::CI}, {ID::CO}, true); - setup_type(ID($alu), {ID::A, ID::B, ID::CI, ID::BI}, {ID::X, ID::Y, ID::CO}, true); - setup_type(ID($fa), {ID::A, ID::B, ID::C}, {ID::X, ID::Y}, true); + setup_type(ID($lcu), {P, G, CI}, {CO}, true); + setup_type(ID($alu), {A, B, CI, BI}, {X, Y, CO}, true); + setup_type(ID($fa), {A, B, C}, {X, Y}, true); } void setup_internals_ff() { - setup_type(ID($sr), {ID::SET, ID::CLR}, {ID::Q}); - setup_type(ID($ff), {ID::D}, {ID::Q}); - setup_type(ID($dff), {ID::CLK, ID::D}, {ID::Q}); - setup_type(ID($dffe), {ID::CLK, ID::EN, ID::D}, {ID::Q}); - setup_type(ID($dffsr), {ID::CLK, ID::SET, ID::CLR, ID::D}, {ID::Q}); - setup_type(ID($dffsre), {ID::CLK, ID::SET, ID::CLR, ID::D, ID::E}, {ID::Q}); - setup_type(ID($adff), {ID::CLK, ID::ARST, ID::D}, {ID::Q}); - setup_type(ID($adffe), {ID::CLK, ID::ARST, ID::D, ID::E}, {ID::Q}); - setup_type(ID($sdff), {ID::CLK, ID::SRST, ID::D}, {ID::Q}); - setup_type(ID($sdffe), {ID::CLK, ID::SRST, ID::D, ID::E}, {ID::Q}); - setup_type(ID($sdffce), {ID::CLK, ID::SRST, ID::D, ID::E}, {ID::Q}); - setup_type(ID($dlatch), {ID::EN, ID::D}, {ID::Q}); - setup_type(ID($adlatch), {ID::EN, ID::D, ID::ARST}, {ID::Q}); - setup_type(ID($dlatchsr), {ID::EN, ID::SET, ID::CLR, ID::D}, {ID::Q}); + 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() { setup_internals_ff(); - setup_type(ID($memrd), {ID::CLK, ID::EN, ID::ADDR}, {ID::DATA}); - setup_type(ID($memwr), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, pool()); - setup_type(ID($meminit), {ID::ADDR, ID::DATA}, pool()); - setup_type(ID($mem), {ID::RD_CLK, ID::RD_EN, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA}); + IdString CLK = ID(CLK), ARST = ID(ARST), EN = ID(EN); + IdString ADDR = ID(ADDR), DATA = ID(DATA), RD_EN = ID(RD_EN); + IdString RD_CLK = ID(RD_CLK), RD_ADDR = ID(RD_ADDR), WR_CLK = ID(WR_CLK), WR_EN = ID(WR_EN); + IdString WR_ADDR = ID(WR_ADDR), WR_DATA = ID(WR_DATA), RD_DATA = ID(RD_DATA); + IdString CTRL_IN = ID(CTRL_IN), CTRL_OUT = ID(CTRL_OUT); + + setup_type(ID($memrd), {CLK, EN, ADDR}, {DATA}); + setup_type(ID($memwr), {CLK, EN, ADDR, DATA}, pool()); + setup_type(ID($meminit), {ADDR, DATA}, pool()); + setup_type(ID($mem), {RD_CLK, RD_EN, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA}); - setup_type(ID($fsm), {ID::CLK, ID::ARST, ID::CTRL_IN}, {ID::CTRL_OUT}); + setup_type(ID($fsm), {CLK, ARST, CTRL_IN}, {CTRL_OUT}); } void setup_stdcells() { setup_stdcells_eval(); - setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}, true); + IdString A = ID::A, E = ID(E), Y = ID::Y; + + setup_type(ID($_TBUF_), {A, E}, {Y}, true); } void setup_stdcells_eval() { - setup_type(ID($_BUF_), {ID::A}, {ID::Y}, true); - setup_type(ID($_NOT_), {ID::A}, {ID::Y}, true); - setup_type(ID($_AND_), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($_NAND_), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($_OR_), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($_NOR_), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($_XOR_), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($_XNOR_), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($_ANDNOT_), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($_ORNOT_), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($_MUX_), {ID::A, ID::B, ID::S}, {ID::Y}, true); - setup_type(ID($_NMUX_), {ID::A, ID::B, ID::S}, {ID::Y}, true); - setup_type(ID($_MUX4_), {ID::A, ID::B, ID::C, ID::D, ID::S, ID::T}, {ID::Y}, true); - setup_type(ID($_MUX8_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::S, ID::T, ID::U}, {ID::Y}, true); - setup_type(ID($_MUX16_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::I, ID::J, ID::K, ID::L, ID::M, ID::N, ID::O, ID::P, ID::S, ID::T, ID::U, ID::V}, {ID::Y}, true); - setup_type(ID($_AOI3_), {ID::A, ID::B, ID::C}, {ID::Y}, true); - setup_type(ID($_OAI3_), {ID::A, ID::B, ID::C}, {ID::Y}, true); - setup_type(ID($_AOI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y}, true); - setup_type(ID($_OAI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y}, true); + IdString A = ID::A, B = ID::B, C = ID(C), D = ID(D); + IdString E = ID(E), F = ID(F), G = ID(G), H = ID(H); + IdString I = ID(I), J = ID(J), K = ID(K), L = ID(L); + IdString M = ID(M), N = ID(N), O = ID(O), P = ID(P); + IdString S = ID(S), T = ID(T), U = ID(U), V = ID(V); + IdString Y = ID::Y; + + setup_type(ID($_BUF_), {A}, {Y}, true); + setup_type(ID($_NOT_), {A}, {Y}, true); + setup_type(ID($_AND_), {A, B}, {Y}, true); + setup_type(ID($_NAND_), {A, B}, {Y}, true); + setup_type(ID($_OR_), {A, B}, {Y}, true); + setup_type(ID($_NOR_), {A, B}, {Y}, true); + setup_type(ID($_XOR_), {A, B}, {Y}, true); + setup_type(ID($_XNOR_), {A, B}, {Y}, true); + setup_type(ID($_ANDNOT_), {A, B}, {Y}, true); + setup_type(ID($_ORNOT_), {A, B}, {Y}, true); + setup_type(ID($_MUX_), {A, B, S}, {Y}, true); + setup_type(ID($_NMUX_), {A, B, S}, {Y}, true); + setup_type(ID($_MUX4_), {A, B, C, D, S, T}, {Y}, true); + setup_type(ID($_MUX8_), {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true); + setup_type(ID($_MUX16_), {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true); + setup_type(ID($_AOI3_), {A, B, C}, {Y}, true); + setup_type(ID($_OAI3_), {A, B, C}, {Y}, true); + setup_type(ID($_AOI4_), {A, B, C, D}, {Y}, true); + setup_type(ID($_OAI4_), {A, B, C, D}, {Y}, true); } void setup_stdcells_mem() { + IdString S = ID(S), R = ID(R), C = ID(C); + IdString D = ID(D), Q = ID(Q), E = ID(E); + std::vector list_np = {'N', 'P'}, list_01 = {'0', '1'}; for (auto c1 : list_np) for (auto c2 : list_np) - setup_type(stringf("$_SR_%c%c_", c1, c2), {ID::S, ID::R}, {ID::Q}); + setup_type(stringf("$_SR_%c%c_", c1, c2), {S, R}, {Q}); - setup_type(ID($_FF_), {ID::D}, {ID::Q}); + setup_type(ID($_FF_), {D}, {Q}); for (auto c1 : list_np) - setup_type(stringf("$_DFF_%c_", c1), {ID::C, ID::D}, {ID::Q}); - - for (auto c1 : list_np) - for (auto c2 : list_np) - setup_type(stringf("$_DFFE_%c%c_", c1, c2), {ID::C, ID::D, ID::E}, {ID::Q}); + setup_type(stringf("$_DFF_%c_", c1), {C, D}, {Q}); for (auto c1 : list_np) for (auto c2 : list_np) - for (auto c3 : list_01) - setup_type(stringf("$_DFF_%c%c%c_", c1, c2, c3), {ID::C, ID::R, ID::D}, {ID::Q}); + setup_type(stringf("$_DFFE_%c%c_", c1, c2), {C, D, E}, {Q}); for (auto c1 : list_np) for (auto c2 : list_np) for (auto c3 : list_01) - for (auto c4 : list_np) - setup_type(stringf("$_DFFE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}); + setup_type(stringf("$_DFF_%c%c%c_", c1, c2, c3), {C, R, D}, {Q}); for (auto c1 : list_np) for (auto c2 : list_np) for (auto c3 : list_np) - setup_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}); - - for (auto c1 : list_np) - for (auto c2 : list_np) - for (auto c3 : list_np) - for (auto c4 : list_np) - setup_type(stringf("$_DFFSRE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}); - - for (auto c1 : list_np) - for (auto c2 : list_np) - for (auto c3 : list_01) - setup_type(stringf("$_SDFF_%c%c%c_", c1, c2, c3), {ID::C, ID::R, ID::D}, {ID::Q}); - - for (auto c1 : list_np) - for (auto c2 : list_np) - for (auto c3 : list_01) - for (auto c4 : list_np) - setup_type(stringf("$_SDFFE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}); - - for (auto c1 : list_np) - for (auto c2 : list_np) - for (auto c3 : list_01) - for (auto c4 : list_np) - setup_type(stringf("$_SDFFCE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}); + setup_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {C, S, R, D}, {Q}); for (auto c1 : list_np) - setup_type(stringf("$_DLATCH_%c_", c1), {ID::E, ID::D}, {ID::Q}); - - for (auto c1 : list_np) - for (auto c2 : list_np) - for (auto c3 : list_01) - setup_type(stringf("$_DLATCH_%c%c%c_", c1, c2, c3), {ID::E, ID::R, ID::D}, {ID::Q}); + setup_type(stringf("$_DLATCH_%c_", c1), {E, D}, {Q}); for (auto c1 : list_np) for (auto c2 : list_np) for (auto c3 : list_np) - setup_type(stringf("$_DLATCHSR_%c%c%c_", c1, c2, c3), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}); + setup_type(stringf("$_DLATCHSR_%c%c%c_", c1, c2, c3), {E, S, R, D}, {Q}); } void clear() @@ -311,7 +300,7 @@ struct CellTypes signed1 = false, signed2 = false; } -#define HANDLE_CELL_TYPE(_t) if (type == ID($##_t)) return const_ ## _t(arg1, arg2, signed1, signed2, result_len); +#define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len); HANDLE_CELL_TYPE(not) HANDLE_CELL_TYPE(and) HANDLE_CELL_TYPE(or) @@ -344,8 +333,6 @@ struct CellTypes HANDLE_CELL_TYPE(mul) HANDLE_CELL_TYPE(div) HANDLE_CELL_TYPE(mod) - HANDLE_CELL_TYPE(divfloor) - HANDLE_CELL_TYPE(modfloor) HANDLE_CELL_TYPE(pow) HANDLE_CELL_TYPE(pos) HANDLE_CELL_TYPE(neg) @@ -384,8 +371,8 @@ struct CellTypes { if (cell->type == ID($slice)) { RTLIL::Const ret; - int width = cell->parameters.at(ID::Y_WIDTH).as_int(); - int offset = cell->parameters.at(ID::OFFSET).as_int(); + int width = cell->parameters.at(ID(Y_WIDTH)).as_int(); + int offset = cell->parameters.at(ID(OFFSET)).as_int(); ret.bits.insert(ret.bits.end(), arg1.bits.begin()+offset, arg1.bits.begin()+offset+width); return ret; } @@ -398,9 +385,9 @@ struct CellTypes if (cell->type == ID($lut)) { - int width = cell->parameters.at(ID::WIDTH).as_int(); + int width = cell->parameters.at(ID(WIDTH)).as_int(); - std::vector t = cell->parameters.at(ID::LUT).bits; + std::vector t = cell->parameters.at(ID(LUT)).bits; while (GetSize(t) < (1 << width)) t.push_back(State::S0); t.resize(1 << width); @@ -424,9 +411,9 @@ struct CellTypes if (cell->type == ID($sop)) { - int width = cell->parameters.at(ID::WIDTH).as_int(); - int depth = cell->parameters.at(ID::DEPTH).as_int(); - std::vector t = cell->parameters.at(ID::TABLE).bits; + int width = cell->parameters.at(ID(WIDTH)).as_int(); + int depth = cell->parameters.at(ID(DEPTH)).as_int(); + std::vector t = cell->parameters.at(ID(TABLE)).bits; while (GetSize(t) < width*depth*2) t.push_back(State::S0); @@ -460,9 +447,9 @@ struct CellTypes return default_ret; } - bool signed_a = cell->parameters.count(ID::A_SIGNED) > 0 && cell->parameters[ID::A_SIGNED].as_bool(); - bool signed_b = cell->parameters.count(ID::B_SIGNED) > 0 && cell->parameters[ID::B_SIGNED].as_bool(); - int result_len = cell->parameters.count(ID::Y_WIDTH) > 0 ? cell->parameters[ID::Y_WIDTH].as_int() : -1; + bool signed_a = cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool(); + bool signed_b = cell->parameters.count(ID(B_SIGNED)) > 0 && cell->parameters[ID(B_SIGNED)].as_bool(); + int result_len = cell->parameters.count(ID(Y_WIDTH)) > 0 ? cell->parameters[ID(Y_WIDTH)].as_int() : -1; return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len, errp); } diff --git a/kernel/consteval.h b/kernel/consteval.h index ff8cf86d62b..7a83d28e7d3 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -91,10 +91,10 @@ struct ConstEval { if (cell->type == ID($lcu)) { - RTLIL::SigSpec sig_p = cell->getPort(ID::P); - RTLIL::SigSpec sig_g = cell->getPort(ID::G); - RTLIL::SigSpec sig_ci = cell->getPort(ID::CI); - RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort(ID::CO))); + RTLIL::SigSpec sig_p = cell->getPort(ID(P)); + RTLIL::SigSpec sig_g = cell->getPort(ID(G)); + RTLIL::SigSpec sig_ci = cell->getPort(ID(CI)); + RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort(ID(CO)))); if (sig_co.is_fully_const()) return true; @@ -133,8 +133,8 @@ struct ConstEval if (sig_y.is_fully_const()) return true; - if (cell->hasPort(ID::S)) { - sig_s = cell->getPort(ID::S); + if (cell->hasPort(ID(S))) { + sig_s = cell->getPort(ID(S)); if (!eval(sig_s, undef, cell)) return false; } @@ -200,8 +200,8 @@ struct ConstEval } else if (cell->type == ID($fa)) { - RTLIL::SigSpec sig_c = cell->getPort(ID::C); - RTLIL::SigSpec sig_x = cell->getPort(ID::X); + RTLIL::SigSpec sig_c = cell->getPort(ID(C)); + RTLIL::SigSpec sig_x = cell->getPort(ID(X)); int width = GetSize(sig_c); if (!eval(sig_a, undef, cell)) @@ -229,11 +229,11 @@ struct ConstEval } else if (cell->type == ID($alu)) { - bool signed_a = cell->parameters.count(ID::A_SIGNED) > 0 && cell->parameters[ID::A_SIGNED].as_bool(); - bool signed_b = cell->parameters.count(ID::B_SIGNED) > 0 && cell->parameters[ID::B_SIGNED].as_bool(); + bool signed_a = cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool(); + bool signed_b = cell->parameters.count(ID(B_SIGNED)) > 0 && cell->parameters[ID(B_SIGNED)].as_bool(); - RTLIL::SigSpec sig_ci = cell->getPort(ID::CI); - RTLIL::SigSpec sig_bi = cell->getPort(ID::BI); + RTLIL::SigSpec sig_ci = cell->getPort(ID(CI)); + RTLIL::SigSpec sig_bi = cell->getPort(ID(BI)); if (!eval(sig_a, undef, cell)) return false; @@ -247,8 +247,8 @@ struct ConstEval if (!eval(sig_bi, undef, cell)) return false; - RTLIL::SigSpec sig_x = cell->getPort(ID::X); - RTLIL::SigSpec sig_co = cell->getPort(ID::CO); + RTLIL::SigSpec sig_x = cell->getPort(ID(X)); + RTLIL::SigSpec sig_co = cell->getPort(ID(CO)); bool any_input_undef = !(sig_a.is_fully_def() && sig_b.is_fully_def() && sig_ci.is_fully_def() && sig_bi.is_fully_def()); sig_a.extend_u0(GetSize(sig_y), signed_a); @@ -309,10 +309,10 @@ struct ConstEval RTLIL::SigSpec sig_c, sig_d; if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_))) { - if (cell->hasPort(ID::C)) - sig_c = cell->getPort(ID::C); - if (cell->hasPort(ID::D)) - sig_d = cell->getPort(ID::D); + if (cell->hasPort(ID(C))) + sig_c = cell->getPort(ID(C)); + if (cell->hasPort(ID(D))) + sig_d = cell->getPort(ID(D)); } if (sig_a.size() > 0 && !eval(sig_a, undef, cell)) diff --git a/kernel/constids.inc b/kernel/constids.inc deleted file mode 100644 index 69bc06d2c6a..00000000000 --- a/kernel/constids.inc +++ /dev/null @@ -1,224 +0,0 @@ -X(A) -X(abc9_box) -X(abc9_box_id) -X(abc9_box_seq) -X(abc9_bypass) -X(abc9_carry) -X(abc9_flop) -X(abc9_keep) -X(abc9_lut) -X(abc9_mergeability) -X(abc9_scc_id) -X(abcgroup) -X(ABITS) -X(ADDR) -X(allconst) -X(allseq) -X(always_comb) -X(always_ff) -X(always_latch) -X(anyconst) -X(anyseq) -X(ARST) -X(ARST_POLARITY) -X(ARST_VALUE) -X(A_SIGNED) -X(A_WIDTH) -X(B) -X(BI) -X(blackbox) -X(B_SIGNED) -X(bugpoint_keep) -X(B_WIDTH) -X(C) -X(cells_not_processed) -X(CFG_ABITS) -X(CFG_DBITS) -X(CFG_INIT) -X(CI) -X(CLK) -X(clkbuf_driver) -X(clkbuf_inhibit) -X(clkbuf_inv) -X(clkbuf_sink) -X(CLK_ENABLE) -X(CLK_POLARITY) -X(CLR) -X(CLR_POLARITY) -X(CO) -X(CONFIG) -X(CONFIG_WIDTH) -X(CTRL_IN) -X(CTRL_IN_WIDTH) -X(CTRL_OUT) -X(CTRL_OUT_WIDTH) -X(D) -X(DAT) -X(DATA) -X(DAT_DST_PEN) -X(DAT_DST_POL) -X(defaultvalue) -X(DELAY) -X(DEPTH) -X(DST) -X(DST_EN) -X(DST_PEN) -X(DST_POL) -X(DST_WIDTH) -X(dynports) -X(E) -X(EDGE_EN) -X(EDGE_POL) -X(EN) -X(EN_DST) -X(EN_POLARITY) -X(EN_SRC) -X(enum_base_type) -X(enum_type) -X(equiv_merged) -X(equiv_region) -X(extract_order) -X(F) -X(force_downto) -X(force_upto) -X(fsm_encoding) -X(fsm_export) -X(FULL) -X(full_case) -X(G) -X(gclk) -X(gentb_clock) -X(gentb_constant) -X(gentb_skip) -X(H) -X(hdlname) -X(hierconn) -X(I) -X(INIT) -X(init) -X(initial_top) -X(interface_modport) -X(interfaces_replaced_in_module) -X(interface_type) -X(invertible_pin) -X(iopad_external_pin) -X(is_interface) -X(J) -X(K) -X(keep) -X(keep_hierarchy) -X(L) -X(lib_whitebox) -X(localparam) -X(LUT) -X(lut_keep) -X(M) -X(maximize) -X(mem2reg) -X(MEMID) -X(minimize) -X(module_not_derived) -X(N) -X(NAME) -X(noblackbox) -X(nolatches) -X(nomem2init) -X(nomem2reg) -X(nomeminit) -X(nosync) -X(nowrshmsk) -X(O) -X(OFFSET) -X(onehot) -X(P) -X(parallel_case) -X(parameter) -X(PRIORITY) -X(Q) -X(qwp_position) -X(R) -X(RD_ADDR) -X(RD_CLK) -X(RD_CLK_ENABLE) -X(RD_CLK_POLARITY) -X(RD_DATA) -X(RD_EN) -X(RD_PORTS) -X(RD_TRANSPARENT) -X(reg) -X(S) -X(SET) -X(SET_POLARITY) -X(SIZE) -X(SRC) -X(src) -X(SRC_DST_PEN) -X(SRC_DST_POL) -X(SRC_EN) -X(SRC_PEN) -X(SRC_POL) -X(SRC_WIDTH) -X(SRST) -X(SRST_POLARITY) -X(SRST_VALUE) -X(STATE_BITS) -X(STATE_NUM) -X(STATE_NUM_LOG2) -X(STATE_RST) -X(STATE_TABLE) -X(submod) -X(S_WIDTH) -X(T) -X(TABLE) -X(techmap_autopurge) -X(_TECHMAP_BITS_CONNMAP_) -X(_TECHMAP_CELLTYPE_) -X(techmap_celltype) -X(_TECHMAP_FAIL_) -X(techmap_maccmap) -X(_TECHMAP_REPLACE_) -X(techmap_simplemap) -X(_techmap_special_) -X(techmap_wrap) -X(T_FALL_MAX) -X(T_FALL_MIN) -X(T_FALL_TYP) -X(T_LIMIT) -X(T_LIMIT2) -X(T_LIMIT2_MAX) -X(T_LIMIT2_MIN) -X(T_LIMIT2_TYP) -X(T_LIMIT_MAX) -X(T_LIMIT_MIN) -X(T_LIMIT_TYP) -X(to_delete) -X(top) -X(TRANS_NUM) -X(TRANSPARENT) -X(TRANS_TABLE) -X(T_RISE_MAX) -X(T_RISE_MIN) -X(T_RISE_TYP) -X(TYPE) -X(U) -X(unique) -X(unused_bits) -X(V) -X(via_celltype) -X(wand) -X(whitebox) -X(WIDTH) -X(wildcard_port_conns) -X(wiretype) -X(wor) -X(WORDS) -X(WR_ADDR) -X(WR_CLK) -X(WR_CLK_ENABLE) -X(WR_CLK_POLARITY) -X(WR_DATA) -X(WR_EN) -X(WR_PORTS) -X(X) -X(Y) -X(Y_WIDTH) diff --git a/kernel/driver.cc b/kernel/driver.cc index 57ed7b8b452..70a97c4b955 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -155,19 +155,6 @@ int yosys_history_offset = 0; std::string yosys_history_file; #endif -#if defined(__wasm) -extern "C" { - // FIXME: WASI does not currently support exceptions. - void* __cxa_allocate_exception(size_t thrown_size) throw() { - return malloc(thrown_size); - } - bool __cxa_uncaught_exception() throw(); - void __cxa_throw(void* thrown_exception, struct std::type_info * tinfo, void (*dest)(void*)) { - std::terminate(); - } -} -#endif - void yosys_atexit() { #if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE) @@ -308,9 +295,6 @@ int main(int argc, char **argv) printf(" -E \n"); printf(" write a Makefile dependencies file with in- and output file names\n"); printf("\n"); - printf(" -x \n"); - printf(" do not print warnings for the specified experimental feature\n"); - printf("\n"); printf(" -g\n"); printf(" globally enable debug log messages\n"); printf("\n"); @@ -333,14 +317,8 @@ int main(int argc, char **argv) exit(0); } - if (argc == 2 && (!strcmp(argv[1], "-V") || !strcmp(argv[1], "-version") || !strcmp(argv[1], "--version"))) - { - printf("%s\n", yosys_version_str); - exit(0); - } - int opt; - while ((opt = getopt(argc, argv, "MXAQTVSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:P:E:x:")) != -1) + while ((opt = getopt(argc, argv, "MXAQTVSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:P:E:")) != -1) { switch (opt) { @@ -426,13 +404,22 @@ int main(int argc, char **argv) scriptfile_tcl = true; break; case 'W': - log_warn_regexes.push_back(YS_REGEX_COMPILE(optarg)); + log_warn_regexes.push_back(std::regex(optarg, + std::regex_constants::nosubs | + std::regex_constants::optimize | + std::regex_constants::egrep)); break; case 'w': - log_nowarn_regexes.push_back(YS_REGEX_COMPILE(optarg)); + log_nowarn_regexes.push_back(std::regex(optarg, + std::regex_constants::nosubs | + std::regex_constants::optimize | + std::regex_constants::egrep)); break; case 'e': - log_werror_regexes.push_back(YS_REGEX_COMPILE(optarg)); + log_werror_regexes.push_back(std::regex(optarg, + std::regex_constants::nosubs | + std::regex_constants::optimize | + std::regex_constants::egrep)); break; case 'D': vlog_defines.push_back(optarg); @@ -462,9 +449,6 @@ int main(int argc, char **argv) case 'E': depsfile = optarg; break; - case 'x': - log_experimentals_ignored.insert(optarg); - break; default: fprintf(stderr, "Run '%s -h' for help.\n", argv[0]); exit(1); @@ -562,10 +546,6 @@ int main(int argc, char **argv) fprintf(f, "\n"); } - if (log_expect_no_warnings && log_warnings_count_noexpect) - log_error("Unexpected warnings found: %d unique messages, %d total, %d expected\n", GetSize(log_warnings), - log_warnings_count, log_warnings_count - log_warnings_count_noexpect); - if (print_stats) { std::string hash = log_hasher->final().substr(0, 10); @@ -581,33 +561,39 @@ int main(int argc, char **argv) if (log_warnings_count) log("Warnings: %d unique messages, %d total\n", GetSize(log_warnings), log_warnings_count); - - if (!log_experimentals.empty()) - log("Warnings: %d experimental features used (not excluded with -x).\n", GetSize(log_experimentals)); - #ifdef _WIN32 log("End of script. Logfile hash: %s\n", hash.c_str()); #else std::string meminfo; std::string stats_divider = ", "; +# if defined(__linux__) + std::ifstream statm; + statm.open(stringf("/proc/%lld/statm", (long long)getpid())); + if (statm.is_open()) { + int sz_total, sz_resident; + statm >> sz_total >> sz_resident; + meminfo = stringf(", MEM: %.2f MB total, %.2f MB resident", + sz_total * (getpagesize() / 1024.0 / 1024.0), + sz_resident * (getpagesize() / 1024.0 / 1024.0)); + stats_divider = "\n"; + } +# elif defined(__FreeBSD__) + pid_t pid = getpid(); + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid}; + struct kinfo_proc kip; + size_t kip_len = sizeof(kip); + if (sysctl(mib, 4, &kip, &kip_len, NULL, 0) == 0) { + vm_size_t sz_total = kip.ki_size; + segsz_t sz_resident = kip.ki_rssize; + meminfo = stringf(", MEM: %.2f MB total, %.2f MB resident", + (int)sz_total / 1024.0 / 1024.0, + (int)sz_resident * (getpagesize() / 1024.0 / 1024.0)); + stats_divider = "\n"; + } +# endif struct rusage ru_buffer; getrusage(RUSAGE_SELF, &ru_buffer); - if (yosys_design->scratchpad_get_bool("print_stats.include_children")) { - struct rusage ru_buffer_children; - getrusage(RUSAGE_CHILDREN, &ru_buffer_children); - ru_buffer.ru_utime.tv_sec += ru_buffer_children.ru_utime.tv_sec; - ru_buffer.ru_utime.tv_usec += ru_buffer_children.ru_utime.tv_usec; - ru_buffer.ru_stime.tv_sec += ru_buffer_children.ru_stime.tv_sec; - ru_buffer.ru_stime.tv_usec += ru_buffer_children.ru_stime.tv_usec; -#if defined(__linux__) || defined(__FreeBSD__) - ru_buffer.ru_maxrss = std::max(ru_buffer.ru_maxrss, ru_buffer_children.ru_maxrss); -#endif - } -#if defined(__linux__) || defined(__FreeBSD__) - meminfo = stringf(", MEM: %.2f MB peak", - ru_buffer.ru_maxrss / 1024.0); -#endif log("End of script. Logfile hash: %s%sCPU: user %.2fs system %.2fs%s\n", hash.c_str(), stats_divider.c_str(), ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec, ru_buffer.ru_stime.tv_sec + 1e-6 * ru_buffer.ru_stime.tv_usec, meminfo.c_str()); @@ -674,8 +660,6 @@ int main(int argc, char **argv) } #endif - log_check_expected(); - yosys_atexit(); memhasher_off(); diff --git a/kernel/hashlib.h b/kernel/hashlib.h index a523afadd08..e7cb312ed87 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -207,7 +207,6 @@ class dict entry_t() { } entry_t(const std::pair &udata, int next) : udata(udata), next(next) { } entry_t(std::pair &&udata, int next) : udata(std::move(udata)), next(next) { } - bool operator<(const entry_t &other) const { return udata.first < other.udata.first; } }; std::vector hashtable; @@ -315,11 +314,11 @@ class dict int do_insert(const K &key, int &hash) { if (hashtable.empty()) { - entries.emplace_back(std::pair(key, T()), -1); + entries.push_back(entry_t(std::pair(key, T()), -1)); do_rehash(); hash = do_hash(key); } else { - entries.emplace_back(std::pair(key, T()), hashtable[hash]); + entries.push_back(entry_t(std::pair(key, T()), hashtable[hash])); hashtable[hash] = entries.size() - 1; } return entries.size() - 1; @@ -328,25 +327,11 @@ class dict int do_insert(const std::pair &value, int &hash) { if (hashtable.empty()) { - entries.emplace_back(value, -1); + entries.push_back(entry_t(value, -1)); do_rehash(); hash = do_hash(value.first); } else { - entries.emplace_back(value, hashtable[hash]); - hashtable[hash] = entries.size() - 1; - } - return entries.size() - 1; - } - - int do_insert(std::pair &&rvalue, int &hash) - { - if (hashtable.empty()) { - auto key = rvalue.first; - entries.emplace_back(std::forward>(rvalue), -1); - do_rehash(); - hash = do_hash(key); - } else { - entries.emplace_back(std::forward>(rvalue), hashtable[hash]); + entries.push_back(entry_t(value, hashtable[hash])); hashtable[hash] = entries.size() - 1; } return entries.size() - 1; @@ -363,7 +348,6 @@ class dict public: const_iterator() { } const_iterator operator++() { index--; return *this; } - const_iterator operator+=(int amt) { index -= amt; return *this; } bool operator<(const const_iterator &other) const { return index > other.index; } bool operator==(const const_iterator &other) const { return index == other.index; } bool operator!=(const const_iterator &other) const { return index != other.index; } @@ -381,7 +365,6 @@ class dict public: iterator() { } iterator operator++() { index--; return *this; } - iterator operator+=(int amt) { index -= amt; return *this; } bool operator<(const iterator &other) const { return index > other.index; } bool operator==(const iterator &other) const { return index == other.index; } bool operator!=(const iterator &other) const { return index != other.index; } @@ -458,56 +441,6 @@ class dict return std::pair(iterator(this, i), true); } - std::pair insert(std::pair &&rvalue) - { - int hash = do_hash(rvalue.first); - int i = do_lookup(rvalue.first, hash); - if (i >= 0) - return std::pair(iterator(this, i), false); - i = do_insert(std::forward>(rvalue), hash); - return std::pair(iterator(this, i), true); - } - - std::pair emplace(K const &key, T const &value) - { - int hash = do_hash(key); - int i = do_lookup(key, hash); - if (i >= 0) - return std::pair(iterator(this, i), false); - i = do_insert(std::make_pair(key, value), hash); - return std::pair(iterator(this, i), true); - } - - std::pair emplace(K const &key, T &&rvalue) - { - int hash = do_hash(key); - int i = do_lookup(key, hash); - if (i >= 0) - return std::pair(iterator(this, i), false); - i = do_insert(std::make_pair(key, std::forward(rvalue)), hash); - return std::pair(iterator(this, i), true); - } - - std::pair emplace(K &&rkey, T const &value) - { - int hash = do_hash(rkey); - int i = do_lookup(rkey, hash); - if (i >= 0) - return std::pair(iterator(this, i), false); - i = do_insert(std::make_pair(std::forward(rkey), value), hash); - return std::pair(iterator(this, i), true); - } - - std::pair emplace(K &&rkey, T &&rvalue) - { - int hash = do_hash(rkey); - int i = do_lookup(rkey, hash); - if (i >= 0) - return std::pair(iterator(this, i), false); - i = do_insert(std::make_pair(std::forward(rkey), std::forward(rvalue)), hash); - return std::pair(iterator(this, i), true); - } - int erase(const K &key) { int hash = do_hash(key); @@ -572,7 +505,7 @@ class dict return entries[i].udata.second; } - const T& at(const K &key, const T &defval) const + T at(const K &key, const T &defval) const { int hash = do_hash(key); int i = do_lookup(key, hash); @@ -618,15 +551,6 @@ class dict return !operator==(other); } - unsigned int hash() const { - unsigned int h = mkhash_init; - for (auto &entry : entries) { - h ^= hash_ops::hash(entry.udata.first); - h ^= hash_ops::hash(entry.udata.second); - } - return h; - } - void reserve(size_t n) { entries.reserve(n); } size_t size() const { return entries.size(); } bool empty() const { return entries.empty(); } @@ -654,7 +578,6 @@ class pool entry_t() { } entry_t(const K &udata, int next) : udata(udata), next(next) { } - entry_t(K &&udata, int next) : udata(std::move(udata)), next(next) { } }; std::vector hashtable; @@ -758,24 +681,11 @@ class pool int do_insert(const K &value, int &hash) { if (hashtable.empty()) { - entries.emplace_back(value, -1); + entries.push_back(entry_t(value, -1)); do_rehash(); hash = do_hash(value); } else { - entries.emplace_back(value, hashtable[hash]); - hashtable[hash] = entries.size() - 1; - } - return entries.size() - 1; - } - - int do_insert(K &&rvalue, int &hash) - { - if (hashtable.empty()) { - entries.emplace_back(std::forward(rvalue), -1); - do_rehash(); - hash = do_hash(rvalue); - } else { - entries.emplace_back(std::forward(rvalue), hashtable[hash]); + entries.push_back(entry_t(value, hashtable[hash])); hashtable[hash] = entries.size() - 1; } return entries.size() - 1; @@ -873,22 +783,6 @@ class pool return std::pair(iterator(this, i), true); } - std::pair insert(K &&rvalue) - { - int hash = do_hash(rvalue); - int i = do_lookup(rvalue, hash); - if (i >= 0) - return std::pair(iterator(this, i), false); - i = do_insert(std::forward(rvalue), hash); - return std::pair(iterator(this, i), true); - } - - template - std::pair emplace(Args&&... args) - { - return insert(K(std::forward(args)...)); - } - int erase(const K &key) { int hash = do_hash(key); @@ -1003,21 +897,7 @@ class idict pool database; public: - class const_iterator : public std::iterator - { - friend class idict; - protected: - const idict &container; - int index; - const_iterator(const idict &container, int index) : container(container), index(index) { } - public: - const_iterator() { } - const_iterator operator++() { index++; return *this; } - bool operator==(const const_iterator &other) const { return index == other.index; } - bool operator!=(const const_iterator &other) const { return index != other.index; } - const K &operator*() const { return container[index]; } - const K *operator->() const { return &container[index]; } - }; + typedef typename pool::const_iterator const_iterator; int operator()(const K &key) { @@ -1075,9 +955,9 @@ class idict bool empty() const { return database.empty(); } void clear() { database.clear(); } - const_iterator begin() const { return const_iterator(*this, offset); } - const_iterator element(int n) const { return const_iterator(*this, n); } - const_iterator end() const { return const_iterator(*this, offset + size()); } + const_iterator begin() const { return database.begin(); } + const_iterator element(int n) const { return database.element(n); } + const_iterator end() const { return database.end(); } }; template diff --git a/kernel/log.cc b/kernel/log.cc index 1c1d0182e93..c5ba0d10d8d 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -41,12 +41,9 @@ YOSYS_NAMESPACE_BEGIN std::vector log_files; std::vector log_streams; std::map> log_hdump; -std::vector log_warn_regexes, log_nowarn_regexes, log_werror_regexes; -dict log_expect_log, log_expect_warning, log_expect_error; -std::set log_warnings, log_experimentals, log_experimentals_ignored; +std::vector log_warn_regexes, log_nowarn_regexes, log_werror_regexes; +std::set log_warnings; int log_warnings_count = 0; -int log_warnings_count_noexpect = 0; -bool log_expect_no_warnings = false; bool log_hdump_all = false; FILE *log_errfile = NULL; SHA1 *log_hasher = NULL; @@ -71,8 +68,6 @@ int string_buf_index = -1; static struct timeval initial_tv = { 0, 0 }; static bool next_print_log = false; static int log_newline_count = 0; -static bool check_expected_logs = true; -static bool display_error_log_msg = true; static void log_id_cache_clear() { @@ -167,7 +162,7 @@ void logv(const char *format, va_list ap) { log_warn_regex_recusion_guard = true; - if (log_warn_regexes.empty() && log_expect_log.empty()) + if (log_warn_regexes.empty()) { linebuffer.clear(); } @@ -177,13 +172,8 @@ void logv(const char *format, va_list ap) if (!linebuffer.empty() && linebuffer.back() == '\n') { for (auto &re : log_warn_regexes) - if (YS_REGEX_NS::regex_search(linebuffer, re)) + if (std::regex_search(linebuffer, re)) log_warning("Found log message matching -W regex:\n%s", str.c_str()); - - for (auto &item : log_expect_log) - if (YS_REGEX_NS::regex_search(linebuffer, item.second.pattern)) - item.second.current_count++; - linebuffer.clear(); } } @@ -238,7 +228,7 @@ static void logv_warning_with_prefix(const char *prefix, bool suppressed = false; for (auto &re : log_nowarn_regexes) - if (YS_REGEX_NS::regex_search(message, re)) + if (std::regex_search(message, re)) suppressed = true; if (suppressed) @@ -251,16 +241,9 @@ static void logv_warning_with_prefix(const char *prefix, log_make_debug = 0; for (auto &re : log_werror_regexes) - if (YS_REGEX_NS::regex_search(message, re)) + if (std::regex_search(message, re)) log_error("%s", message.c_str()); - bool warning_match = false; - for (auto &item : log_expect_warning) - if (YS_REGEX_NS::regex_search(message, item.second.pattern)) { - item.second.current_count++; - warning_match = true; - } - if (log_warnings.count(message)) { log("%s%s", prefix, message.c_str()); @@ -280,8 +263,6 @@ static void logv_warning_with_prefix(const char *prefix, log_warnings.insert(message); } - if (!warning_match) - log_warnings_count_noexpect++; log_warnings_count++; log_make_debug = bak_log_make_debug; } @@ -319,7 +300,7 @@ void log_file_info(const std::string &filename, int lineno, va_end(ap); } -[[noreturn]] +YS_ATTRIBUTE(noreturn) static void logv_error_with_prefix(const char *prefix, const char *format, va_list ap) { @@ -339,8 +320,7 @@ static void logv_error_with_prefix(const char *prefix, f = stderr; log_last_error = vstringf(format, ap); - if (display_error_log_msg) - log("%s%s", prefix, log_last_error.c_str()); + log("%s%s", prefix, log_last_error.c_str()); log_flush(); log_make_debug = bak_log_make_debug; @@ -348,15 +328,6 @@ static void logv_error_with_prefix(const char *prefix, if (log_error_atexit) log_error_atexit(); - for (auto &item : log_expect_error) - if (YS_REGEX_NS::regex_search(log_last_error, item.second.pattern)) - item.second.current_count++; - - if (check_expected_logs) - log_check_expected(); - - YS_DEBUGTRAP_IF_DEBUGGING; - #ifdef EMSCRIPTEN log_files = backup_log_files; throw 0; @@ -406,19 +377,6 @@ void log_warning(const char *format, ...) va_end(ap); } -void log_experimental(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - string s = vstringf(format, ap); - va_end(ap); - - if (log_experimentals_ignored.count(s) == 0 && log_experimentals.count(s) == 0) { - log_warning("Feature '%s' is experimental.\n", s.c_str()); - log_experimentals.insert(s); - } -} - void log_warning_noprefix(const char *format, ...) { va_list ap; @@ -665,52 +623,6 @@ void log_wire(RTLIL::Wire *wire, std::string indent) log("%s", buf.str().c_str()); } -void log_check_expected() -{ - check_expected_logs = false; - - for (auto &item : log_expect_warning) { - if (item.second.current_count == 0) { - log_warn_regexes.clear(); - log_error("Expected warning pattern '%s' not found !\n", item.first.c_str()); - } - if (item.second.current_count != item.second.expected_count) { - log_warn_regexes.clear(); - log_error("Expected warning pattern '%s' found %d time(s), instead of %d time(s) !\n", - item.first.c_str(), item.second.current_count, item.second.expected_count); - } - } - - for (auto &item : log_expect_log) { - if (item.second.current_count == 0) { - log_warn_regexes.clear(); - log_error("Expected log pattern '%s' not found !\n", item.first.c_str()); - } - if (item.second.current_count != item.second.expected_count) { - log_warn_regexes.clear(); - log_error("Expected log pattern '%s' found %d time(s), instead of %d time(s) !\n", - item.first.c_str(), item.second.current_count, item.second.expected_count); - } - } - - for (auto &item : log_expect_error) - if (item.second.current_count == item.second.expected_count) { - log_warn_regexes.clear(); - log("Expected error pattern '%s' found !!!\n", item.first.c_str()); - #ifdef EMSCRIPTEN - throw 0; - #elif defined(_MSC_VER) - _exit(0); - #else - _Exit(0); - #endif - } else { - display_error_log_msg = false; - log_warn_regexes.clear(); - log_error("Expected error pattern '%s' not found !\n", item.first.c_str()); - } -} - // --------------------------------------------------- // This is the magic behind the code coverage counters // --------------------------------------------------- diff --git a/kernel/log.h b/kernel/log.h index 8981c4cde1e..1f15f3459bc 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -23,41 +23,11 @@ #define LOG_H #include +#include -// In GCC 4.8 std::regex is not working correctlty, in order to make features -// using regular expressions to work replacement regex library is used -#if defined(__GNUC__) && !defined( __clang__) && ( __GNUC__ == 4 && __GNUC_MINOR__ <= 8) - #include - #define YS_REGEX_TYPE boost::xpressive::sregex - #define YS_REGEX_MATCH_TYPE boost::xpressive::smatch - #define YS_REGEX_NS boost::xpressive - #define YS_REGEX_COMPILE(param) boost::xpressive::sregex::compile(param, \ - boost::xpressive::regex_constants::nosubs | \ - boost::xpressive::regex_constants::optimize) - #define YS_REGEX_COMPILE_WITH_SUBS(param) boost::xpressive::sregex::compile(param, \ - boost::xpressive::regex_constants::optimize) -# else - #include - #define YS_REGEX_TYPE std::regex - #define YS_REGEX_MATCH_TYPE std::smatch - #define YS_REGEX_NS std - #define YS_REGEX_COMPILE(param) std::regex(param, \ - std::regex_constants::nosubs | \ - std::regex_constants::optimize | \ - std::regex_constants::egrep) - #define YS_REGEX_COMPILE_WITH_SUBS(param) std::regex(param, \ - std::regex_constants::optimize | \ - std::regex_constants::egrep) -#endif - -#if defined(_WIN32) -# include -#else +#ifndef _WIN32 # include # include -# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -# include -# endif #endif #if defined(_MSC_VER) @@ -74,51 +44,14 @@ YOSYS_NAMESPACE_BEGIN #define S__LINE__sub1(x) S__LINE__sub2(x) #define S__LINE__ S__LINE__sub1(__LINE__) -// YS_DEBUGTRAP is a macro that is functionally equivalent to a breakpoint -// if the platform provides such functionality, and does nothing otherwise. -// If no debugger is attached, it starts a just-in-time debugger if available, -// and crashes the process otherwise. -#if defined(_WIN32) -# define YS_DEBUGTRAP __debugbreak() -#else -# ifndef __has_builtin -// __has_builtin is a GCC/Clang extension; on a different compiler (or old enough GCC/Clang) -// that does not have it, using __has_builtin(...) is a syntax error. -# define __has_builtin(x) 0 -# endif -# if __has_builtin(__builtin_debugtrap) -# define YS_DEBUGTRAP __builtin_debugtrap() -# elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -# define YS_DEBUGTRAP raise(SIGTRAP) -# else -# define YS_DEBUGTRAP do {} while(0) -# endif -#endif - -// YS_DEBUGTRAP_IF_DEBUGGING is a macro that is functionally equivalent to a breakpoint -// if a debugger is attached, and does nothing otherwise. -#if defined(_WIN32) -# define YS_DEBUGTRAP_IF_DEBUGGING do { if (IsDebuggerPresent()) DebugBreak(); } while(0) -# elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -// There is no reliable (or portable) *nix equivalent of IsDebuggerPresent(). However, -// debuggers will stop when SIGTRAP is raised, even if the action is set to ignore. -# define YS_DEBUGTRAP_IF_DEBUGGING do { \ - auto old = signal(SIGTRAP, SIG_IGN); raise(SIGTRAP); signal(SIGTRAP, old); \ - } while(0) -#else -# define YS_DEBUGTRAP_IF_DEBUGGING do {} while(0) -#endif - struct log_cmd_error_exception { }; extern std::vector log_files; extern std::vector log_streams; extern std::map> log_hdump; -extern std::vector log_warn_regexes, log_nowarn_regexes, log_werror_regexes; -extern std::set log_warnings, log_experimentals, log_experimentals_ignored; +extern std::vector log_warn_regexes, log_nowarn_regexes, log_werror_regexes; +extern std::set log_warnings; extern int log_warnings_count; -extern int log_warnings_count_noexpect; -extern bool log_expect_no_warnings; extern bool log_hdump_all; extern FILE *log_errfile; extern SHA1 *log_hasher; @@ -139,28 +72,28 @@ void logv(const char *format, va_list ap); void logv_header(RTLIL::Design *design, const char *format, va_list ap); void logv_warning(const char *format, va_list ap); void logv_warning_noprefix(const char *format, va_list ap); -[[noreturn]] void logv_error(const char *format, va_list ap); +YS_NORETURN void logv_error(const char *format, va_list ap) YS_ATTRIBUTE(noreturn); void log(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); void log_header(RTLIL::Design *design, const char *format, ...) YS_ATTRIBUTE(format(printf, 2, 3)); void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); -void log_experimental(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); // Log with filename to report a problem in a source file. void log_file_warning(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); void log_file_info(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); void log_warning_noprefix(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); -[[noreturn]] void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); -[[noreturn]] void log_file_error(const string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); -[[noreturn]] void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); +YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); +void log_file_error(const string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4), noreturn); +YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); #ifndef NDEBUG static inline bool ys_debug(int n = 0) { if (log_force_debug) return true; log_debug_suppressed += n; return false; } +# define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0) #else static inline bool ys_debug(int = 0) { return false; } +# define log_debug(_fmt, ...) do { } while (0) #endif -# define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0) static inline void log_suppressed() { if (log_debug_suppressed && !log_make_debug) { @@ -201,20 +134,6 @@ void log_backtrace(const char *prefix, int levels); void log_reset_stack(); void log_flush(); -struct LogExpectedItem -{ - LogExpectedItem(const YS_REGEX_TYPE &pat, int expected) : - pattern(pat), expected_count(expected), current_count(0) {} - LogExpectedItem() : expected_count(0), current_count(0) {} - - YS_REGEX_TYPE pattern; - int expected_count; - int current_count; -}; - -extern dict log_expect_log, log_expect_warning, log_expect_error; -void log_check_expected(); - const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true); const char *log_const(const RTLIL::Const &value, bool autoint = true); const char *log_id(RTLIL::IdString id); @@ -235,7 +154,7 @@ static inline void log_assert_worker(bool cond, const char *expr, const char *fi } # define log_assert(_assert_expr_) YOSYS_NAMESPACE_PREFIX log_assert_worker(_assert_expr_, #_assert_expr_, __FILE__, __LINE__) #else -# define log_assert(_assert_expr_) do { if (0) { (void)(_assert_expr_); } } while(0) +# define log_assert(_assert_expr_) #endif #define log_abort() YOSYS_NAMESPACE_PREFIX log_error("Abort in %s:%d.\n", __FILE__, __LINE__) @@ -307,17 +226,19 @@ struct PerformanceTimer static int64_t query() { # ifdef _WIN32 return 0; +# elif defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) + struct timespec ts; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + return int64_t(ts.tv_sec)*1000000000 + ts.tv_nsec; # elif defined(RUSAGE_SELF) struct rusage rusage; - int64_t t = 0; - for (int who : {RUSAGE_SELF, RUSAGE_CHILDREN}) { - if (getrusage(who, &rusage) == -1) { - log_cmd_error("getrusage failed!\n"); - log_abort(); - } - t += 1000000000ULL * (int64_t) rusage.ru_utime.tv_sec + (int64_t) rusage.ru_utime.tv_usec * 1000ULL; - t += 1000000000ULL * (int64_t) rusage.ru_stime.tv_sec + (int64_t) rusage.ru_stime.tv_usec * 1000ULL; + int64_t t; + if (getrusage(RUSAGE_SELF, &rusage) == -1) { + log_cmd_error("getrusage failed!\n"); + log_abort(); } + t = 1000000000ULL * (int64_t) rusage.ru_utime.tv_sec + (int64_t) rusage.ru_utime.tv_usec * 1000ULL; + t += 1000000000ULL * (int64_t) rusage.ru_stime.tv_sec + (int64_t) rusage.ru_stime.tv_usec * 1000ULL; return t; # else # error "Don't know how to measure per-process CPU time. Need alternative method (times()/clocks()/gettimeofday()?)." @@ -368,7 +289,7 @@ static inline void log_dump_val_worker(char *v) { log("%s", v); } static inline void log_dump_val_worker(const char *v) { log("%s", v); } static inline void log_dump_val_worker(std::string v) { log("%s", v.c_str()); } static inline void log_dump_val_worker(PerformanceTimer p) { log("%f seconds", p.sec()); } -static inline void log_dump_args_worker(const char *p) { log_assert(*p == 0); } +static inline void log_dump_args_worker(const char *p YS_ATTRIBUTE(unused)) { log_assert(*p == 0); } void log_dump_val_worker(RTLIL::IdString v); void log_dump_val_worker(RTLIL::SigSpec v); void log_dump_val_worker(RTLIL::State v); diff --git a/kernel/macc.h b/kernel/macc.h index d216e6772e1..371f6737d32 100644 --- a/kernel/macc.h +++ b/kernel/macc.h @@ -104,11 +104,13 @@ struct Macc ports.clear(); bit_ports = cell->getPort(ID::B); - std::vector config_bits = cell->getParam(ID::CONFIG).bits; + std::vector config_bits = cell->getParam(ID(CONFIG)).bits; int config_cursor = 0; - int config_width = cell->getParam(ID::CONFIG_WIDTH).as_int(); +#ifndef NDEBUG + int config_width = cell->getParam(ID(CONFIG_WIDTH)).as_int(); log_assert(GetSize(config_bits) >= config_width); +#endif int num_bits = 0; if (config_bits[config_cursor++] == State::S1) num_bits |= 1; @@ -191,10 +193,10 @@ struct Macc cell->setPort(ID::A, port_a); cell->setPort(ID::B, bit_ports); - cell->setParam(ID::CONFIG, config_bits); - cell->setParam(ID::CONFIG_WIDTH, GetSize(config_bits)); - cell->setParam(ID::A_WIDTH, GetSize(port_a)); - cell->setParam(ID::B_WIDTH, GetSize(bit_ports)); + cell->setParam(ID(CONFIG), config_bits); + cell->setParam(ID(CONFIG_WIDTH), GetSize(config_bits)); + cell->setParam(ID(A_WIDTH), GetSize(port_a)); + cell->setParam(ID(B_WIDTH), GetSize(bit_ports)); } bool eval(RTLIL::Const &result) const diff --git a/kernel/modtools.h b/kernel/modtools.h index 29c510059ff..409562eb965 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -158,7 +158,7 @@ struct ModIndex : public RTLIL::Monitor #endif } - void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override + void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE { log_assert(module == cell->module); @@ -169,7 +169,7 @@ struct ModIndex : public RTLIL::Monitor port_add(cell, port, sig); } - void notify_connect(RTLIL::Module *mod, const RTLIL::SigSig &sigsig) override + void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const RTLIL::SigSig &sigsig) YS_OVERRIDE { log_assert(module == mod); @@ -214,13 +214,13 @@ struct ModIndex : public RTLIL::Monitor } } - void notify_connect(RTLIL::Module *mod, const std::vector&) override + void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const std::vector&) YS_OVERRIDE { log_assert(module == mod); auto_reload_module = true; } - void notify_blackout(RTLIL::Module *mod) override + void notify_blackout(RTLIL::Module *mod YS_ATTRIBUTE(unused)) YS_OVERRIDE { log_assert(module == mod); auto_reload_module = true; @@ -380,15 +380,22 @@ struct ModWalker } } - ModWalker(RTLIL::Design *design) : design(design), module(NULL) + ModWalker() : design(NULL), module(NULL) { - ct.setup(design); } - void setup(RTLIL::Module *module, CellTypes *filter_ct = NULL) + ModWalker(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL) { + setup(design, module, filter_ct); + } + + void setup(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL) + { + this->design = design; this->module = module; + ct.clear(); + ct.setup(design); sigmap.set(module); signal_drivers.clear(); diff --git a/kernel/register.cc b/kernel/register.cc index 34735a60854..37f2e5e1bf8 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -114,35 +114,20 @@ void Pass::run_register() void Pass::init_register() { - vector added_passes; while (first_queued_pass) { - added_passes.push_back(first_queued_pass); first_queued_pass->run_register(); first_queued_pass = first_queued_pass->next_queued_pass; } - for (auto added_pass : added_passes) - added_pass->on_register(); } void Pass::done_register() { - for (auto &it : pass_register) - it.second->on_shutdown(); - frontend_register.clear(); pass_register.clear(); backend_register.clear(); log_assert(first_queued_pass == NULL); } -void Pass::on_register() -{ -} - -void Pass::on_shutdown() -{ -} - Pass::~Pass() { } @@ -238,7 +223,6 @@ void Pass::call(RTLIL::Design *design, std::string command) return; if (tok[0] == '!') { -#if !defined(YOSYS_DISABLE_SPAWN) cmd_buf = command.substr(command.find('!') + 1); while (!cmd_buf.empty() && (cmd_buf.back() == ' ' || cmd_buf.back() == '\t' || cmd_buf.back() == '\r' || cmd_buf.back() == '\n')) @@ -248,9 +232,6 @@ void Pass::call(RTLIL::Design *design, std::string command) if (retCode != 0) log_cmd_error("Shell command returned error code %d.\n", retCode); return; -#else - log_cmd_error("Shell is not available.\n"); -#endif } while (!tok.empty()) { @@ -308,9 +289,6 @@ void Pass::call(RTLIL::Design *design, std::vector args) if (pass_register.count(args[0]) == 0) log_cmd_error("No such command: %s (type 'help' for a command overview)\n", args[0].c_str()); - if (pass_register[args[0]]->experimental_flag) - log_experimental("%s", args[0].c_str()); - size_t orig_sel_stack_pos = design->selection_stack.size(); auto state = pass_register[args[0]]->pre_execute(); pass_register[args[0]]->execute(args, design); @@ -404,18 +382,6 @@ void ScriptPass::run(std::string command, std::string info) } } -void ScriptPass::run_nocheck(std::string command, std::string info) -{ - if (active_design == nullptr) { - if (info.empty()) - log(" %s\n", command.c_str()); - else - log(" %s %s\n", command.c_str(), info.c_str()); - } else { - Pass::call(active_design, command); - } -} - void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to) { help_mode = false; @@ -489,21 +455,20 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector 0 && (buffer[buffer.size() - 1] == '\n' || buffer[buffer.size() - 1] == '\r')) @@ -753,7 +718,7 @@ static struct CellHelpMessages { struct HelpPass : public Pass { HelpPass() : Pass("help", "display help messages") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" help ................ list all commands\n"); @@ -822,7 +787,7 @@ struct HelpPass : public Pass { fclose(f); } - void execute(std::vector args, RTLIL::Design*) override + void execute(std::vector args, RTLIL::Design*) YS_OVERRIDE { if (args.size() == 1) { log("\n"); @@ -844,11 +809,6 @@ struct HelpPass : public Pass { log("="); log("\n"); it.second->help(); - if (it.second->experimental_flag) { - log("\n"); - log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", it.first.c_str()); - log("\n"); - } } } else if (args[1] == "-cells") { @@ -871,11 +831,6 @@ struct HelpPass : public Pass { std::ostringstream buf; log_streams.push_back(&buf); it.second->help(); - if (it.second->experimental_flag) { - log("\n"); - log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", it.first.c_str()); - log("\n"); - } log_streams.pop_back(); write_tex(f, it.first, it.second->short_help, buf.str()); } @@ -888,11 +843,6 @@ struct HelpPass : public Pass { std::ostringstream buf; log_streams.push_back(&buf); it.second->help(); - if (it.second->experimental_flag) { - log("\n"); - log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", it.first.c_str()); - log("\n"); - } log_streams.pop_back(); write_html(f, it.first, it.second->short_help, buf.str()); } @@ -900,11 +850,6 @@ struct HelpPass : public Pass { } else if (pass_register.count(args[1])) { pass_register.at(args[1])->help(); - if (pass_register.at(args[1])->experimental_flag) { - log("\n"); - log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", args[1].c_str()); - log("\n"); - } } else if (cell_help_messages.cell_help.count(args[1])) { log("%s", cell_help_messages.cell_help.at(args[1]).c_str()); @@ -926,7 +871,7 @@ struct HelpPass : public Pass { struct EchoPass : public Pass { EchoPass() : Pass("echo", "turning echoing back of commands on and off") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" echo on\n"); @@ -939,7 +884,7 @@ struct EchoPass : public Pass { log("Do not print all commands to log before executing them. (default)\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design*) override + void execute(std::vector args, RTLIL::Design*) YS_OVERRIDE { if (args.size() > 2) cmd_error(args, 2, "Unexpected argument."); @@ -964,7 +909,7 @@ struct MinisatSatSolver : public SatSolver { MinisatSatSolver() : SatSolver("minisat") { yosys_satsolver = this; } - ezSAT *create() override { + ezSAT *create() YS_OVERRIDE { return new ezMiniSAT(); } } MinisatSatSolver; diff --git a/kernel/register.h b/kernel/register.h index 5cd8490824b..85d552f0dc8 100644 --- a/kernel/register.h +++ b/kernel/register.h @@ -36,11 +36,6 @@ struct Pass int call_counter; int64_t runtime_ns; - bool experimental_flag = false; - - void experimental() { - experimental_flag = true; - } struct pre_post_exec_state_t { Pass *parent_pass; @@ -67,9 +62,6 @@ struct Pass virtual void run_register(); static void init_register(); static void done_register(); - - virtual void on_register(); - virtual void on_shutdown(); }; struct ScriptPass : Pass @@ -84,7 +76,6 @@ struct ScriptPass : Pass bool check_label(std::string label, std::string info = std::string()); void run(std::string command, std::string info = std::string()); - void run_nocheck(std::string command, std::string info = std::string()); void run_script(RTLIL::Design *design, std::string run_from = std::string(), std::string run_to = std::string()); void help_script(); }; @@ -97,9 +88,9 @@ struct Frontend : Pass std::string frontend_name; Frontend(std::string name, std::string short_help = "** document me **"); - void run_register() override; - ~Frontend() override; - void execute(std::vector args, RTLIL::Design *design) override final; + void run_register() YS_OVERRIDE; + ~Frontend() YS_OVERRIDE; + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL; virtual void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) = 0; static std::vector next_args; @@ -113,9 +104,9 @@ struct Backend : Pass { std::string backend_name; Backend(std::string name, std::string short_help = "** document me **"); - void run_register() override; - ~Backend() override; - void execute(std::vector args, RTLIL::Design *design) override final; + void run_register() YS_OVERRIDE; + ~Backend() YS_OVERRIDE; + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL; virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) = 0; void extra_args(std::ostream *&f, std::string &filename, std::vector args, size_t argidx, bool bin_output = false); @@ -125,7 +116,7 @@ struct Backend : Pass }; // implemented in passes/cmds/select.cc -extern void handle_extra_select_args(Pass *pass, const std::vector &args, size_t argidx, size_t args_size, RTLIL::Design *design); +extern void handle_extra_select_args(Pass *pass, std::vector args, size_t argidx, size_t args_size, RTLIL::Design *design); extern RTLIL::Selection eval_select_args(const vector &args, RTLIL::Design *design); extern void eval_select_op(vector &work, const string &op, RTLIL::Design *design); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d7d2269422b..7c73f94c8a1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -21,7 +21,6 @@ #include "kernel/macc.h" #include "kernel/celltypes.h" #include "frontends/verilog/verilog_frontend.h" -#include "frontends/verilog/preproc.h" #include "backends/ilang/ilang_backend.h" #include @@ -41,148 +40,12 @@ int RTLIL::IdString::last_created_idx_[8]; int RTLIL::IdString::last_created_idx_ptr_; #endif -#define X(_id) IdString RTLIL::ID::_id; -#include "kernel/constids.inc" -#undef X - -dict RTLIL::constpad; - -const pool &RTLIL::builtin_ff_cell_types() { - static const pool res = { - ID($sr), - ID($ff), - ID($dff), - ID($dffe), - ID($dffsr), - ID($dffsre), - ID($adff), - ID($adffe), - ID($sdff), - ID($sdffe), - ID($sdffce), - ID($dlatch), - ID($adlatch), - ID($dlatchsr), - ID($_DFFE_NN_), - ID($_DFFE_NP_), - ID($_DFFE_PN_), - ID($_DFFE_PP_), - ID($_DFFSR_NNN_), - ID($_DFFSR_NNP_), - ID($_DFFSR_NPN_), - ID($_DFFSR_NPP_), - ID($_DFFSR_PNN_), - ID($_DFFSR_PNP_), - ID($_DFFSR_PPN_), - ID($_DFFSR_PPP_), - ID($_DFFSRE_NNNN_), - ID($_DFFSRE_NNNP_), - ID($_DFFSRE_NNPN_), - ID($_DFFSRE_NNPP_), - ID($_DFFSRE_NPNN_), - ID($_DFFSRE_NPNP_), - ID($_DFFSRE_NPPN_), - ID($_DFFSRE_NPPP_), - ID($_DFFSRE_PNNN_), - ID($_DFFSRE_PNNP_), - ID($_DFFSRE_PNPN_), - ID($_DFFSRE_PNPP_), - ID($_DFFSRE_PPNN_), - ID($_DFFSRE_PPNP_), - ID($_DFFSRE_PPPN_), - ID($_DFFSRE_PPPP_), - ID($_DFF_N_), - ID($_DFF_P_), - ID($_DFF_NN0_), - ID($_DFF_NN1_), - ID($_DFF_NP0_), - ID($_DFF_NP1_), - ID($_DFF_PN0_), - ID($_DFF_PN1_), - ID($_DFF_PP0_), - ID($_DFF_PP1_), - ID($_DFFE_NN0N_), - ID($_DFFE_NN0P_), - ID($_DFFE_NN1N_), - ID($_DFFE_NN1P_), - ID($_DFFE_NP0N_), - ID($_DFFE_NP0P_), - ID($_DFFE_NP1N_), - ID($_DFFE_NP1P_), - ID($_DFFE_PN0N_), - ID($_DFFE_PN0P_), - ID($_DFFE_PN1N_), - ID($_DFFE_PN1P_), - ID($_DFFE_PP0N_), - ID($_DFFE_PP0P_), - ID($_DFFE_PP1N_), - ID($_DFFE_PP1P_), - ID($_SDFF_NN0_), - ID($_SDFF_NN1_), - ID($_SDFF_NP0_), - ID($_SDFF_NP1_), - ID($_SDFF_PN0_), - ID($_SDFF_PN1_), - ID($_SDFF_PP0_), - ID($_SDFF_PP1_), - ID($_SDFFE_NN0N_), - ID($_SDFFE_NN0P_), - ID($_SDFFE_NN1N_), - ID($_SDFFE_NN1P_), - ID($_SDFFE_NP0N_), - ID($_SDFFE_NP0P_), - ID($_SDFFE_NP1N_), - ID($_SDFFE_NP1P_), - ID($_SDFFE_PN0N_), - ID($_SDFFE_PN0P_), - ID($_SDFFE_PN1N_), - ID($_SDFFE_PN1P_), - ID($_SDFFE_PP0N_), - ID($_SDFFE_PP0P_), - ID($_SDFFE_PP1N_), - ID($_SDFFE_PP1P_), - ID($_SDFFCE_NN0N_), - ID($_SDFFCE_NN0P_), - ID($_SDFFCE_NN1N_), - ID($_SDFFCE_NN1P_), - ID($_SDFFCE_NP0N_), - ID($_SDFFCE_NP0P_), - ID($_SDFFCE_NP1N_), - ID($_SDFFCE_NP1P_), - ID($_SDFFCE_PN0N_), - ID($_SDFFCE_PN0P_), - ID($_SDFFCE_PN1N_), - ID($_SDFFCE_PN1P_), - ID($_SDFFCE_PP0N_), - ID($_SDFFCE_PP0P_), - ID($_SDFFCE_PP1N_), - ID($_SDFFCE_PP1P_), - ID($_SR_NN_), - ID($_SR_NP_), - ID($_SR_PN_), - ID($_SR_PP_), - ID($_DLATCH_N_), - ID($_DLATCH_P_), - ID($_DLATCH_NN0_), - ID($_DLATCH_NN1_), - ID($_DLATCH_NP0_), - ID($_DLATCH_NP1_), - ID($_DLATCH_PN0_), - ID($_DLATCH_PN1_), - ID($_DLATCH_PP0_), - ID($_DLATCH_PP1_), - ID($_DLATCHSR_NNN_), - ID($_DLATCHSR_NNP_), - ID($_DLATCHSR_NPN_), - ID($_DLATCHSR_NPP_), - ID($_DLATCHSR_PNN_), - ID($_DLATCHSR_PNP_), - ID($_DLATCHSR_PPN_), - ID($_DLATCHSR_PPP_), - ID($_FF_), - }; - return res; -} +IdString RTLIL::ID::A; +IdString RTLIL::ID::B; +IdString RTLIL::ID::Y; +IdString RTLIL::ID::keep; +IdString RTLIL::ID::whitebox; +IdString RTLIL::ID::blackbox; RTLIL::Const::Const() { @@ -220,14 +83,14 @@ RTLIL::Const::Const(RTLIL::State bit, int width) RTLIL::Const::Const(const std::vector &bits) { flags = RTLIL::CONST_FLAG_NONE; - for (const auto &b : bits) - this->bits.emplace_back(b ? State::S1 : State::S0); + for (auto b : bits) + this->bits.push_back(b ? State::S1 : State::S0); } RTLIL::Const::Const(const RTLIL::Const &c) { flags = c.flags; - for (const auto &b : c.bits) + for (auto b : c.bits) this->bits.push_back(b); } @@ -274,7 +137,6 @@ int RTLIL::Const::as_int(bool is_signed) const std::string RTLIL::Const::as_string() const { std::string ret; - ret.reserve(bits.size()); for (size_t i = bits.size(); i > 0; i--) switch (bits[i-1]) { case S0: ret += "0"; break; @@ -287,10 +149,9 @@ std::string RTLIL::Const::as_string() const return ret; } -RTLIL::Const RTLIL::Const::from_string(const std::string &str) +RTLIL::Const RTLIL::Const::from_string(std::string str) { Const c; - c.bits.reserve(str.size()); for (auto it = str.rbegin(); it != str.rend(); it++) switch (*it) { case '0': c.bits.push_back(State::S0); break; @@ -306,16 +167,17 @@ RTLIL::Const RTLIL::Const::from_string(const std::string &str) std::string RTLIL::Const::decode_string() const { std::string string; - string.reserve(GetSize(bits)/8); - for (int i = 0; i < GetSize(bits); i += 8) { + std::vector string_chars; + for (int i = 0; i < int (bits.size()); i += 8) { char ch = 0; for (int j = 0; j < 8 && i + j < int (bits.size()); j++) if (bits[i + j] == RTLIL::State::S1) ch |= 1 << j; if (ch != 0) - string.append({ch}); + string_chars.push_back(ch); } - std::reverse(string.begin(), string.end()); + for (int i = int (string_chars.size()) - 1; i >= 0; i--) + string += string_chars[i]; return string; } @@ -323,7 +185,7 @@ bool RTLIL::Const::is_fully_zero() const { cover("kernel.rtlil.const.is_fully_zero"); - for (const auto &bit : bits) + for (auto bit : bits) if (bit != RTLIL::State::S0) return false; @@ -334,7 +196,7 @@ bool RTLIL::Const::is_fully_ones() const { cover("kernel.rtlil.const.is_fully_ones"); - for (const auto &bit : bits) + for (auto bit : bits) if (bit != RTLIL::State::S1) return false; @@ -345,7 +207,7 @@ bool RTLIL::Const::is_fully_def() const { cover("kernel.rtlil.const.is_fully_def"); - for (const auto &bit : bits) + for (auto bit : bits) if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) return false; @@ -356,24 +218,22 @@ bool RTLIL::Const::is_fully_undef() const { cover("kernel.rtlil.const.is_fully_undef"); - for (const auto &bit : bits) + for (auto bit : bits) if (bit != RTLIL::State::Sx && bit != RTLIL::State::Sz) return false; return true; } -bool RTLIL::AttrObject::has_attribute(RTLIL::IdString id) const -{ - return attributes.count(id); -} - void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id, bool value) { if (value) attributes[id] = RTLIL::Const(1); - else - attributes.erase(id); + else { + const auto it = attributes.find(id); + if (it != attributes.end()) + attributes.erase(it); + } } bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const @@ -384,32 +244,15 @@ bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const return it->second.as_bool(); } -void RTLIL::AttrObject::set_string_attribute(RTLIL::IdString id, string value) -{ - if (value.empty()) - attributes.erase(id); - else - attributes[id] = value; -} - -string RTLIL::AttrObject::get_string_attribute(RTLIL::IdString id) const -{ - std::string value; - const auto it = attributes.find(id); - if (it != attributes.end()) - value = it->second.decode_string(); - return value; -} - void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool &data) { string attrval; - for (const auto &s : data) { + for (auto &s : data) { if (!attrval.empty()) attrval += "|"; attrval += s; } - set_string_attribute(id, attrval); + attributes[id] = RTLIL::Const(attrval); } void RTLIL::AttrObject::add_strpool_attribute(RTLIL::IdString id, const pool &data) @@ -424,25 +267,25 @@ pool RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const { pool data; if (attributes.count(id) != 0) - for (auto s : split_tokens(get_string_attribute(id), "|")) + for (auto s : split_tokens(attributes.at(id).decode_string(), "|")) data.insert(s); return data; } -void RTLIL::AttrObject::set_hdlname_attribute(const vector &hierarchy) +void RTLIL::AttrObject::set_src_attribute(const std::string &src) { - string attrval; - for (const auto &ident : hierarchy) { - if (!attrval.empty()) - attrval += " "; - attrval += ident; - } - set_string_attribute(ID::hdlname, attrval); + if (src.empty()) + attributes.erase(ID(src)); + else + attributes[ID(src)] = src; } -vector RTLIL::AttrObject::get_hdlname_attribute() const +std::string RTLIL::AttrObject::get_src_attribute() const { - return split_tokens(get_string_attribute(ID::hdlname), " "); + std::string src; + if (attributes.count(ID(src))) + src = attributes.at(ID(src)).decode_string(); + return src; } bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const @@ -535,7 +378,6 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) } RTLIL::Design::Design() - : verilog_defines (new define_map_t) { static unsigned int hashidx_count = 123456789; hashidx_count = mkhash_xorshift(hashidx_count); @@ -586,7 +428,7 @@ RTLIL::Module *RTLIL::Design::top_module() int module_count = 0; for (auto mod : selected_modules()) { - if (mod->get_bool_attribute(ID::top)) + if (mod->get_bool_attribute(ID(top))) return mod; module_count++; module = mod; @@ -632,33 +474,32 @@ RTLIL::Module *RTLIL::Design::addModule(RTLIL::IdString name) return module; } -void RTLIL::Design::scratchpad_unset(const std::string &varname) +void RTLIL::Design::scratchpad_unset(std::string varname) { scratchpad.erase(varname); } -void RTLIL::Design::scratchpad_set_int(const std::string &varname, int value) +void RTLIL::Design::scratchpad_set_int(std::string varname, int value) { scratchpad[varname] = stringf("%d", value); } -void RTLIL::Design::scratchpad_set_bool(const std::string &varname, bool value) +void RTLIL::Design::scratchpad_set_bool(std::string varname, bool value) { scratchpad[varname] = value ? "true" : "false"; } -void RTLIL::Design::scratchpad_set_string(const std::string &varname, std::string value) +void RTLIL::Design::scratchpad_set_string(std::string varname, std::string value) { - scratchpad[varname] = std::move(value); + scratchpad[varname] = value; } -int RTLIL::Design::scratchpad_get_int(const std::string &varname, int default_value) const +int RTLIL::Design::scratchpad_get_int(std::string varname, int default_value) const { - auto it = scratchpad.find(varname); - if (it == scratchpad.end()) + if (scratchpad.count(varname) == 0) return default_value; - const std::string &str = it->second; + std::string str = scratchpad.at(varname); if (str == "0" || str == "false") return 0; @@ -671,13 +512,12 @@ int RTLIL::Design::scratchpad_get_int(const std::string &varname, int default_va return *endptr ? default_value : parsed_value; } -bool RTLIL::Design::scratchpad_get_bool(const std::string &varname, bool default_value) const +bool RTLIL::Design::scratchpad_get_bool(std::string varname, bool default_value) const { - auto it = scratchpad.find(varname); - if (it == scratchpad.end()) + if (scratchpad.count(varname) == 0) return default_value; - const std::string &str = it->second; + std::string str = scratchpad.at(varname); if (str == "0" || str == "false") return false; @@ -688,13 +528,11 @@ bool RTLIL::Design::scratchpad_get_bool(const std::string &varname, bool default return default_value; } -std::string RTLIL::Design::scratchpad_get_string(const std::string &varname, const std::string &default_value) const +std::string RTLIL::Design::scratchpad_get_string(std::string varname, std::string default_value) const { - auto it = scratchpad.find(varname); - if (it == scratchpad.end()) + if (scratchpad.count(varname) == 0) return default_value; - - return it->second; + return scratchpad.at(varname); } void RTLIL::Design::remove(RTLIL::Module *module) @@ -708,7 +546,6 @@ void RTLIL::Design::remove(RTLIL::Module *module) } log_assert(modules_.at(module->name) == module); - log_assert(refcount_modules_ == 0); modules_.erase(module->name); delete module; } @@ -879,18 +716,16 @@ void RTLIL::Module::makeblackbox() delete it->second; processes.clear(); - connections_.clear(); - remove(delwires); set_bool_attribute(ID::blackbox); } -void RTLIL::Module::reprocess_module(RTLIL::Design *, const dict &) +void RTLIL::Module::reprocess_module(RTLIL::Design *, dict) { log_error("Cannot reprocess_module module `%s' !\n", id2cstr(name)); } -RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, const dict &, bool mayfail) +RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict, bool mayfail) { if (mayfail) return RTLIL::IdString(); @@ -898,7 +733,7 @@ RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, const dict &, const dict &, const dict &, bool mayfail) +RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict, dict, dict, bool mayfail) { if (mayfail) return RTLIL::IdString(); @@ -932,17 +767,16 @@ namespace { int param(RTLIL::IdString name) { - auto it = cell->parameters.find(name); - if (it == cell->parameters.end()) + if (cell->parameters.count(name) == 0) error(__LINE__); expected_params.insert(name); - return it->second.as_int(); + return cell->parameters.at(name).as_int(); } int param_bool(RTLIL::IdString name) { int v = param(name); - if (GetSize(cell->parameters.at(name)) > 32) + if (cell->parameters.at(name).bits.size() > 32) error(__LINE__); if (v != 0 && v != 1) error(__LINE__); @@ -960,21 +794,20 @@ namespace { void param_bits(RTLIL::IdString name, int width) { param(name); - if (GetSize(cell->parameters.at(name).bits) != width) + if (int(cell->parameters.at(name).bits.size()) != width) error(__LINE__); } void port(RTLIL::IdString name, int width) { - auto it = cell->connections_.find(name); - if (it == cell->connections_.end()) + if (!cell->hasPort(name)) error(__LINE__); - if (GetSize(it->second) != width) + if (cell->getPort(name).size() != width) error(__LINE__); expected_ports.insert(name); } - void check_expected(bool check_matched_sign = false) + void check_expected(bool check_matched_sign = true) { for (auto ¶ : cell->parameters) if (expected_params.count(para.first) == 0) @@ -983,15 +816,35 @@ namespace { if (expected_ports.count(conn.first) == 0) error(__LINE__); - if (check_matched_sign) { - log_assert(expected_params.count(ID::A_SIGNED) != 0 && expected_params.count(ID::B_SIGNED) != 0); - bool a_is_signed = cell->parameters.at(ID::A_SIGNED).as_bool(); - bool b_is_signed = cell->parameters.at(ID::B_SIGNED).as_bool(); + if (expected_params.count(ID(A_SIGNED)) != 0 && expected_params.count(ID(B_SIGNED)) && check_matched_sign) { + bool a_is_signed = param(ID(A_SIGNED)) != 0; + bool b_is_signed = param(ID(B_SIGNED)) != 0; if (a_is_signed != b_is_signed) error(__LINE__); } } + void check_gate(const char *ports) + { + if (cell->parameters.size() != 0) + error(__LINE__); + + for (const char *p = ports; *p; p++) { + char portname[3] = { '\\', *p, 0 }; + if (!cell->hasPort(portname)) + error(__LINE__); + if (cell->getPort(portname).size() != 1) + error(__LINE__); + } + + for (auto &conn : cell->connections()) { + if (conn.first.size() != 2 || conn.first[0] != '\\') + error(__LINE__); + if (strchr(ports, conn.first[1]) == NULL) + error(__LINE__); + } + } + void check() { if (!cell->type.begins_with("$") || cell->type.begins_with("$__") || cell->type.begins_with("$paramod") || cell->type.begins_with("$fmcombine") || @@ -999,424 +852,357 @@ namespace { return; if (cell->type.in(ID($not), ID($pos), ID($neg))) { - param_bool(ID::A_SIGNED); - port(ID::A, param(ID::A_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); + param_bool(ID(A_SIGNED)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); check_expected(); return; } if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor))) { - param_bool(ID::A_SIGNED); - param_bool(ID::B_SIGNED); - port(ID::A, param(ID::A_WIDTH)); - port(ID::B, param(ID::B_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); - check_expected(true); + param_bool(ID(A_SIGNED)); + param_bool(ID(B_SIGNED)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::B, param(ID(B_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); + check_expected(); return; } if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool))) { - param_bool(ID::A_SIGNED); - port(ID::A, param(ID::A_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); + param_bool(ID(A_SIGNED)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); check_expected(); return; } if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) { - param_bool(ID::A_SIGNED); - param_bool(ID::B_SIGNED, /*expected=*/false); - port(ID::A, param(ID::A_WIDTH)); - port(ID::B, param(ID::B_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); + param_bool(ID(A_SIGNED)); + param_bool(ID(B_SIGNED), /*expected=*/false); + port(ID::A, param(ID(A_WIDTH))); + port(ID::B, param(ID(B_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); check_expected(/*check_matched_sign=*/false); return; } if (cell->type.in(ID($shift), ID($shiftx))) { - param_bool(ID::A_SIGNED); - param_bool(ID::B_SIGNED); - port(ID::A, param(ID::A_WIDTH)); - port(ID::B, param(ID::B_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); + param_bool(ID(A_SIGNED)); + param_bool(ID(B_SIGNED)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::B, param(ID(B_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); check_expected(/*check_matched_sign=*/false); return; } if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt))) { - param_bool(ID::A_SIGNED); - param_bool(ID::B_SIGNED); - port(ID::A, param(ID::A_WIDTH)); - port(ID::B, param(ID::B_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); - check_expected(true); + param_bool(ID(A_SIGNED)); + param_bool(ID(B_SIGNED)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::B, param(ID(B_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); + check_expected(); return; } - if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow))) { - param_bool(ID::A_SIGNED); - param_bool(ID::B_SIGNED); - port(ID::A, param(ID::A_WIDTH)); - port(ID::B, param(ID::B_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); + if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow))) { + param_bool(ID(A_SIGNED)); + param_bool(ID(B_SIGNED)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::B, param(ID(B_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); check_expected(cell->type != ID($pow)); return; } if (cell->type == ID($fa)) { - port(ID::A, param(ID::WIDTH)); - port(ID::B, param(ID::WIDTH)); - port(ID::C, param(ID::WIDTH)); - port(ID::X, param(ID::WIDTH)); - port(ID::Y, param(ID::WIDTH)); + port(ID::A, param(ID(WIDTH))); + port(ID::B, param(ID(WIDTH))); + port(ID(C), param(ID(WIDTH))); + port(ID(X), param(ID(WIDTH))); + port(ID::Y, param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($lcu)) { - port(ID::P, param(ID::WIDTH)); - port(ID::G, param(ID::WIDTH)); - port(ID::CI, 1); - port(ID::CO, param(ID::WIDTH)); + port(ID(P), param(ID(WIDTH))); + port(ID(G), param(ID(WIDTH))); + port(ID(CI), 1); + port(ID(CO), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($alu)) { - param_bool(ID::A_SIGNED); - param_bool(ID::B_SIGNED); - port(ID::A, param(ID::A_WIDTH)); - port(ID::B, param(ID::B_WIDTH)); - port(ID::CI, 1); - port(ID::BI, 1); - port(ID::X, param(ID::Y_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); - port(ID::CO, param(ID::Y_WIDTH)); - check_expected(true); + param_bool(ID(A_SIGNED)); + param_bool(ID(B_SIGNED)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::B, param(ID(B_WIDTH))); + port(ID(CI), 1); + port(ID(BI), 1); + port(ID(X), param(ID(Y_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); + port(ID(CO), param(ID(Y_WIDTH))); + check_expected(); return; } if (cell->type == ID($macc)) { - param(ID::CONFIG); - param(ID::CONFIG_WIDTH); - port(ID::A, param(ID::A_WIDTH)); - port(ID::B, param(ID::B_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); + param(ID(CONFIG)); + param(ID(CONFIG_WIDTH)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::B, param(ID(B_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); check_expected(); Macc().from_cell(cell); return; } if (cell->type == ID($logic_not)) { - param_bool(ID::A_SIGNED); - port(ID::A, param(ID::A_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); + param_bool(ID(A_SIGNED)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); check_expected(); return; } if (cell->type.in(ID($logic_and), ID($logic_or))) { - param_bool(ID::A_SIGNED); - param_bool(ID::B_SIGNED); - port(ID::A, param(ID::A_WIDTH)); - port(ID::B, param(ID::B_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); + param_bool(ID(A_SIGNED)); + param_bool(ID(B_SIGNED)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::B, param(ID(B_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); check_expected(/*check_matched_sign=*/false); return; } if (cell->type == ID($slice)) { - param(ID::OFFSET); - port(ID::A, param(ID::A_WIDTH)); - port(ID::Y, param(ID::Y_WIDTH)); - if (param(ID::OFFSET) + param(ID::Y_WIDTH) > param(ID::A_WIDTH)) + param(ID(OFFSET)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::Y, param(ID(Y_WIDTH))); + if (param(ID(OFFSET)) + param(ID(Y_WIDTH)) > param(ID(A_WIDTH))) error(__LINE__); check_expected(); return; } if (cell->type == ID($concat)) { - port(ID::A, param(ID::A_WIDTH)); - port(ID::B, param(ID::B_WIDTH)); - port(ID::Y, param(ID::A_WIDTH) + param(ID::B_WIDTH)); + port(ID::A, param(ID(A_WIDTH))); + port(ID::B, param(ID(B_WIDTH))); + port(ID::Y, param(ID(A_WIDTH)) + param(ID(B_WIDTH))); check_expected(); return; } if (cell->type == ID($mux)) { - port(ID::A, param(ID::WIDTH)); - port(ID::B, param(ID::WIDTH)); - port(ID::S, 1); - port(ID::Y, param(ID::WIDTH)); + port(ID::A, param(ID(WIDTH))); + port(ID::B, param(ID(WIDTH))); + port(ID(S), 1); + port(ID::Y, param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($pmux)) { - port(ID::A, param(ID::WIDTH)); - port(ID::B, param(ID::WIDTH) * param(ID::S_WIDTH)); - port(ID::S, param(ID::S_WIDTH)); - port(ID::Y, param(ID::WIDTH)); + port(ID::A, param(ID(WIDTH))); + port(ID::B, param(ID(WIDTH)) * param(ID(S_WIDTH))); + port(ID(S), param(ID(S_WIDTH))); + port(ID::Y, param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($lut)) { - param(ID::LUT); - port(ID::A, param(ID::WIDTH)); + param(ID(LUT)); + port(ID::A, param(ID(WIDTH))); port(ID::Y, 1); check_expected(); return; } if (cell->type == ID($sop)) { - param(ID::DEPTH); - param(ID::TABLE); - port(ID::A, param(ID::WIDTH)); + param(ID(DEPTH)); + param(ID(TABLE)); + port(ID::A, param(ID(WIDTH))); port(ID::Y, 1); check_expected(); return; } if (cell->type == ID($sr)) { - param_bool(ID::SET_POLARITY); - param_bool(ID::CLR_POLARITY); - port(ID::SET, param(ID::WIDTH)); - port(ID::CLR, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); + param_bool(ID(SET_POLARITY)); + param_bool(ID(CLR_POLARITY)); + port(ID(SET), param(ID(WIDTH))); + port(ID(CLR), param(ID(WIDTH))); + port(ID(Q), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($ff)) { - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); + port(ID(D), param(ID(WIDTH))); + port(ID(Q), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($dff)) { - param_bool(ID::CLK_POLARITY); - port(ID::CLK, 1); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); + param_bool(ID(CLK_POLARITY)); + port(ID(CLK), 1); + port(ID(D), param(ID(WIDTH))); + port(ID(Q), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($dffe)) { - param_bool(ID::CLK_POLARITY); - param_bool(ID::EN_POLARITY); - port(ID::CLK, 1); - port(ID::EN, 1); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); + param_bool(ID(CLK_POLARITY)); + param_bool(ID(EN_POLARITY)); + port(ID(CLK), 1); + port(ID(EN), 1); + port(ID(D), param(ID(WIDTH))); + port(ID(Q), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($dffsr)) { - param_bool(ID::CLK_POLARITY); - param_bool(ID::SET_POLARITY); - param_bool(ID::CLR_POLARITY); - port(ID::CLK, 1); - port(ID::SET, param(ID::WIDTH)); - port(ID::CLR, param(ID::WIDTH)); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); - check_expected(); - return; - } - - if (cell->type == ID($dffsre)) { - param_bool(ID::CLK_POLARITY); - param_bool(ID::SET_POLARITY); - param_bool(ID::CLR_POLARITY); - param_bool(ID::EN_POLARITY); - port(ID::CLK, 1); - port(ID::EN, 1); - port(ID::SET, param(ID::WIDTH)); - port(ID::CLR, param(ID::WIDTH)); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); + param_bool(ID(CLK_POLARITY)); + param_bool(ID(SET_POLARITY)); + param_bool(ID(CLR_POLARITY)); + port(ID(CLK), 1); + port(ID(SET), param(ID(WIDTH))); + port(ID(CLR), param(ID(WIDTH))); + port(ID(D), param(ID(WIDTH))); + port(ID(Q), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($adff)) { - param_bool(ID::CLK_POLARITY); - param_bool(ID::ARST_POLARITY); - param_bits(ID::ARST_VALUE, param(ID::WIDTH)); - port(ID::CLK, 1); - port(ID::ARST, 1); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); - check_expected(); - return; - } - - if (cell->type == ID($sdff)) { - param_bool(ID::CLK_POLARITY); - param_bool(ID::SRST_POLARITY); - param_bits(ID::SRST_VALUE, param(ID::WIDTH)); - port(ID::CLK, 1); - port(ID::SRST, 1); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); - check_expected(); - return; - } - - if (cell->type.in(ID($sdffe), ID($sdffce))) { - param_bool(ID::CLK_POLARITY); - param_bool(ID::EN_POLARITY); - param_bool(ID::SRST_POLARITY); - param_bits(ID::SRST_VALUE, param(ID::WIDTH)); - port(ID::CLK, 1); - port(ID::EN, 1); - port(ID::SRST, 1); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); - check_expected(); - return; - } - - if (cell->type == ID($adffe)) { - param_bool(ID::CLK_POLARITY); - param_bool(ID::EN_POLARITY); - param_bool(ID::ARST_POLARITY); - param_bits(ID::ARST_VALUE, param(ID::WIDTH)); - port(ID::CLK, 1); - port(ID::EN, 1); - port(ID::ARST, 1); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); + param_bool(ID(CLK_POLARITY)); + param_bool(ID(ARST_POLARITY)); + param_bits(ID(ARST_VALUE), param(ID(WIDTH))); + port(ID(CLK), 1); + port(ID(ARST), 1); + port(ID(D), param(ID(WIDTH))); + port(ID(Q), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($dlatch)) { - param_bool(ID::EN_POLARITY); - port(ID::EN, 1); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); - check_expected(); - return; - } - - if (cell->type == ID($adlatch)) { - param_bool(ID::EN_POLARITY); - param_bool(ID::ARST_POLARITY); - param_bits(ID::ARST_VALUE, param(ID::WIDTH)); - port(ID::EN, 1); - port(ID::ARST, 1); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); + param_bool(ID(EN_POLARITY)); + port(ID(EN), 1); + port(ID(D), param(ID(WIDTH))); + port(ID(Q), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($dlatchsr)) { - param_bool(ID::EN_POLARITY); - param_bool(ID::SET_POLARITY); - param_bool(ID::CLR_POLARITY); - port(ID::EN, 1); - port(ID::SET, param(ID::WIDTH)); - port(ID::CLR, param(ID::WIDTH)); - port(ID::D, param(ID::WIDTH)); - port(ID::Q, param(ID::WIDTH)); + param_bool(ID(EN_POLARITY)); + param_bool(ID(SET_POLARITY)); + param_bool(ID(CLR_POLARITY)); + port(ID(EN), 1); + port(ID(SET), param(ID(WIDTH))); + port(ID(CLR), param(ID(WIDTH))); + port(ID(D), param(ID(WIDTH))); + port(ID(Q), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($fsm)) { - param(ID::NAME); - param_bool(ID::CLK_POLARITY); - param_bool(ID::ARST_POLARITY); - param(ID::STATE_BITS); - param(ID::STATE_NUM); - param(ID::STATE_NUM_LOG2); - param(ID::STATE_RST); - param_bits(ID::STATE_TABLE, param(ID::STATE_BITS) * param(ID::STATE_NUM)); - param(ID::TRANS_NUM); - param_bits(ID::TRANS_TABLE, param(ID::TRANS_NUM) * (2*param(ID::STATE_NUM_LOG2) + param(ID::CTRL_IN_WIDTH) + param(ID::CTRL_OUT_WIDTH))); - port(ID::CLK, 1); - port(ID::ARST, 1); - port(ID::CTRL_IN, param(ID::CTRL_IN_WIDTH)); - port(ID::CTRL_OUT, param(ID::CTRL_OUT_WIDTH)); + param(ID(NAME)); + param_bool(ID(CLK_POLARITY)); + param_bool(ID(ARST_POLARITY)); + param(ID(STATE_BITS)); + param(ID(STATE_NUM)); + param(ID(STATE_NUM_LOG2)); + param(ID(STATE_RST)); + param_bits(ID(STATE_TABLE), param(ID(STATE_BITS)) * param(ID(STATE_NUM))); + param(ID(TRANS_NUM)); + param_bits(ID(TRANS_TABLE), param(ID(TRANS_NUM)) * (2*param(ID(STATE_NUM_LOG2)) + param(ID(CTRL_IN_WIDTH)) + param(ID(CTRL_OUT_WIDTH)))); + port(ID(CLK), 1); + port(ID(ARST), 1); + port(ID(CTRL_IN), param(ID(CTRL_IN_WIDTH))); + port(ID(CTRL_OUT), param(ID(CTRL_OUT_WIDTH))); check_expected(); return; } if (cell->type == ID($memrd)) { - param(ID::MEMID); - param_bool(ID::CLK_ENABLE); - param_bool(ID::CLK_POLARITY); - param_bool(ID::TRANSPARENT); - port(ID::CLK, 1); - port(ID::EN, 1); - port(ID::ADDR, param(ID::ABITS)); - port(ID::DATA, param(ID::WIDTH)); + param(ID(MEMID)); + param_bool(ID(CLK_ENABLE)); + param_bool(ID(CLK_POLARITY)); + param_bool(ID(TRANSPARENT)); + port(ID(CLK), 1); + port(ID(EN), 1); + port(ID(ADDR), param(ID(ABITS))); + port(ID(DATA), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($memwr)) { - param(ID::MEMID); - param_bool(ID::CLK_ENABLE); - param_bool(ID::CLK_POLARITY); - param(ID::PRIORITY); - port(ID::CLK, 1); - port(ID::EN, param(ID::WIDTH)); - port(ID::ADDR, param(ID::ABITS)); - port(ID::DATA, param(ID::WIDTH)); + param(ID(MEMID)); + param_bool(ID(CLK_ENABLE)); + param_bool(ID(CLK_POLARITY)); + param(ID(PRIORITY)); + port(ID(CLK), 1); + port(ID(EN), param(ID(WIDTH))); + port(ID(ADDR), param(ID(ABITS))); + port(ID(DATA), param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($meminit)) { - param(ID::MEMID); - param(ID::PRIORITY); - port(ID::ADDR, param(ID::ABITS)); - port(ID::DATA, param(ID::WIDTH) * param(ID::WORDS)); + param(ID(MEMID)); + param(ID(PRIORITY)); + port(ID(ADDR), param(ID(ABITS))); + port(ID(DATA), param(ID(WIDTH)) * param(ID(WORDS))); check_expected(); return; } if (cell->type == ID($mem)) { - param(ID::MEMID); - param(ID::SIZE); - param(ID::OFFSET); - param(ID::INIT); - param_bits(ID::RD_CLK_ENABLE, max(1, param(ID::RD_PORTS))); - param_bits(ID::RD_CLK_POLARITY, max(1, param(ID::RD_PORTS))); - param_bits(ID::RD_TRANSPARENT, max(1, param(ID::RD_PORTS))); - param_bits(ID::WR_CLK_ENABLE, max(1, param(ID::WR_PORTS))); - param_bits(ID::WR_CLK_POLARITY, max(1, param(ID::WR_PORTS))); - port(ID::RD_CLK, param(ID::RD_PORTS)); - port(ID::RD_EN, param(ID::RD_PORTS)); - port(ID::RD_ADDR, param(ID::RD_PORTS) * param(ID::ABITS)); - port(ID::RD_DATA, param(ID::RD_PORTS) * param(ID::WIDTH)); - port(ID::WR_CLK, param(ID::WR_PORTS)); - port(ID::WR_EN, param(ID::WR_PORTS) * param(ID::WIDTH)); - port(ID::WR_ADDR, param(ID::WR_PORTS) * param(ID::ABITS)); - port(ID::WR_DATA, param(ID::WR_PORTS) * param(ID::WIDTH)); + param(ID(MEMID)); + param(ID(SIZE)); + param(ID(OFFSET)); + param(ID(INIT)); + param_bits(ID(RD_CLK_ENABLE), max(1, param(ID(RD_PORTS)))); + param_bits(ID(RD_CLK_POLARITY), max(1, param(ID(RD_PORTS)))); + param_bits(ID(RD_TRANSPARENT), max(1, param(ID(RD_PORTS)))); + param_bits(ID(WR_CLK_ENABLE), max(1, param(ID(WR_PORTS)))); + param_bits(ID(WR_CLK_POLARITY), max(1, param(ID(WR_PORTS)))); + port(ID(RD_CLK), param(ID(RD_PORTS))); + port(ID(RD_EN), param(ID(RD_PORTS))); + port(ID(RD_ADDR), param(ID(RD_PORTS)) * param(ID(ABITS))); + port(ID(RD_DATA), param(ID(RD_PORTS)) * param(ID(WIDTH))); + port(ID(WR_CLK), param(ID(WR_PORTS))); + port(ID(WR_EN), param(ID(WR_PORTS)) * param(ID(WIDTH))); + port(ID(WR_ADDR), param(ID(WR_PORTS)) * param(ID(ABITS))); + port(ID(WR_DATA), param(ID(WR_PORTS)) * param(ID(WIDTH))); check_expected(); return; } if (cell->type == ID($tribuf)) { - port(ID::A, param(ID::WIDTH)); - port(ID::Y, param(ID::WIDTH)); - port(ID::EN, 1); + port(ID::A, param(ID(WIDTH))); + port(ID::Y, param(ID(WIDTH))); + port(ID(EN), 1); check_expected(); return; } if (cell->type.in(ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) { port(ID::A, 1); - port(ID::EN, 1); + port(ID(EN), 1); check_expected(); return; } @@ -1428,7 +1214,7 @@ namespace { } if (cell->type.in(ID($anyconst), ID($anyseq), ID($allconst), ID($allseq))) { - port(ID::Y, param(ID::WIDTH)); + port(ID::Y, param(ID(WIDTH))); check_expected(); return; } @@ -1442,135 +1228,111 @@ namespace { } if (cell->type.in(ID($specify2), ID($specify3))) { - param_bool(ID::FULL); - param_bool(ID::SRC_DST_PEN); - param_bool(ID::SRC_DST_POL); - param(ID::T_RISE_MIN); - param(ID::T_RISE_TYP); - param(ID::T_RISE_MAX); - param(ID::T_FALL_MIN); - param(ID::T_FALL_TYP); - param(ID::T_FALL_MAX); - port(ID::EN, 1); - port(ID::SRC, param(ID::SRC_WIDTH)); - port(ID::DST, param(ID::DST_WIDTH)); + param_bool(ID(FULL)); + param_bool(ID(SRC_DST_PEN)); + param_bool(ID(SRC_DST_POL)); + param(ID(T_RISE_MIN)); + param(ID(T_RISE_TYP)); + param(ID(T_RISE_MAX)); + param(ID(T_FALL_MIN)); + param(ID(T_FALL_TYP)); + param(ID(T_FALL_MAX)); + port(ID(EN), 1); + port(ID(SRC), param(ID(SRC_WIDTH))); + port(ID(DST), param(ID(DST_WIDTH))); if (cell->type == ID($specify3)) { - param_bool(ID::EDGE_EN); - param_bool(ID::EDGE_POL); - param_bool(ID::DAT_DST_PEN); - param_bool(ID::DAT_DST_POL); - port(ID::DAT, param(ID::DST_WIDTH)); + param_bool(ID(EDGE_EN)); + param_bool(ID(EDGE_POL)); + param_bool(ID(DAT_DST_PEN)); + param_bool(ID(DAT_DST_POL)); + port(ID(DAT), param(ID(DST_WIDTH))); } check_expected(); return; } if (cell->type == ID($specrule)) { - param(ID::TYPE); - param_bool(ID::SRC_PEN); - param_bool(ID::SRC_POL); - param_bool(ID::DST_PEN); - param_bool(ID::DST_POL); - param(ID::T_LIMIT_MIN); - param(ID::T_LIMIT_TYP); - param(ID::T_LIMIT_MAX); - param(ID::T_LIMIT2_MIN); - param(ID::T_LIMIT2_TYP); - param(ID::T_LIMIT2_MAX); - port(ID::SRC_EN, 1); - port(ID::DST_EN, 1); - port(ID::SRC, param(ID::SRC_WIDTH)); - port(ID::DST, param(ID::DST_WIDTH)); + param(ID(TYPE)); + param_bool(ID(SRC_PEN)); + param_bool(ID(SRC_POL)); + param_bool(ID(DST_PEN)); + param_bool(ID(DST_POL)); + param(ID(T_LIMIT)); + param(ID(T_LIMIT2)); + port(ID(SRC_EN), 1); + port(ID(DST_EN), 1); + port(ID(SRC), param(ID(SRC_WIDTH))); + port(ID(DST), param(ID(DST_WIDTH))); check_expected(); return; } - if (cell->type == ID($_BUF_)) { port(ID::A,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_NOT_)) { port(ID::A,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_AND_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_NAND_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_OR_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_NOR_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_XOR_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_XNOR_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_ANDNOT_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_ORNOT_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_MUX_)) { port(ID::A,1); port(ID::B,1); port(ID::S,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_NMUX_)) { port(ID::A,1); port(ID::B,1); port(ID::S,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_AOI3_)) { port(ID::A,1); port(ID::B,1); port(ID::C,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_OAI3_)) { port(ID::A,1); port(ID::B,1); port(ID::C,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_AOI4_)) { port(ID::A,1); port(ID::B,1); port(ID::C,1); port(ID::D,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_OAI4_)) { port(ID::A,1); port(ID::B,1); port(ID::C,1); port(ID::D,1); port(ID::Y,1); check_expected(); return; } - - if (cell->type == ID($_TBUF_)) { port(ID::A,1); port(ID::Y,1); port(ID::E,1); check_expected(); return; } - - if (cell->type == ID($_MUX4_)) { port(ID::A,1); port(ID::B,1); port(ID::C,1); port(ID::D,1); port(ID::S,1); port(ID::T,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_MUX8_)) { port(ID::A,1); port(ID::B,1); port(ID::C,1); port(ID::D,1); port(ID::E,1); port(ID::F,1); port(ID::G,1); port(ID::H,1); port(ID::S,1); port(ID::T,1); port(ID::U,1); port(ID::Y,1); check_expected(); return; } - if (cell->type == ID($_MUX16_)) { port(ID::A,1); port(ID::B,1); port(ID::C,1); port(ID::D,1); port(ID::E,1); port(ID::F,1); port(ID::G,1); port(ID::H,1); port(ID::I,1); port(ID::J,1); port(ID::K,1); port(ID::L,1); port(ID::M,1); port(ID::N,1); port(ID::O,1); port(ID::P,1); port(ID::S,1); port(ID::T,1); port(ID::U,1); port(ID::V,1); port(ID::Y,1); check_expected(); return; } - - if (cell->type.in(ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_))) - { port(ID::S,1); port(ID::R,1); port(ID::Q,1); check_expected(); return; } - - if (cell->type == ID($_FF_)) { port(ID::D,1); port(ID::Q,1); check_expected(); return; } - - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - { port(ID::D,1); port(ID::Q,1); port(ID::C,1); check_expected(); return; } - - if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::E,1); check_expected(); return; } - - if (cell->type.in( - ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_))) - { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; } - - if (cell->type.in( - ID($_DFFE_NN0N_), ID($_DFFE_NN0P_), ID($_DFFE_NN1N_), ID($_DFFE_NN1P_), - ID($_DFFE_NP0N_), ID($_DFFE_NP0P_), ID($_DFFE_NP1N_), ID($_DFFE_NP1P_), - ID($_DFFE_PN0N_), ID($_DFFE_PN0P_), ID($_DFFE_PN1N_), ID($_DFFE_PN1P_), - ID($_DFFE_PP0N_), ID($_DFFE_PP0P_), ID($_DFFE_PP1N_), ID($_DFFE_PP1P_))) - { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); port(ID::E,1); check_expected(); return; } - - if (cell->type.in( - ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), - ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_))) - { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; } - - if (cell->type.in( - ID($_DFFSRE_NNNN_), ID($_DFFSRE_NNNP_), ID($_DFFSRE_NNPN_), ID($_DFFSRE_NNPP_), - ID($_DFFSRE_NPNN_), ID($_DFFSRE_NPNP_), ID($_DFFSRE_NPPN_), ID($_DFFSRE_NPPP_), - ID($_DFFSRE_PNNN_), ID($_DFFSRE_PNNP_), ID($_DFFSRE_PNPN_), ID($_DFFSRE_PNPP_), - ID($_DFFSRE_PPNN_), ID($_DFFSRE_PPNP_), ID($_DFFSRE_PPPN_), ID($_DFFSRE_PPPP_))) - { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::E,1); port(ID::Q,1); check_expected(); return; } - - if (cell->type.in( - ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_), - ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_))) - { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; } - - if (cell->type.in( - ID($_SDFFE_NN0N_), ID($_SDFFE_NN0P_), ID($_SDFFE_NN1N_), ID($_SDFFE_NN1P_), - ID($_SDFFE_NP0N_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1N_), ID($_SDFFE_NP1P_), - ID($_SDFFE_PN0N_), ID($_SDFFE_PN0P_), ID($_SDFFE_PN1N_), ID($_SDFFE_PN1P_), - ID($_SDFFE_PP0N_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1N_), ID($_SDFFE_PP1P_), - ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NN1P_), - ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1N_), ID($_SDFFCE_NP1P_), - ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PN1P_), - ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1N_), ID($_SDFFCE_PP1P_))) - { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); port(ID::E,1); check_expected(); return; } - - if (cell->type.in(ID($_DLATCH_N_), ID($_DLATCH_P_))) - { port(ID::E,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; } - - if (cell->type.in( - ID($_DLATCH_NN0_), ID($_DLATCH_NN1_), ID($_DLATCH_NP0_), ID($_DLATCH_NP1_), - ID($_DLATCH_PN0_), ID($_DLATCH_PN1_), ID($_DLATCH_PP0_), ID($_DLATCH_PP1_))) - { port(ID::E,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; } - - if (cell->type.in( - ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_), - ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_))) - { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; } + if (cell->type == ID($_BUF_)) { check_gate("AY"); return; } + if (cell->type == ID($_NOT_)) { check_gate("AY"); return; } + if (cell->type == ID($_AND_)) { check_gate("ABY"); return; } + if (cell->type == ID($_NAND_)) { check_gate("ABY"); return; } + if (cell->type == ID($_OR_)) { check_gate("ABY"); return; } + if (cell->type == ID($_NOR_)) { check_gate("ABY"); return; } + if (cell->type == ID($_XOR_)) { check_gate("ABY"); return; } + if (cell->type == ID($_XNOR_)) { check_gate("ABY"); return; } + if (cell->type == ID($_ANDNOT_)) { check_gate("ABY"); return; } + if (cell->type == ID($_ORNOT_)) { check_gate("ABY"); return; } + if (cell->type == ID($_MUX_)) { check_gate("ABSY"); return; } + if (cell->type == ID($_NMUX_)) { check_gate("ABSY"); return; } + if (cell->type == ID($_AOI3_)) { check_gate("ABCY"); return; } + if (cell->type == ID($_OAI3_)) { check_gate("ABCY"); return; } + if (cell->type == ID($_AOI4_)) { check_gate("ABCDY"); return; } + if (cell->type == ID($_OAI4_)) { check_gate("ABCDY"); return; } + + if (cell->type == ID($_TBUF_)) { check_gate("AYE"); return; } + + if (cell->type == ID($_MUX4_)) { check_gate("ABCDSTY"); return; } + if (cell->type == ID($_MUX8_)) { check_gate("ABCDEFGHSTUY"); return; } + if (cell->type == ID($_MUX16_)) { check_gate("ABCDEFGHIJKLMNOPSTUVY"); return; } + + if (cell->type == ID($_SR_NN_)) { check_gate("SRQ"); return; } + if (cell->type == ID($_SR_NP_)) { check_gate("SRQ"); return; } + if (cell->type == ID($_SR_PN_)) { check_gate("SRQ"); return; } + if (cell->type == ID($_SR_PP_)) { check_gate("SRQ"); return; } + + if (cell->type == ID($_FF_)) { check_gate("DQ"); return; } + if (cell->type == ID($_DFF_N_)) { check_gate("DQC"); return; } + if (cell->type == ID($_DFF_P_)) { check_gate("DQC"); return; } + + if (cell->type == ID($_DFFE_NN_)) { check_gate("DQCE"); return; } + if (cell->type == ID($_DFFE_NP_)) { check_gate("DQCE"); return; } + if (cell->type == ID($_DFFE_PN_)) { check_gate("DQCE"); return; } + if (cell->type == ID($_DFFE_PP_)) { check_gate("DQCE"); return; } + + if (cell->type == ID($_DFF_NN0_)) { check_gate("DQCR"); return; } + if (cell->type == ID($_DFF_NN1_)) { check_gate("DQCR"); return; } + if (cell->type == ID($_DFF_NP0_)) { check_gate("DQCR"); return; } + if (cell->type == ID($_DFF_NP1_)) { check_gate("DQCR"); return; } + if (cell->type == ID($_DFF_PN0_)) { check_gate("DQCR"); return; } + if (cell->type == ID($_DFF_PN1_)) { check_gate("DQCR"); return; } + if (cell->type == ID($_DFF_PP0_)) { check_gate("DQCR"); return; } + if (cell->type == ID($_DFF_PP1_)) { check_gate("DQCR"); return; } + + if (cell->type == ID($_DFFSR_NNN_)) { check_gate("CSRDQ"); return; } + if (cell->type == ID($_DFFSR_NNP_)) { check_gate("CSRDQ"); return; } + if (cell->type == ID($_DFFSR_NPN_)) { check_gate("CSRDQ"); return; } + if (cell->type == ID($_DFFSR_NPP_)) { check_gate("CSRDQ"); return; } + if (cell->type == ID($_DFFSR_PNN_)) { check_gate("CSRDQ"); return; } + if (cell->type == ID($_DFFSR_PNP_)) { check_gate("CSRDQ"); return; } + if (cell->type == ID($_DFFSR_PPN_)) { check_gate("CSRDQ"); return; } + if (cell->type == ID($_DFFSR_PPP_)) { check_gate("CSRDQ"); return; } + + if (cell->type == ID($_DLATCH_N_)) { check_gate("EDQ"); return; } + if (cell->type == ID($_DLATCH_P_)) { check_gate("EDQ"); return; } + + if (cell->type == ID($_DLATCHSR_NNN_)) { check_gate("ESRDQ"); return; } + if (cell->type == ID($_DLATCHSR_NNP_)) { check_gate("ESRDQ"); return; } + if (cell->type == ID($_DLATCHSR_NPN_)) { check_gate("ESRDQ"); return; } + if (cell->type == ID($_DLATCHSR_NPP_)) { check_gate("ESRDQ"); return; } + if (cell->type == ID($_DLATCHSR_PNN_)) { check_gate("ESRDQ"); return; } + if (cell->type == ID($_DLATCHSR_PNP_)) { check_gate("ESRDQ"); return; } + if (cell->type == ID($_DLATCHSR_PPN_)) { check_gate("ESRDQ"); return; } + if (cell->type == ID($_DLATCHSR_PPP_)) { check_gate("ESRDQ"); return; } error(__LINE__); } @@ -1582,7 +1344,7 @@ void RTLIL::Module::sort() { wires_.sort(sort_by_id_str()); cells_.sort(sort_by_id_str()); - parameter_default_values.sort(sort_by_id_str()); + avail_parameters.sort(sort_by_id_str()); memories.sort(sort_by_id_str()); processes.sort(sort_by_id_str()); for (auto &it : cells_) @@ -1701,7 +1463,6 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod) const log_assert(new_mod->refcount_cells_ == 0); new_mod->avail_parameters = avail_parameters; - new_mod->parameter_default_values = parameter_default_values; for (auto &conn : connections_) new_mod->connect(conn); @@ -1713,23 +1474,24 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod) const new_mod->addWire(it.first, it.second); for (auto &it : memories) - new_mod->addMemory(it.first, it.second); + new_mod->memories[it.first] = new RTLIL::Memory(*it.second); for (auto &it : cells_) new_mod->addCell(it.first, it.second); for (auto &it : processes) - new_mod->addProcess(it.first, it.second); + new_mod->processes[it.first] = it.second->clone(); struct RewriteSigSpecWorker { RTLIL::Module *mod; void operator()(RTLIL::SigSpec &sig) { - sig.pack(); - for (auto &c : sig.chunks_) + std::vector chunks = sig.chunks(); + for (auto &c : chunks) if (c.wire != NULL) c.wire = mod->wires_.at(c.wire->name); + sig = chunks; } }; @@ -1819,26 +1581,30 @@ void RTLIL::Module::remove(const pool &wires) const pool *wires_p; void operator()(RTLIL::SigSpec &sig) { - sig.pack(); - for (auto &c : sig.chunks_) + std::vector chunks = sig; + for (auto &c : chunks) if (c.wire != NULL && wires_p->count(c.wire)) { c.wire = module->addWire(NEW_ID, c.width); c.offset = 0; } + sig = chunks; } void operator()(RTLIL::SigSpec &lhs, RTLIL::SigSpec &rhs) { log_assert(GetSize(lhs) == GetSize(rhs)); - lhs.unpack(); - rhs.unpack(); + RTLIL::SigSpec new_lhs, new_rhs; for (int i = 0; i < GetSize(lhs); i++) { - RTLIL::SigBit &lhs_bit = lhs.bits_[i]; - RTLIL::SigBit &rhs_bit = rhs.bits_[i]; - if ((lhs_bit.wire != nullptr && wires_p->count(lhs_bit.wire)) || (rhs_bit.wire != nullptr && wires_p->count(rhs_bit.wire))) { - lhs_bit = State::Sx; - rhs_bit = State::Sx; - } + RTLIL::SigBit lhs_bit = lhs[i]; + if (lhs_bit.wire != nullptr && wires_p->count(lhs_bit.wire)) + continue; + RTLIL::SigBit rhs_bit = rhs[i]; + if (rhs_bit.wire != nullptr && wires_p->count(rhs_bit.wire)) + continue; + new_lhs.append(lhs_bit); + new_rhs.append(rhs_bit); } + lhs = new_lhs; + rhs = new_rhs; } }; @@ -2055,7 +1821,6 @@ RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, const RTLIL::Wire *oth wire->port_input = other->port_input; wire->port_output = other->port_output; wire->upto = other->upto; - wire->is_signed = other->is_signed; wire->attributes = other->attributes; return wire; } @@ -2078,38 +1843,18 @@ RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, const RTLIL::Cell *oth return cell; } -RTLIL::Memory *RTLIL::Module::addMemory(RTLIL::IdString name, const RTLIL::Memory *other) -{ - RTLIL::Memory *mem = new RTLIL::Memory; - mem->name = name; - mem->width = other->width; - mem->start_offset = other->start_offset; - mem->size = other->size; - mem->attributes = other->attributes; - memories[mem->name] = mem; - return mem; -} - -RTLIL::Process *RTLIL::Module::addProcess(RTLIL::IdString name, const RTLIL::Process *other) -{ - RTLIL::Process *proc = other->clone(); - proc->name = name; - processes[name] = proc; - return proc; -} - #define DEF_METHOD(_func, _y_size, _type) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ + RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed, const std::string &src) { \ RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::A_SIGNED] = is_signed; \ - cell->parameters[ID::A_WIDTH] = sig_a.size(); \ - cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ + cell->parameters[ID(A_SIGNED)] = is_signed; \ + cell->parameters[ID(A_WIDTH)] = sig_a.size(); \ + cell->parameters[ID(Y_WIDTH)] = sig_y.size(); \ cell->setPort(ID::A, sig_a); \ cell->setPort(ID::Y, sig_y); \ cell->set_src_attribute(src); \ return cell; \ } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed, const std::string &src) { \ + RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed, const std::string &src) { \ RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \ add ## _func(name, sig_a, sig_y, is_signed, src); \ return sig_y; \ @@ -2126,20 +1871,20 @@ DEF_METHOD(LogicNot, 1, ID($logic_not)) #undef DEF_METHOD #define DEF_METHOD(_func, _y_size, _type) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ + RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed, const std::string &src) { \ RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::A_SIGNED] = is_signed; \ - cell->parameters[ID::B_SIGNED] = is_signed; \ - cell->parameters[ID::A_WIDTH] = sig_a.size(); \ - cell->parameters[ID::B_WIDTH] = sig_b.size(); \ - cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ + cell->parameters[ID(A_SIGNED)] = is_signed; \ + cell->parameters[ID(B_SIGNED)] = is_signed; \ + cell->parameters[ID(A_WIDTH)] = sig_a.size(); \ + cell->parameters[ID(B_WIDTH)] = sig_b.size(); \ + cell->parameters[ID(Y_WIDTH)] = sig_y.size(); \ cell->setPort(ID::A, sig_a); \ cell->setPort(ID::B, sig_b); \ cell->setPort(ID::Y, sig_y); \ cell->set_src_attribute(src); \ return cell; \ } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed, const std::string &src) { \ + RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed, const std::string &src) { \ RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \ add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \ return sig_y; \ @@ -2148,6 +1893,10 @@ DEF_METHOD(And, max(sig_a.size(), sig_b.size()), ID($and)) DEF_METHOD(Or, max(sig_a.size(), sig_b.size()), ID($or)) DEF_METHOD(Xor, max(sig_a.size(), sig_b.size()), ID($xor)) DEF_METHOD(Xnor, max(sig_a.size(), sig_b.size()), ID($xnor)) +DEF_METHOD(Shl, sig_a.size(), ID($shl)) +DEF_METHOD(Shr, sig_a.size(), ID($shr)) +DEF_METHOD(Sshl, sig_a.size(), ID($sshl)) +DEF_METHOD(Sshr, sig_a.size(), ID($sshr)) DEF_METHOD(Shift, sig_a.size(), ID($shift)) DEF_METHOD(Shiftx, sig_a.size(), ID($shiftx)) DEF_METHOD(Lt, 1, ID($lt)) @@ -2163,50 +1912,23 @@ DEF_METHOD(Sub, max(sig_a.size(), sig_b.size()), ID($sub)) DEF_METHOD(Mul, max(sig_a.size(), sig_b.size()), ID($mul)) DEF_METHOD(Div, max(sig_a.size(), sig_b.size()), ID($div)) DEF_METHOD(Mod, max(sig_a.size(), sig_b.size()), ID($mod)) -DEF_METHOD(DivFloor, max(sig_a.size(), sig_b.size()), ID($divfloor)) -DEF_METHOD(ModFloor, max(sig_a.size(), sig_b.size()), ID($modfloor)) DEF_METHOD(LogicAnd, 1, ID($logic_and)) DEF_METHOD(LogicOr, 1, ID($logic_or)) #undef DEF_METHOD -#define DEF_METHOD(_func, _y_size, _type) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::A_SIGNED] = is_signed; \ - cell->parameters[ID::B_SIGNED] = false; \ - cell->parameters[ID::A_WIDTH] = sig_a.size(); \ - cell->parameters[ID::B_WIDTH] = sig_b.size(); \ - cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ - cell->setPort(ID::A, sig_a); \ - cell->setPort(ID::B, sig_b); \ - cell->setPort(ID::Y, sig_y); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed, const std::string &src) { \ - RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \ - add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \ - return sig_y; \ - } -DEF_METHOD(Shl, sig_a.size(), ID($shl)) -DEF_METHOD(Shr, sig_a.size(), ID($shr)) -DEF_METHOD(Sshl, sig_a.size(), ID($sshl)) -DEF_METHOD(Sshr, sig_a.size(), ID($sshr)) -#undef DEF_METHOD - #define DEF_METHOD(_func, _type, _pmux) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src) { \ + RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, RTLIL::SigSpec sig_y, const std::string &src) { \ RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::WIDTH] = sig_a.size(); \ - if (_pmux) cell->parameters[ID::S_WIDTH] = sig_s.size(); \ + cell->parameters[ID(WIDTH)] = sig_a.size(); \ + if (_pmux) cell->parameters[ID(S_WIDTH)] = sig_s.size(); \ cell->setPort(ID::A, sig_a); \ cell->setPort(ID::B, sig_b); \ - cell->setPort(ID::S, sig_s); \ + cell->setPort(ID(S), sig_s); \ cell->setPort(ID::Y, sig_y); \ cell->set_src_attribute(src); \ return cell; \ } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src) { \ + RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, const std::string &src) { \ RTLIL::SigSpec sig_y = addWire(NEW_ID, sig_a.size()); \ add ## _func(name, sig_a, sig_b, sig_s, sig_y, src); \ return sig_y; \ @@ -2216,20 +1938,20 @@ DEF_METHOD(Pmux, ID($pmux), 1) #undef DEF_METHOD #define DEF_METHOD_2(_func, _type, _P1, _P2) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const std::string &src) { \ + RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigBit sig1, RTLIL::SigBit sig2, const std::string &src) { \ RTLIL::Cell *cell = addCell(name, _type); \ cell->setPort("\\" #_P1, sig1); \ cell->setPort("\\" #_P2, sig2); \ cell->set_src_attribute(src); \ return cell; \ } \ - RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const std::string &src) { \ + RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, RTLIL::SigBit sig1, const std::string &src) { \ RTLIL::SigBit sig2 = addWire(NEW_ID); \ add ## _func(name, sig1, sig2, src); \ return sig2; \ } #define DEF_METHOD_3(_func, _type, _P1, _P2, _P3) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const std::string &src) { \ + RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigBit sig1, RTLIL::SigBit sig2, RTLIL::SigBit sig3, const std::string &src) { \ RTLIL::Cell *cell = addCell(name, _type); \ cell->setPort("\\" #_P1, sig1); \ cell->setPort("\\" #_P2, sig2); \ @@ -2237,13 +1959,13 @@ DEF_METHOD(Pmux, ID($pmux), 1) cell->set_src_attribute(src); \ return cell; \ } \ - RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const std::string &src) { \ + RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, RTLIL::SigBit sig1, RTLIL::SigBit sig2, const std::string &src) { \ RTLIL::SigBit sig3 = addWire(NEW_ID); \ add ## _func(name, sig1, sig2, sig3, src); \ return sig3; \ } #define DEF_METHOD_4(_func, _type, _P1, _P2, _P3, _P4) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const RTLIL::SigBit &sig4, const std::string &src) { \ + RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigBit sig1, RTLIL::SigBit sig2, RTLIL::SigBit sig3, RTLIL::SigBit sig4, const std::string &src) { \ RTLIL::Cell *cell = addCell(name, _type); \ cell->setPort("\\" #_P1, sig1); \ cell->setPort("\\" #_P2, sig2); \ @@ -2252,13 +1974,13 @@ DEF_METHOD(Pmux, ID($pmux), 1) cell->set_src_attribute(src); \ return cell; \ } \ - RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const std::string &src) { \ + RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, RTLIL::SigBit sig1, RTLIL::SigBit sig2, RTLIL::SigBit sig3, const std::string &src) { \ RTLIL::SigBit sig4 = addWire(NEW_ID); \ add ## _func(name, sig1, sig2, sig3, sig4, src); \ return sig4; \ } #define DEF_METHOD_5(_func, _type, _P1, _P2, _P3, _P4, _P5) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const RTLIL::SigBit &sig4, const RTLIL::SigBit &sig5, const std::string &src) { \ + RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigBit sig1, RTLIL::SigBit sig2, RTLIL::SigBit sig3, RTLIL::SigBit sig4, RTLIL::SigBit sig5, const std::string &src) { \ RTLIL::Cell *cell = addCell(name, _type); \ cell->setPort("\\" #_P1, sig1); \ cell->setPort("\\" #_P2, sig2); \ @@ -2268,7 +1990,7 @@ DEF_METHOD(Pmux, ID($pmux), 1) cell->set_src_attribute(src); \ return cell; \ } \ - RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const RTLIL::SigBit &sig4, const std::string &src) { \ + RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, RTLIL::SigBit sig1, RTLIL::SigBit sig2, RTLIL::SigBit sig3, RTLIL::SigBit sig4, const std::string &src) { \ RTLIL::SigBit sig5 = addWire(NEW_ID); \ add ## _func(name, sig1, sig2, sig3, sig4, sig5, src); \ return sig5; \ @@ -2294,14 +2016,14 @@ DEF_METHOD_5(Oai4Gate, ID($_OAI4_), A, B, C, D, Y) #undef DEF_METHOD_4 #undef DEF_METHOD_5 -RTLIL::Cell* RTLIL::Module::addPow(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed, bool b_signed, const std::string &src) +RTLIL::Cell* RTLIL::Module::addPow(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool a_signed, bool b_signed, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($pow)); - cell->parameters[ID::A_SIGNED] = a_signed; - cell->parameters[ID::B_SIGNED] = b_signed; - cell->parameters[ID::A_WIDTH] = sig_a.size(); - cell->parameters[ID::B_WIDTH] = sig_b.size(); - cell->parameters[ID::Y_WIDTH] = sig_y.size(); + cell->parameters[ID(A_SIGNED)] = a_signed; + cell->parameters[ID(B_SIGNED)] = b_signed; + cell->parameters[ID(A_WIDTH)] = sig_a.size(); + cell->parameters[ID(B_WIDTH)] = sig_b.size(); + cell->parameters[ID(Y_WIDTH)] = sig_y.size(); cell->setPort(ID::A, sig_a); cell->setPort(ID::B, sig_b); cell->setPort(ID::Y, sig_y); @@ -2309,23 +2031,23 @@ RTLIL::Cell* RTLIL::Module::addPow(RTLIL::IdString name, const RTLIL::SigSpec &s return cell; } -RTLIL::Cell* RTLIL::Module::addSlice(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, const std::string &src) +RTLIL::Cell* RTLIL::Module::addSlice(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const offset, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($slice)); - cell->parameters[ID::A_WIDTH] = sig_a.size(); - cell->parameters[ID::Y_WIDTH] = sig_y.size(); - cell->parameters[ID::OFFSET] = offset; + cell->parameters[ID(A_WIDTH)] = sig_a.size(); + cell->parameters[ID(Y_WIDTH)] = sig_y.size(); + cell->parameters[ID(OFFSET)] = offset; cell->setPort(ID::A, sig_a); cell->setPort(ID::Y, sig_y); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addConcat(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src) +RTLIL::Cell* RTLIL::Module::addConcat(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($concat)); - cell->parameters[ID::A_WIDTH] = sig_a.size(); - cell->parameters[ID::B_WIDTH] = sig_b.size(); + cell->parameters[ID(A_WIDTH)] = sig_a.size(); + cell->parameters[ID(B_WIDTH)] = sig_b.size(); cell->setPort(ID::A, sig_a); cell->setPort(ID::B, sig_b); cell->setPort(ID::Y, sig_y); @@ -2333,74 +2055,74 @@ RTLIL::Cell* RTLIL::Module::addConcat(RTLIL::IdString name, const RTLIL::SigSpec return cell; } -RTLIL::Cell* RTLIL::Module::addLut(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const lut, const std::string &src) +RTLIL::Cell* RTLIL::Module::addLut(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const lut, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($lut)); - cell->parameters[ID::LUT] = lut; - cell->parameters[ID::WIDTH] = sig_a.size(); + cell->parameters[ID(LUT)] = lut; + cell->parameters[ID(WIDTH)] = sig_a.size(); cell->setPort(ID::A, sig_a); cell->setPort(ID::Y, sig_y); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addTribuf(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_y, const std::string &src) +RTLIL::Cell* RTLIL::Module::addTribuf(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_y, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($tribuf)); - cell->parameters[ID::WIDTH] = sig_a.size(); + cell->parameters[ID(WIDTH)] = sig_a.size(); cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); + cell->setPort(ID(EN), sig_en); cell->setPort(ID::Y, sig_y); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addAssert(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) +RTLIL::Cell* RTLIL::Module::addAssert(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($assert)); cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); + cell->setPort(ID(EN), sig_en); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addAssume(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) +RTLIL::Cell* RTLIL::Module::addAssume(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($assume)); cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); + cell->setPort(ID(EN), sig_en); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addLive(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) +RTLIL::Cell* RTLIL::Module::addLive(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($live)); cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); + cell->setPort(ID(EN), sig_en); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addFair(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) +RTLIL::Cell* RTLIL::Module::addFair(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($fair)); cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); + cell->setPort(ID(EN), sig_en); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addCover(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) +RTLIL::Cell* RTLIL::Module::addCover(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($cover)); cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); + cell->setPort(ID(EN), sig_en); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addEquiv(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src) +RTLIL::Cell* RTLIL::Module::addEquiv(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($equiv)); cell->setPort(ID::A, sig_a); @@ -2410,384 +2132,191 @@ RTLIL::Cell* RTLIL::Module::addEquiv(RTLIL::IdString name, const RTLIL::SigSpec return cell; } -RTLIL::Cell* RTLIL::Module::addSr(RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, const RTLIL::SigSpec &sig_q, bool set_polarity, bool clr_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addSr(RTLIL::IdString name, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, RTLIL::SigSpec sig_q, bool set_polarity, bool clr_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($sr)); - cell->parameters[ID::SET_POLARITY] = set_polarity; - cell->parameters[ID::CLR_POLARITY] = clr_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::SET, sig_set); - cell->setPort(ID::CLR, sig_clr); - cell->setPort(ID::Q, sig_q); + cell->parameters[ID(SET_POLARITY)] = set_polarity; + cell->parameters[ID(CLR_POLARITY)] = clr_polarity; + cell->parameters[ID(WIDTH)] = sig_q.size(); + cell->setPort(ID(SET), sig_set); + cell->setPort(ID(CLR), sig_clr); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addFf(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src) +RTLIL::Cell* RTLIL::Module::addFf(RTLIL::IdString name, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($ff)); - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->parameters[ID(WIDTH)] = sig_q.size(); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($dff)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->parameters[ID(CLK_POLARITY)] = clk_polarity; + cell->parameters[ID(WIDTH)] = sig_q.size(); + cell->setPort(ID(CLK), sig_clk); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDffe(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool en_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($dffe)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->parameters[ID(CLK_POLARITY)] = clk_polarity; + cell->parameters[ID(EN_POLARITY)] = en_polarity; + cell->parameters[ID(WIDTH)] = sig_q.size(); + cell->setPort(ID(CLK), sig_clk); + cell->setPort(ID(EN), sig_en); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDffsr(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDffsr(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, + RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($dffsr)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::SET_POLARITY] = set_polarity; - cell->parameters[ID::CLR_POLARITY] = clr_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::SET, sig_set); - cell->setPort(ID::CLR, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addDffsre(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($dffsre)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::SET_POLARITY] = set_polarity; - cell->parameters[ID::CLR_POLARITY] = clr_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::SET, sig_set); - cell->setPort(ID::CLR, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->parameters[ID(CLK_POLARITY)] = clk_polarity; + cell->parameters[ID(SET_POLARITY)] = set_polarity; + cell->parameters[ID(CLR_POLARITY)] = clr_polarity; + cell->parameters[ID(WIDTH)] = sig_q.size(); + cell->setPort(ID(CLK), sig_clk); + cell->setPort(ID(SET), sig_set); + cell->setPort(ID(CLR), sig_clr); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addAdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, +RTLIL::Cell* RTLIL::Module::addAdff(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_arst, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, RTLIL::Const arst_value, bool clk_polarity, bool arst_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($adff)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::ARST_POLARITY] = arst_polarity; - cell->parameters[ID::ARST_VALUE] = arst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::ARST, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAdffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const arst_value, bool clk_polarity, bool en_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($adffe)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::ARST_POLARITY] = arst_polarity; - cell->parameters[ID::ARST_VALUE] = arst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::ARST, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addSdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const srst_value, bool clk_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($sdff)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::SRST_POLARITY] = srst_polarity; - cell->parameters[ID::SRST_VALUE] = srst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::SRST, sig_srst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addSdffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($sdffe)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::SRST_POLARITY] = srst_polarity; - cell->parameters[ID::SRST_VALUE] = srst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::SRST, sig_srst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addSdffce(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($sdffce)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::SRST_POLARITY] = srst_polarity; - cell->parameters[ID::SRST_VALUE] = srst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::SRST, sig_srst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->parameters[ID(CLK_POLARITY)] = clk_polarity; + cell->parameters[ID(ARST_POLARITY)] = arst_polarity; + cell->parameters[ID(ARST_VALUE)] = arst_value; + cell->parameters[ID(WIDTH)] = sig_q.size(); + cell->setPort(ID(CLK), sig_clk); + cell->setPort(ID(ARST), sig_arst); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDlatch(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDlatch(RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($dlatch)); - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAdlatch(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const arst_value, bool en_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($adlatch)); - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::ARST_POLARITY] = arst_polarity; - cell->parameters[ID::ARST_VALUE] = arst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::ARST, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->parameters[ID(EN_POLARITY)] = en_polarity; + cell->parameters[ID(WIDTH)] = sig_q.size(); + cell->setPort(ID(EN), sig_en); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDlatchsr(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDlatchsr(RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, + RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($dlatchsr)); - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::SET_POLARITY] = set_polarity; - cell->parameters[ID::CLR_POLARITY] = clr_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::SET, sig_set); - cell->setPort(ID::CLR, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addSrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - const RTLIL::SigSpec &sig_q, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_SR_%c%c_", set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N')); - cell->setPort(ID::S, sig_set); - cell->setPort(ID::R, sig_clr); - cell->setPort(ID::Q, sig_q); + cell->parameters[ID(EN_POLARITY)] = en_polarity; + cell->parameters[ID(SET_POLARITY)] = set_polarity; + cell->parameters[ID(CLR_POLARITY)] = clr_polarity; + cell->parameters[ID(WIDTH)] = sig_q.size(); + cell->setPort(ID(EN), sig_en); + cell->setPort(ID(SET), sig_set); + cell->setPort(ID(CLR), sig_clr); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addFfGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src) +RTLIL::Cell* RTLIL::Module::addFfGate(RTLIL::IdString name, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, const std::string &src) { RTLIL::Cell *cell = addCell(name, ID($_FF_)); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDffGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, stringf("$_DFF_%c_", clk_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setPort(ID(C), sig_clk); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDffeGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool en_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setPort(ID(C), sig_clk); + cell->setPort(ID(E), sig_en); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDffsrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDffsrGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, + RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, stringf("$_DFFSR_%c%c%c_", clk_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::S, sig_set); - cell->setPort(ID::R, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setPort(ID(C), sig_clk); + cell->setPort(ID(S), sig_set); + cell->setPort(ID(R), sig_clr); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDffsreGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DFFSRE_%c%c%c%c_", clk_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::S, sig_set); - cell->setPort(ID::R, sig_clr); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, +RTLIL::Cell* RTLIL::Module::addAdffGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_arst, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool arst_value, bool clk_polarity, bool arst_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, stringf("$_DFF_%c%c%c_", clk_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAdffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool arst_value, bool clk_polarity, bool en_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DFFE_%c%c%c%c_", clk_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_arst); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setPort(ID(C), sig_clk); + cell->setPort(ID(R), sig_arst); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addSdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool srst_value, bool clk_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_SDFF_%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_srst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addSdffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_SDFFE_%c%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_srst); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addSdffceGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_SDFFCE_%c%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_srst); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addDlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDlatchGate(RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, stringf("$_DLATCH_%c_", en_polarity ? 'P' : 'N')); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAdlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool arst_value, bool en_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DLATCH_%c%c%c_", en_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0')); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::R, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setPort(ID(E), sig_en); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } -RTLIL::Cell* RTLIL::Module::addDlatchsrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) +RTLIL::Cell* RTLIL::Module::addDlatchsrGate(RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, + RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) { RTLIL::Cell *cell = addCell(name, stringf("$_DLATCHSR_%c%c%c_", en_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N')); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::S, sig_set); - cell->setPort(ID::R, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setPort(ID(E), sig_en); + cell->setPort(ID(S), sig_set); + cell->setPort(ID(R), sig_clr); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->set_src_attribute(src); return cell; } @@ -2796,7 +2325,7 @@ RTLIL::SigSpec RTLIL::Module::Anyconst(RTLIL::IdString name, int width, const st { RTLIL::SigSpec sig = addWire(NEW_ID, width); Cell *cell = addCell(name, ID($anyconst)); - cell->setParam(ID::WIDTH, width); + cell->setParam(ID(WIDTH), width); cell->setPort(ID::Y, sig); cell->set_src_attribute(src); return sig; @@ -2806,7 +2335,7 @@ RTLIL::SigSpec RTLIL::Module::Anyseq(RTLIL::IdString name, int width, const std: { RTLIL::SigSpec sig = addWire(NEW_ID, width); Cell *cell = addCell(name, ID($anyseq)); - cell->setParam(ID::WIDTH, width); + cell->setParam(ID(WIDTH), width); cell->setPort(ID::Y, sig); cell->set_src_attribute(src); return sig; @@ -2816,7 +2345,7 @@ RTLIL::SigSpec RTLIL::Module::Allconst(RTLIL::IdString name, int width, const st { RTLIL::SigSpec sig = addWire(NEW_ID, width); Cell *cell = addCell(name, ID($allconst)); - cell->setParam(ID::WIDTH, width); + cell->setParam(ID(WIDTH), width); cell->setPort(ID::Y, sig); cell->set_src_attribute(src); return sig; @@ -2826,7 +2355,7 @@ RTLIL::SigSpec RTLIL::Module::Allseq(RTLIL::IdString name, int width, const std: { RTLIL::SigSpec sig = addWire(NEW_ID, width); Cell *cell = addCell(name, ID($allseq)); - cell->setParam(ID::WIDTH, width); + cell->setParam(ID(WIDTH), width); cell->setPort(ID::Y, sig); cell->set_src_attribute(src); return sig; @@ -2854,7 +2383,6 @@ RTLIL::Wire::Wire() port_input = false; port_output = false; upto = false; - is_signed = false; #ifdef WITH_PYTHON RTLIL::Wire::get_all_wires()->insert(std::pair(hashidx_, this)); @@ -2949,9 +2477,14 @@ void RTLIL::Cell::unsetPort(RTLIL::IdString portname) void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) { - auto r = connections_.insert(portname); - auto conn_it = r.first; - if (!r.second && conn_it->second == signal) + auto conn_it = connections_.find(portname); + + if (conn_it == connections_.end()) { + connections_[portname] = RTLIL::SigSpec(); + conn_it = connections_.find(portname); + log_assert(conn_it != connections_.end()); + } else + if (conn_it->second == signal) return; for (auto mon : module->monitors) @@ -2966,7 +2499,7 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) log_backtrace("-X- ", yosys_xtrace-1); } - conn_it->second = std::move(signal); + conn_it->second = signal; } const RTLIL::SigSpec &RTLIL::Cell::getPort(RTLIL::IdString portname) const @@ -3024,20 +2557,12 @@ void RTLIL::Cell::unsetParam(RTLIL::IdString paramname) void RTLIL::Cell::setParam(RTLIL::IdString paramname, RTLIL::Const value) { - parameters[paramname] = std::move(value); + parameters[paramname] = value; } const RTLIL::Const &RTLIL::Cell::getParam(RTLIL::IdString paramname) const { - const auto &it = parameters.find(paramname); - if (it != parameters.end()) - return it->second; - if (module && module->design) { - RTLIL::Module *m = module->design->module(type); - if (m) - return m->parameter_default_values.at(paramname); - } - throw std::out_of_range("Cell::getParam()"); + return parameters.at(paramname); } void RTLIL::Cell::sort() @@ -3062,25 +2587,25 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) return; if (type == ID($mux) || type == ID($pmux)) { - parameters[ID::WIDTH] = GetSize(connections_[ID::Y]); + parameters[ID(WIDTH)] = GetSize(connections_[ID::Y]); if (type == ID($pmux)) - parameters[ID::S_WIDTH] = GetSize(connections_[ID::S]); + parameters[ID(S_WIDTH)] = GetSize(connections_[ID(S)]); check(); return; } if (type == ID($lut) || type == ID($sop)) { - parameters[ID::WIDTH] = GetSize(connections_[ID::A]); + parameters[ID(WIDTH)] = GetSize(connections_[ID::A]); return; } if (type == ID($fa)) { - parameters[ID::WIDTH] = GetSize(connections_[ID::Y]); + parameters[ID(WIDTH)] = GetSize(connections_[ID::Y]); return; } if (type == ID($lcu)) { - parameters[ID::WIDTH] = GetSize(connections_[ID::CO]); + parameters[ID(WIDTH)] = GetSize(connections_[ID(CO)]); return; } @@ -3089,28 +2614,28 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) if (connections_.count(ID::A)) { if (signedness_ab) { if (set_a_signed) - parameters[ID::A_SIGNED] = true; - else if (parameters.count(ID::A_SIGNED) == 0) - parameters[ID::A_SIGNED] = false; + parameters[ID(A_SIGNED)] = true; + else if (parameters.count(ID(A_SIGNED)) == 0) + parameters[ID(A_SIGNED)] = false; } - parameters[ID::A_WIDTH] = GetSize(connections_[ID::A]); + parameters[ID(A_WIDTH)] = GetSize(connections_[ID::A]); } if (connections_.count(ID::B)) { if (signedness_ab) { if (set_b_signed) - parameters[ID::B_SIGNED] = true; - else if (parameters.count(ID::B_SIGNED) == 0) - parameters[ID::B_SIGNED] = false; + parameters[ID(B_SIGNED)] = true; + else if (parameters.count(ID(B_SIGNED)) == 0) + parameters[ID(B_SIGNED)] = false; } - parameters[ID::B_WIDTH] = GetSize(connections_[ID::B]); + parameters[ID(B_WIDTH)] = GetSize(connections_[ID::B]); } if (connections_.count(ID::Y)) - parameters[ID::Y_WIDTH] = GetSize(connections_[ID::Y]); + parameters[ID(Y_WIDTH)] = GetSize(connections_[ID::Y]); - if (connections_.count(ID::Q)) - parameters[ID::WIDTH] = GetSize(connections_[ID::Q]); + if (connections_.count(ID(Q))) + parameters[ID(WIDTH)] = GetSize(connections_[ID(Q)]); check(); } @@ -3170,7 +2695,7 @@ RTLIL::SigChunk::SigChunk(RTLIL::State bit, int width) offset = 0; } -RTLIL::SigChunk::SigChunk(const RTLIL::SigBit &bit) +RTLIL::SigChunk::SigChunk(RTLIL::SigBit bit) { wire = bit.wire; offset = 0; @@ -3181,9 +2706,12 @@ RTLIL::SigChunk::SigChunk(const RTLIL::SigBit &bit) width = 1; } -RTLIL::SigChunk::SigChunk(const RTLIL::SigChunk &sigchunk) +RTLIL::SigChunk::SigChunk(const RTLIL::SigChunk &sigchunk) : data(sigchunk.data) { - *this = sigchunk; + wire = sigchunk.wire; + data = sigchunk.data; + width = sigchunk.width; + offset = sigchunk.offset; } RTLIL::SigChunk RTLIL::SigChunk::extract(int offset, int length) const @@ -3249,21 +2777,45 @@ RTLIL::SigSpec::SigSpec(std::initializer_list parts) width_ = 0; hash_ = 0; - log_assert(parts.size() > 0); - auto ie = parts.begin(); - auto it = ie + parts.size() - 1; - while (it >= ie) - append(*it--); + std::vector parts_vec(parts.begin(), parts.end()); + for (auto it = parts_vec.rbegin(); it != parts_vec.rend(); it++) + append(*it); } -RTLIL::SigSpec &RTLIL::SigSpec::operator=(const RTLIL::SigSpec &other) +const RTLIL::SigSpec &RTLIL::SigSpec::operator=(const RTLIL::SigSpec &other) { cover("kernel.rtlil.sigspec.assign"); width_ = other.width_; hash_ = other.hash_; chunks_ = other.chunks_; - bits_ = other.bits_; + bits_.clear(); + + if (!other.bits_.empty()) + { + RTLIL::SigChunk *last = NULL; + int last_end_offset = 0; + + for (auto &bit : other.bits_) { + if (last && bit.wire == last->wire) { + if (bit.wire == NULL) { + last->data.push_back(bit.data); + last->width++; + continue; + } else if (last_end_offset == bit.offset) { + last_end_offset++; + last->width++; + continue; + } + } + chunks_.push_back(bit); + last = &chunks_.back(); + last_end_offset = bit.offset + 1; + } + + check(); + } + return *this; } @@ -3271,7 +2823,7 @@ RTLIL::SigSpec::SigSpec(const RTLIL::Const &value) { cover("kernel.rtlil.sigspec.init.const"); - chunks_.emplace_back(value); + chunks_.push_back(RTLIL::SigChunk(value)); width_ = chunks_.back().width; hash_ = 0; check(); @@ -3281,7 +2833,7 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk &chunk) { cover("kernel.rtlil.sigspec.init.chunk"); - chunks_.emplace_back(chunk); + chunks_.push_back(chunk); width_ = chunks_.back().width; hash_ = 0; check(); @@ -3291,7 +2843,7 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire) { cover("kernel.rtlil.sigspec.init.wire"); - chunks_.emplace_back(wire); + chunks_.push_back(RTLIL::SigChunk(wire)); width_ = chunks_.back().width; hash_ = 0; check(); @@ -3301,7 +2853,7 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire, int offset, int width) { cover("kernel.rtlil.sigspec.init.wire_part"); - chunks_.emplace_back(wire, offset, width); + chunks_.push_back(RTLIL::SigChunk(wire, offset, width)); width_ = chunks_.back().width; hash_ = 0; check(); @@ -3311,7 +2863,7 @@ RTLIL::SigSpec::SigSpec(const std::string &str) { cover("kernel.rtlil.sigspec.init.str"); - chunks_.emplace_back(str); + chunks_.push_back(RTLIL::SigChunk(str)); width_ = chunks_.back().width; hash_ = 0; check(); @@ -3321,7 +2873,7 @@ RTLIL::SigSpec::SigSpec(int val, int width) { cover("kernel.rtlil.sigspec.init.int"); - chunks_.emplace_back(val, width); + chunks_.push_back(RTLIL::SigChunk(val, width)); width_ = width; hash_ = 0; check(); @@ -3331,18 +2883,18 @@ RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width) { cover("kernel.rtlil.sigspec.init.state"); - chunks_.emplace_back(bit, width); + chunks_.push_back(RTLIL::SigChunk(bit, width)); width_ = width; hash_ = 0; check(); } -RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width) +RTLIL::SigSpec::SigSpec(RTLIL::SigBit bit, int width) { cover("kernel.rtlil.sigspec.init.bit"); if (bit.wire == NULL) - chunks_.emplace_back(bit.data, width); + chunks_.push_back(RTLIL::SigChunk(bit.data, width)); else for (int i = 0; i < width; i++) chunks_.push_back(bit); @@ -3351,47 +2903,47 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width) check(); } -RTLIL::SigSpec::SigSpec(const std::vector &chunks) +RTLIL::SigSpec::SigSpec(std::vector chunks) { cover("kernel.rtlil.sigspec.init.stdvec_chunks"); width_ = 0; hash_ = 0; - for (const auto &c : chunks) + for (auto &c : chunks) append(c); check(); } -RTLIL::SigSpec::SigSpec(const std::vector &bits) +RTLIL::SigSpec::SigSpec(std::vector bits) { cover("kernel.rtlil.sigspec.init.stdvec_bits"); width_ = 0; hash_ = 0; - for (const auto &bit : bits) - append(bit); + for (auto &bit : bits) + append_bit(bit); check(); } -RTLIL::SigSpec::SigSpec(const pool &bits) +RTLIL::SigSpec::SigSpec(pool bits) { cover("kernel.rtlil.sigspec.init.pool_bits"); width_ = 0; hash_ = 0; - for (const auto &bit : bits) - append(bit); + for (auto &bit : bits) + append_bit(bit); check(); } -RTLIL::SigSpec::SigSpec(const std::set &bits) +RTLIL::SigSpec::SigSpec(std::set bits) { cover("kernel.rtlil.sigspec.init.stdset_bits"); width_ = 0; hash_ = 0; - for (const auto &bit : bits) - append(bit); + for (auto &bit : bits) + append_bit(bit); check(); } @@ -3401,7 +2953,7 @@ RTLIL::SigSpec::SigSpec(bool bit) width_ = 0; hash_ = 0; - append(SigBit(bit)); + append_bit(bit); check(); } @@ -3454,7 +3006,7 @@ void RTLIL::SigSpec::unpack() const that->bits_.reserve(that->width_); for (auto &c : that->chunks_) for (int i = 0; i < c.width; i++) - that->bits_.emplace_back(c, i); + that->bits_.push_back(RTLIL::SigBit(c, i)); that->chunks_.clear(); that->hash_ = 0; @@ -3719,14 +3271,14 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLI bits_match[i].wire == pattern_chunk.wire && bits_match[i].offset >= pattern_chunk.offset && bits_match[i].offset < pattern_chunk.offset + pattern_chunk.width) - ret.append(bits_other[i]); + ret.append_bit(bits_other[i]); } else { for (int i = 0; i < width_; i++) if (bits_match[i].wire && bits_match[i].wire == pattern_chunk.wire && bits_match[i].offset >= pattern_chunk.offset && bits_match[i].offset < pattern_chunk.offset + pattern_chunk.width) - ret.append(bits_match[i]); + ret.append_bit(bits_match[i]); } } @@ -3750,11 +3302,11 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(const pool &pattern, const std::vector bits_other = other->to_sigbit_vector(); for (int i = 0; i < width_; i++) if (bits_match[i].wire && pattern.count(bits_match[i])) - ret.append(bits_other[i]); + ret.append_bit(bits_other[i]); } else { for (int i = 0; i < width_; i++) if (bits_match[i].wire && pattern.count(bits_match[i])) - ret.append(bits_match[i]); + ret.append_bit(bits_match[i]); } ret.check(); @@ -3876,7 +3428,7 @@ void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal) check(); } -void RTLIL::SigSpec::append(const RTLIL::SigBit &bit) +void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit) { if (packed()) { @@ -3949,7 +3501,7 @@ void RTLIL::SigSpec::check() const int w = 0; for (size_t i = 0; i < chunks_.size(); i++) { - const RTLIL::SigChunk &chunk = chunks_[i]; + const RTLIL::SigChunk chunk = chunks_[i]; if (chunk.wire == NULL) { if (i > 0) log_assert(chunks_[i-1].wire != NULL); @@ -4188,11 +3740,11 @@ std::string RTLIL::SigSpec::as_string() const pack(); std::string str; - str.reserve(size()); for (size_t i = chunks_.size(); i > 0; i--) { const RTLIL::SigChunk &chunk = chunks_[i-1]; if (chunk.wire != NULL) - str.append(chunk.width, '?'); + for (int j = 0; j < chunk.width; j++) + str += "?"; else str += RTLIL::Const(chunk.data).as_string(); } @@ -4239,30 +3791,24 @@ RTLIL::SigBit RTLIL::SigSpec::as_bit() const return bits_[0]; } -bool RTLIL::SigSpec::match(const char* pattern) const +bool RTLIL::SigSpec::match(std::string pattern) const { cover("kernel.rtlil.sigspec.match"); - unpack(); - log_assert(int(strlen(pattern)) == GetSize(bits_)); + pack(); + std::string str = as_string(); + log_assert(pattern.size() == str.size()); - for (auto it = bits_.rbegin(); it != bits_.rend(); it++, pattern++) { - if (*pattern == ' ') + for (size_t i = 0; i < pattern.size(); i++) { + if (pattern[i] == ' ') continue; - if (*pattern == '*') { - if (*it != State::Sz && *it != State::Sx) + if (pattern[i] == '*') { + if (str[i] != 'z' && str[i] != 'x') return false; continue; } - if (*pattern == '0') { - if (*it != State::S0) - return false; - } else - if (*pattern == '1') { - if (*it != State::S1) - return false; - } else - log_abort(); + if (pattern[i] != str[i]) + return false; } return true; @@ -4286,7 +3832,6 @@ pool RTLIL::SigSpec::to_sigbit_pool() const pack(); pool sigbits; - sigbits.reserve(size()); for (auto &c : chunks_) for (int i = 0; i < c.width; i++) sigbits.insert(RTLIL::SigBit(c, i)); @@ -4327,7 +3872,6 @@ dict RTLIL::SigSpec::to_sigbit_dict(const RTLIL::S log_assert(width_ == other.width_); dict new_map; - new_map.reserve(size()); for (int i = 0; i < width_; i++) new_map[bits_[i]] = other.bits_[i]; @@ -4354,6 +3898,8 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri cover("kernel.rtlil.sigspec.parse"); AST::current_filename = "input"; + AST::use_internal_line_num(); + AST::set_line_num(0); std::vector tokens; sigspec_parse_split(tokens, str, ','); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 6c561cb855c..e5b24cc02ef 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -150,6 +150,9 @@ namespace RTLIL if (!p[0]) return 0; + log_assert(p[0] == '$' || p[0] == '\\'); + log_assert(p[1] != 0); + auto it = global_id_index_.find((char*)p); if (it != global_id_index_.end()) { #ifndef YOSYS_NO_IDS_REFCNT @@ -162,11 +165,6 @@ namespace RTLIL return it->second; } - log_assert(p[0] == '$' || p[0] == '\\'); - log_assert(p[1] != 0); - for (const char *c = p; *c; c++) - log_assert((unsigned)*c > (unsigned)' '); - #ifndef YOSYS_NO_IDS_REFCNT if (global_free_idx_list_.empty()) { if (global_id_storage_.empty()) { @@ -237,10 +235,7 @@ namespace RTLIL return; log_assert(refcount == 0); - free_reference(idx); - } - static inline void free_reference(int idx) - { + if (yosys_xtrace) { log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx); log_backtrace("-X- ", yosys_xtrace-1); @@ -298,8 +293,8 @@ namespace RTLIL // The methods below are just convenience functions for better compatibility with std::string. - bool operator==(const std::string &rhs) const { return c_str() == rhs; } - bool operator!=(const std::string &rhs) const { return c_str() != rhs; } + bool operator==(const std::string &rhs) const { return str() == rhs; } + bool operator!=(const std::string &rhs) const { return str() != rhs; } bool operator==(const char *rhs) const { return strcmp(c_str(), rhs) == 0; } bool operator!=(const char *rhs) const { return strcmp(c_str(), rhs) != 0; } @@ -363,37 +358,32 @@ namespace RTLIL // often one needs to check if a given IdString is part of a list (for example a list // of cell types). the following functions helps with that. - template - bool in(Args... args) const { - // Credit: https://articles.emptycrate.com/2016/05/14/folds_in_cpp11_ish.html - bool result = false; - (void) std::initializer_list{ (result = result || in(args), 0)... }; - return result; + template + bool in(T first, Args... rest) const { + return in(first) || in(rest...); } - bool in(const IdString &rhs) const { return *this == rhs; } + bool in(IdString rhs) const { return *this == rhs; } bool in(const char *rhs) const { return *this == rhs; } bool in(const std::string &rhs) const { return *this == rhs; } bool in(const pool &rhs) const { return rhs.count(*this) != 0; } }; namespace ID { -#define X(_id) extern IdString _id; -#include "kernel/constids.inc" -#undef X + // defined in rtlil.cc, initialized in yosys.cc + extern IdString A, B, Y; + extern IdString keep; + extern IdString whitebox; + extern IdString blackbox; }; - extern dict constpad; - - const pool &builtin_ff_cell_types(); - - static inline std::string escape_id(const std::string &str) { + static inline std::string escape_id(std::string str) { if (str.size() > 0 && str[0] != '\\' && str[0] != '$') return "\\" + str; return str; } - static inline std::string unescape_id(const std::string &str) { + static inline std::string unescape_id(std::string str) { if (str.size() < 2) return str; if (str[0] != '\\') @@ -409,7 +399,7 @@ namespace RTLIL return unescape_id(str.str()); } - static inline const char *id2cstr(RTLIL::IdString str) { + static inline const char *id2cstr(const RTLIL::IdString &str) { return log_id(str); } @@ -468,8 +458,6 @@ namespace RTLIL RTLIL::Const const_sub (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_mul (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_div (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); - RTLIL::Const const_divfloor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); - RTLIL::Const const_modfloor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_mod (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_pow (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); @@ -554,29 +542,6 @@ namespace RTLIL return *this; } - inline ObjIterator& operator+=(int amt) { - log_assert(list_p != nullptr); - it += amt; - if (it == list_p->end()) { - (*refcount_p)--; - list_p = nullptr; - refcount_p = nullptr; - } - return *this; - } - - inline ObjIterator operator+(int amt) { - log_assert(list_p != nullptr); - ObjIterator new_obj(*this); - new_obj.it += amt; - if (new_obj.it == list_p->end()) { - (*(new_obj.refcount_p))--; - new_obj.list_p = nullptr; - new_obj.refcount_p = nullptr; - } - return new_obj; - } - inline const ObjIterator operator++(int) { ObjIterator result(*this); ++(*this); @@ -639,7 +604,7 @@ struct RTLIL::Const bool as_bool() const; int as_int(bool is_signed = false) const; std::string as_string() const; - static Const from_string(const std::string &str); + static Const from_string(std::string str); std::string decode_string() const; @@ -683,8 +648,6 @@ struct RTLIL::AttrObject { dict attributes; - bool has_attribute(RTLIL::IdString id) const; - void set_bool_attribute(RTLIL::IdString id, bool value=true); bool get_bool_attribute(RTLIL::IdString id) const; @@ -692,22 +655,12 @@ struct RTLIL::AttrObject return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox)); } - void set_string_attribute(RTLIL::IdString id, string value); - string get_string_attribute(RTLIL::IdString id) const; - void set_strpool_attribute(RTLIL::IdString id, const pool &data); void add_strpool_attribute(RTLIL::IdString id, const pool &data); pool get_strpool_attribute(RTLIL::IdString id) const; - void set_src_attribute(const std::string &src) { - set_string_attribute(ID::src, src); - } - std::string get_src_attribute() const { - return get_string_attribute(ID::src); - } - - void set_hdlname_attribute(const vector &hierarchy); - vector get_hdlname_attribute() const; + void set_src_attribute(const std::string &src); + std::string get_src_attribute() const; }; struct RTLIL::SigChunk @@ -723,7 +676,7 @@ struct RTLIL::SigChunk SigChunk(const std::string &str); SigChunk(int val, int width = 32); SigChunk(RTLIL::State bit, int width = 1); - SigChunk(const RTLIL::SigBit &bit); + SigChunk(RTLIL::SigBit bit); SigChunk(const RTLIL::SigChunk &sigchunk); RTLIL::SigChunk &operator =(const RTLIL::SigChunk &other) = default; @@ -751,7 +704,7 @@ struct RTLIL::SigBit SigBit(const RTLIL::SigChunk &chunk); SigBit(const RTLIL::SigChunk &chunk, int index); SigBit(const RTLIL::SigSpec &sig); - SigBit(const RTLIL::SigBit &sigbit) = default; + SigBit(const RTLIL::SigBit &sigbit); RTLIL::SigBit &operator =(const RTLIL::SigBit &other) = default; bool operator <(const RTLIL::SigBit &other) const; @@ -803,15 +756,11 @@ struct RTLIL::SigSpec unpack(); } - // Only used by Module::remove(const pool &wires) - // but cannot be more specific as it isn't yet declared - friend struct RTLIL::Module; - public: SigSpec(); SigSpec(const RTLIL::SigSpec &other); SigSpec(std::initializer_list parts); - RTLIL::SigSpec &operator=(const RTLIL::SigSpec &other); + const RTLIL::SigSpec &operator=(const RTLIL::SigSpec &other); SigSpec(const RTLIL::Const &value); SigSpec(const RTLIL::SigChunk &chunk); @@ -820,11 +769,11 @@ struct RTLIL::SigSpec SigSpec(const std::string &str); SigSpec(int val, int width = 32); SigSpec(RTLIL::State bit, int width = 1); - SigSpec(const RTLIL::SigBit &bit, int width = 1); - SigSpec(const std::vector &chunks); - SigSpec(const std::vector &bits); - SigSpec(const pool &bits); - SigSpec(const std::set &bits); + SigSpec(RTLIL::SigBit bit, int width = 1); + SigSpec(std::vector chunks); + SigSpec(std::vector bits); + SigSpec(pool bits); + SigSpec(std::set bits); SigSpec(bool bit); SigSpec(RTLIL::SigSpec &&other) { @@ -894,20 +843,12 @@ struct RTLIL::SigSpec RTLIL::SigSpec extract_end(int offset) const { return extract(offset, width_ - offset); } void append(const RTLIL::SigSpec &signal); - inline void append(Wire *wire) { append(RTLIL::SigSpec(wire)); } - inline void append(const RTLIL::SigChunk &chunk) { append(RTLIL::SigSpec(chunk)); } - inline void append(const RTLIL::Const &const_) { append(RTLIL::SigSpec(const_)); } - - void append(const RTLIL::SigBit &bit); - inline void append(RTLIL::State state) { append(RTLIL::SigBit(state)); } - inline void append(bool bool_) { append(RTLIL::SigBit(bool_)); } + void append_bit(const RTLIL::SigBit &bit); void extend_u0(int width, bool is_signed = false); RTLIL::SigSpec repeat(int num) const; - void reverse() { inline_unpack(); std::reverse(bits_.begin(), bits_.end()); } - bool operator <(const RTLIL::SigSpec &other) const; bool operator ==(const RTLIL::SigSpec &other) const; inline bool operator !=(const RTLIL::SigSpec &other) const { return !(*this == other); } @@ -932,7 +873,7 @@ struct RTLIL::SigSpec RTLIL::SigChunk as_chunk() const; RTLIL::SigBit as_bit() const; - bool match(const char* pattern) const; + bool match(std::string pattern) const; std::set to_sigbit_set() const; pool to_sigbit_pool() const; @@ -946,7 +887,7 @@ struct RTLIL::SigSpec operator std::vector() const { return chunks(); } operator std::vector() const { return bits(); } - const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; } + RTLIL::SigBit at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; } unsigned int hash() const { if (!hash_) updhash(); return hash_; }; @@ -1001,15 +942,12 @@ struct RTLIL::Monitor virtual ~Monitor() { } virtual void notify_module_add(RTLIL::Module*) { } virtual void notify_module_del(RTLIL::Module*) { } - virtual void notify_connect(RTLIL::Cell*, const RTLIL::IdString&, const RTLIL::SigSpec&, const RTLIL::SigSpec&) { } + virtual void notify_connect(RTLIL::Cell*, const RTLIL::IdString&, const RTLIL::SigSpec&, RTLIL::SigSpec&) { } virtual void notify_connect(RTLIL::Module*, const RTLIL::SigSig&) { } virtual void notify_connect(RTLIL::Module*, const std::vector&) { } virtual void notify_blackout(RTLIL::Module*) { } }; -// Forward declaration; defined in preproc.h. -struct define_map_t; - struct RTLIL::Design { unsigned int hashidx_; @@ -1021,7 +959,7 @@ struct RTLIL::Design int refcount_modules_; dict modules_; std::vector verilog_packages, verilog_globals; - std::unique_ptr verilog_defines; + dict> verilog_defines; std::vector selection_stack; dict selection_vars; @@ -1043,15 +981,15 @@ struct RTLIL::Design void remove(RTLIL::Module *module); void rename(RTLIL::Module *module, RTLIL::IdString new_name); - void scratchpad_unset(const std::string &varname); + void scratchpad_unset(std::string varname); - void scratchpad_set_int(const std::string &varname, int value); - void scratchpad_set_bool(const std::string &varname, bool value); - void scratchpad_set_string(const std::string &varname, std::string value); + void scratchpad_set_int(std::string varname, int value); + void scratchpad_set_bool(std::string varname, bool value); + void scratchpad_set_string(std::string varname, std::string value); - int scratchpad_get_int(const std::string &varname, int default_value = 0) const; - bool scratchpad_get_bool(const std::string &varname, bool default_value = false) const; - std::string scratchpad_get_string(const std::string &varname, const std::string &default_value = std::string()) const; + int scratchpad_get_int(std::string varname, int default_value = 0) const; + bool scratchpad_get_bool(std::string varname, bool default_value = false) const; + std::string scratchpad_get_string(std::string varname, std::string default_value = std::string()) const; void sort(); void check(); @@ -1084,13 +1022,6 @@ struct RTLIL::Design return selected_member(module->name, member->name); } - template void select(T1 *module) { - if (selection_stack.size() > 0) { - RTLIL::Selection &sel = selection_stack.back(); - sel.select(module); - } - } - template void select(T1 *module, T2 *member) { if (selection_stack.size() > 0) { RTLIL::Selection &sel = selection_stack.back(); @@ -1128,17 +1059,16 @@ struct RTLIL::Module : public RTLIL::AttrObject std::vector connections_; RTLIL::IdString name; - idict avail_parameters; - dict parameter_default_values; + pool avail_parameters; dict memories; dict processes; Module(); virtual ~Module(); - virtual RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, bool mayfail = false); - virtual RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, const dict &interfaces, const dict &modports, bool mayfail = false); + virtual RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail = false); + virtual RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail = false); virtual size_t count_id(RTLIL::IdString id); - virtual void reprocess_module(RTLIL::Design *design, const dict &local_interfaces); + virtual void reprocess_module(RTLIL::Design *design, dict local_interfaces); virtual void sort(); virtual void check(); @@ -1171,14 +1101,8 @@ struct RTLIL::Module : public RTLIL::AttrObject return design->selected_member(name, member->name); } - RTLIL::Wire* wire(RTLIL::IdString id) { - auto it = wires_.find(id); - return it == wires_.end() ? nullptr : it->second; - } - RTLIL::Cell* cell(RTLIL::IdString id) { - auto it = cells_.find(id); - return it == cells_.end() ? nullptr : it->second; - } + RTLIL::Wire* wire(RTLIL::IdString id) { return wires_.count(id) ? wires_.at(id) : nullptr; } + RTLIL::Cell* cell(RTLIL::IdString id) { return cells_.count(id) ? cells_.at(id) : nullptr; } RTLIL::ObjRange wires() { return RTLIL::ObjRange(&wires_, &refcount_wires_); } RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } @@ -1203,197 +1127,168 @@ struct RTLIL::Module : public RTLIL::AttrObject RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type); RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other); - RTLIL::Memory *addMemory(RTLIL::IdString name, const RTLIL::Memory *other); - - RTLIL::Process *addProcess(RTLIL::IdString name, const RTLIL::Process *other); - // The add* methods create a cell and return the created cell. All signals must exist in advance. - RTLIL::Cell* addNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addPos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addNeg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - - RTLIL::Cell* addAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addXor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addXnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - - RTLIL::Cell* addReduceAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addReduceOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addReduceXor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addReduceXnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addReduceBool (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - - RTLIL::Cell* addShl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addShr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addSshl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addSshr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addShift (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addShiftx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - - RTLIL::Cell* addLt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addLe (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addEq (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addNe (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addEqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addNex (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addGe (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addGt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - - RTLIL::Cell* addAdd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addSub (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addMul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - // truncating division - RTLIL::Cell* addDiv (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - // truncating modulo - RTLIL::Cell* addMod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addDivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addPow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed = false, bool b_signed = false, const std::string &src = ""); - - RTLIL::Cell* addLogicNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addLogicAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - RTLIL::Cell* addLogicOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); - - RTLIL::Cell* addMux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = ""); - RTLIL::Cell* addPmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = ""); - - RTLIL::Cell* addSlice (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, const std::string &src = ""); - RTLIL::Cell* addConcat (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src = ""); - RTLIL::Cell* addLut (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const lut, const std::string &src = ""); - RTLIL::Cell* addTribuf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_y, const std::string &src = ""); - RTLIL::Cell* addAssert (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = ""); - RTLIL::Cell* addAssume (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = ""); - RTLIL::Cell* addLive (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = ""); - RTLIL::Cell* addFair (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = ""); - RTLIL::Cell* addCover (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = ""); - RTLIL::Cell* addEquiv (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src = ""); - - RTLIL::Cell* addSr (RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, const RTLIL::SigSpec &sig_q, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); - RTLIL::Cell* addFf (RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src = ""); - RTLIL::Cell* addDff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDffsr (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDffsre (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); - RTLIL::Cell* addAdff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addAdffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addSdff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool srst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addSdffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addSdffce (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDlatch (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, const std::string &src = ""); - RTLIL::Cell* addAdlatch (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool en_polarity = true, bool arst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDlatchsr (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); - - RTLIL::Cell* addBufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addNotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addAndGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addNandGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addOrGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addNorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addXorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addXnorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addAndnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addOrnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addMuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addNmuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addOai3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addAoi4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const RTLIL::SigBit &sig_y, const std::string &src = ""); - RTLIL::Cell* addOai4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const RTLIL::SigBit &sig_y, const std::string &src = ""); - - RTLIL::Cell* addSrGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - const RTLIL::SigSpec &sig_q, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); - RTLIL::Cell* addFfGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src = ""); - RTLIL::Cell* addDffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDffeGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDffsrGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDffsreGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); - RTLIL::Cell* addAdffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + RTLIL::Cell* addNot (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addPos (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addNeg (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + + RTLIL::Cell* addAnd (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addOr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addXor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addXnor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + + RTLIL::Cell* addReduceAnd (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addReduceOr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addReduceXor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addReduceXnor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addReduceBool (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + + RTLIL::Cell* addShl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addShr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addSshl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addSshr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addShift (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addShiftx (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + + RTLIL::Cell* addLt (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addLe (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addEq (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addNe (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addEqx (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addNex (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addGe (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addGt (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + + RTLIL::Cell* addAdd (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addSub (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addMul (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addDiv (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addMod (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addPow (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool a_signed = false, bool b_signed = false, const std::string &src = ""); + + RTLIL::Cell* addLogicNot (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addLogicAnd (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addLogicOr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false, const std::string &src = ""); + + RTLIL::Cell* addMux (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, RTLIL::SigSpec sig_y, const std::string &src = ""); + RTLIL::Cell* addPmux (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, RTLIL::SigSpec sig_y, const std::string &src = ""); + + RTLIL::Cell* addSlice (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const offset, const std::string &src = ""); + RTLIL::Cell* addConcat (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, const std::string &src = ""); + RTLIL::Cell* addLut (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const lut, const std::string &src = ""); + RTLIL::Cell* addTribuf (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_y, const std::string &src = ""); + RTLIL::Cell* addAssert (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src = ""); + RTLIL::Cell* addAssume (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src = ""); + RTLIL::Cell* addLive (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src = ""); + RTLIL::Cell* addFair (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src = ""); + RTLIL::Cell* addCover (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src = ""); + RTLIL::Cell* addEquiv (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, const std::string &src = ""); + + RTLIL::Cell* addSr (RTLIL::IdString name, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, RTLIL::SigSpec sig_q, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); + RTLIL::Cell* addFf (RTLIL::IdString name, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, const std::string &src = ""); + RTLIL::Cell* addDff (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDffe (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, bool en_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDffsr (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, + RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); + RTLIL::Cell* addAdff (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_arst, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, + RTLIL::Const arst_value, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDlatch (RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDlatchsr (RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, + RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); + + RTLIL::Cell* addBufGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addNotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addAndGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addNandGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addOrGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addNorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addXorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addXnorGate (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* addMuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addNmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addOai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addAoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y, const std::string &src = ""); + RTLIL::Cell* addOai4Gate (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* addFfGate (RTLIL::IdString name, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, const std::string &src = ""); + RTLIL::Cell* addDffGate (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDffeGate (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, bool en_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDffsrGate (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, + RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); + RTLIL::Cell* addAdffGate (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_arst, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool arst_value = false, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addAdffeGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool arst_value = false, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addSdffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool srst_value = false, bool clk_polarity = true, bool srst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addSdffeGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool srst_value = false, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addSdffceGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool srst_value = false, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDlatchGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, const std::string &src = ""); - RTLIL::Cell* addAdlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool arst_value = false, bool en_polarity = true, bool arst_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDlatchsrGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDlatchGate (RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDlatchsrGate (RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, + RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); // The methods without the add* prefix create a cell and an output signal. They return the newly created output signal. - RTLIL::SigSpec Not (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Pos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Bu0 (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Neg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - - RTLIL::SigSpec And (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Or (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Xor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Xnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - - RTLIL::SigSpec ReduceAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec ReduceOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec ReduceXor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec ReduceXnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec ReduceBool (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - - RTLIL::SigSpec Shl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Shr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Sshl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Sshr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Shift (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Shiftx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - - RTLIL::SigSpec Lt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Le (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Eq (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Ne (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Eqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Nex (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Ge (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Gt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - - RTLIL::SigSpec Add (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Sub (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Mul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - // truncating division - RTLIL::SigSpec Div (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - // truncating modulo - RTLIL::SigSpec Mod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec DivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec ModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec Pow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool a_signed = false, bool b_signed = false, const std::string &src = ""); - - RTLIL::SigSpec LogicNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec LogicAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - RTLIL::SigSpec LogicOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); - - RTLIL::SigSpec Mux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src = ""); - RTLIL::SigSpec Pmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src = ""); - - RTLIL::SigBit BufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const std::string &src = ""); - RTLIL::SigBit NotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const std::string &src = ""); - RTLIL::SigBit AndGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = ""); - RTLIL::SigBit NandGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = ""); - RTLIL::SigBit OrGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = ""); - RTLIL::SigBit NorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = ""); - RTLIL::SigBit XorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = ""); - RTLIL::SigBit XnorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = ""); - RTLIL::SigBit AndnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = ""); - RTLIL::SigBit OrnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = ""); - RTLIL::SigBit MuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const std::string &src = ""); - RTLIL::SigBit NmuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const std::string &src = ""); - RTLIL::SigBit Aoi3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const std::string &src = ""); - RTLIL::SigBit Oai3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const std::string &src = ""); - RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const std::string &src = ""); - RTLIL::SigBit Oai4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const std::string &src = ""); + RTLIL::SigSpec Not (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Pos (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Bu0 (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Neg (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + + RTLIL::SigSpec And (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Or (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Xor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Xnor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + + RTLIL::SigSpec ReduceAnd (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec ReduceOr (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec ReduceXor (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec ReduceXnor (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec ReduceBool (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + + RTLIL::SigSpec Shl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Shr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Sshl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Sshr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Shift (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Shiftx (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + + RTLIL::SigSpec Lt (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Le (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Eq (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Ne (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Eqx (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Nex (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Ge (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Gt (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + + RTLIL::SigSpec Add (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Sub (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Mul (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Div (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Mod (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec Pow (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool a_signed = false, bool b_signed = false, const std::string &src = ""); + + RTLIL::SigSpec LogicNot (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec LogicAnd (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec LogicOr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false, const std::string &src = ""); + + RTLIL::SigSpec Mux (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, const std::string &src = ""); + RTLIL::SigSpec Pmux (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, const std::string &src = ""); + + RTLIL::SigBit BufGate (RTLIL::IdString name, RTLIL::SigBit sig_a, const std::string &src = ""); + RTLIL::SigBit NotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, const std::string &src = ""); + RTLIL::SigBit AndGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); + RTLIL::SigBit NandGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); + RTLIL::SigBit OrGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); + RTLIL::SigBit NorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); + RTLIL::SigBit XorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); + RTLIL::SigBit XnorGate (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 MuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = ""); + RTLIL::SigBit NmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = ""); + RTLIL::SigBit Aoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = ""); + RTLIL::SigBit Oai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = ""); + RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, const std::string &src = ""); + RTLIL::SigBit Oai4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, const std::string &src = ""); RTLIL::SigSpec Anyconst (RTLIL::IdString name, int width = 1, const std::string &src = ""); RTLIL::SigSpec Anyseq (RTLIL::IdString name, int width = 1, const std::string &src = ""); @@ -1425,7 +1320,7 @@ struct RTLIL::Wire : public RTLIL::AttrObject RTLIL::Module *module; RTLIL::IdString name; int width, start_offset, port_id; - bool port_input, port_output, upto, is_signed; + bool port_input, port_output, upto; #ifdef WITH_PYTHON static std::map *get_all_wires(void); @@ -1566,6 +1461,7 @@ inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_as 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, int index) : wire(chunk.wire) { if (wire) offset = chunk.offset + index; else data = chunk.data[index]; } +inline RTLIL::SigBit::SigBit(const RTLIL::SigBit &sigbit) : wire(sigbit.wire), data(sigbit.data){if(wire) offset = sigbit.offset;} inline bool RTLIL::SigBit::operator<(const RTLIL::SigBit &other) const { if (wire == other.wire) diff --git a/kernel/satgen.h b/kernel/satgen.h index 3929a87081f..133389eee6a 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -224,8 +224,8 @@ struct SatGen void extendSignalWidth(std::vector &vec_a, std::vector &vec_b, RTLIL::Cell *cell, size_t y_width = 0, bool forced_signed = false) { bool is_signed = forced_signed; - if (!forced_signed && cell->parameters.count(ID::A_SIGNED) > 0 && cell->parameters.count(ID::B_SIGNED) > 0) - is_signed = cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool(); + if (!forced_signed && cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters.count(ID(B_SIGNED)) > 0) + is_signed = cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool(); while (vec_a.size() < vec_b.size() || vec_a.size() < y_width) vec_a.push_back(is_signed && vec_a.size() > 0 ? vec_a.back() : ez->CONST_FALSE); while (vec_b.size() < vec_a.size() || vec_b.size() < y_width) @@ -241,7 +241,7 @@ struct SatGen void extendSignalWidthUnary(std::vector &vec_a, std::vector &vec_y, RTLIL::Cell *cell, bool forced_signed = false) { - bool is_signed = forced_signed || (cell->parameters.count(ID::A_SIGNED) > 0 && cell->parameters[ID::A_SIGNED].as_bool()); + bool is_signed = forced_signed || (cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool()); while (vec_a.size() < vec_y.size()) vec_a.push_back(is_signed && vec_a.size() > 0 ? vec_a.back() : ez->CONST_FALSE); while (vec_y.size() < vec_a.size()) @@ -279,7 +279,7 @@ struct SatGen bool arith_undef_handled = false; bool is_arith_compare = cell->type.in(ID($lt), ID($le), ID($ge), ID($gt)); - if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor)) || is_arith_compare)) + if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod)) || is_arith_compare)) { std::vector undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep); std::vector undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep); @@ -293,7 +293,7 @@ struct SatGen int undef_any_b = ez->expression(ezSAT::OpOr, undef_b); int undef_y_bit = ez->OR(undef_any_a, undef_any_b); - if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) { + if (cell->type.in(ID($div), ID($mod))) { std::vector b = importSigSpec(cell->getPort(ID::B), timestep); undef_y_bit = ez->OR(undef_y_bit, ez->NOT(ez->expression(ezSAT::OpOr, b))); } @@ -397,8 +397,8 @@ struct SatGen int a = importDefSigSpec(cell->getPort(ID::A), timestep).at(0); int b = importDefSigSpec(cell->getPort(ID::B), timestep).at(0); - int c = importDefSigSpec(cell->getPort(ID::C), timestep).at(0); - int d = three_mode ? (aoi_mode ? ez->CONST_TRUE : ez->CONST_FALSE) : importDefSigSpec(cell->getPort(ID::D), timestep).at(0); + int c = importDefSigSpec(cell->getPort(ID(C)), timestep).at(0); + int d = three_mode ? (aoi_mode ? ez->CONST_TRUE : ez->CONST_FALSE) : importDefSigSpec(cell->getPort(ID(D)), timestep).at(0); int y = importDefSigSpec(cell->getPort(ID::Y), timestep).at(0); int yy = model_undef ? ez->literal() : y; @@ -411,8 +411,8 @@ struct SatGen { int undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep).at(0); int undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep).at(0); - int undef_c = importUndefSigSpec(cell->getPort(ID::C), timestep).at(0); - int undef_d = three_mode ? ez->CONST_FALSE : importUndefSigSpec(cell->getPort(ID::D), timestep).at(0); + int undef_c = importUndefSigSpec(cell->getPort(ID(C)), timestep).at(0); + int undef_d = three_mode ? ez->CONST_FALSE : importUndefSigSpec(cell->getPort(ID(D)), timestep).at(0); int undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep).at(0); if (aoi_mode) @@ -479,7 +479,7 @@ struct SatGen { std::vector a = importDefSigSpec(cell->getPort(ID::A), timestep); std::vector b = importDefSigSpec(cell->getPort(ID::B), timestep); - std::vector s = importDefSigSpec(cell->getPort(ID::S), timestep); + std::vector s = importDefSigSpec(cell->getPort(ID(S)), timestep); std::vector y = importDefSigSpec(cell->getPort(ID::Y), timestep); std::vector yy = model_undef ? ez->vec_var(y.size()) : y; @@ -492,7 +492,7 @@ struct SatGen { std::vector undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep); std::vector undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep); - std::vector undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep); + std::vector undef_s = importUndefSigSpec(cell->getPort(ID(S)), timestep); std::vector undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep); std::vector unequal_ab = ez->vec_not(ez->vec_iff(a, b)); @@ -508,7 +508,7 @@ struct SatGen { std::vector a = importDefSigSpec(cell->getPort(ID::A), timestep); std::vector b = importDefSigSpec(cell->getPort(ID::B), timestep); - std::vector s = importDefSigSpec(cell->getPort(ID::S), timestep); + std::vector s = importDefSigSpec(cell->getPort(ID(S)), timestep); std::vector y = importDefSigSpec(cell->getPort(ID::Y), timestep); std::vector yy = model_undef ? ez->vec_var(y.size()) : y; @@ -524,7 +524,7 @@ struct SatGen { std::vector undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep); std::vector undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep); - std::vector undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep); + std::vector undef_s = importUndefSigSpec(cell->getPort(ID(S)), timestep); std::vector undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep); int maybe_a = ez->CONST_TRUE; @@ -684,7 +684,7 @@ struct SatGen if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt))) { - bool is_signed = cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool(); + bool is_signed = cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool(); std::vector a = importDefSigSpec(cell->getPort(ID::A), timestep); std::vector b = importDefSigSpec(cell->getPort(ID::B), timestep); std::vector y = importDefSigSpec(cell->getPort(ID::Y), timestep); @@ -774,7 +774,7 @@ struct SatGen int extend_bit = ez->CONST_FALSE; - if (!cell->type.in(ID($shift), ID($shiftx)) && cell->parameters[ID::A_SIGNED].as_bool()) + if (!cell->type.in(ID($shift), ID($shiftx)) && cell->parameters[ID(A_SIGNED)].as_bool()) extend_bit = a.back(); while (y.size() < a.size()) @@ -792,10 +792,10 @@ struct SatGen shifted_a = ez->vec_shift_right(a, b, false, ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == ID($sshr)) - shifted_a = ez->vec_shift_right(a, b, false, cell->parameters[ID::A_SIGNED].as_bool() ? a.back() : ez->CONST_FALSE, ez->CONST_FALSE); + shifted_a = ez->vec_shift_right(a, b, false, cell->parameters[ID(A_SIGNED)].as_bool() ? a.back() : ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type.in(ID($shift), ID($shiftx))) - shifted_a = ez->vec_shift_right(a, b, cell->parameters[ID::B_SIGNED].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE); + shifted_a = ez->vec_shift_right(a, b, cell->parameters[ID(B_SIGNED)].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE); ez->assume(ez->vec_eq(shifted_a, yy)); @@ -807,7 +807,7 @@ struct SatGen std::vector undef_a_shifted; extend_bit = cell->type == ID($shiftx) ? ez->CONST_TRUE : ez->CONST_FALSE; - if (!cell->type.in(ID($shift), ID($shiftx)) && cell->parameters[ID::A_SIGNED].as_bool()) + if (!cell->type.in(ID($shift), ID($shiftx)) && cell->parameters[ID(A_SIGNED)].as_bool()) extend_bit = undef_a.back(); while (undef_y.size() < undef_a.size()) @@ -822,13 +822,13 @@ struct SatGen undef_a_shifted = ez->vec_shift_right(undef_a, b, false, ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == ID($sshr)) - undef_a_shifted = ez->vec_shift_right(undef_a, b, false, cell->parameters[ID::A_SIGNED].as_bool() ? undef_a.back() : ez->CONST_FALSE, ez->CONST_FALSE); + undef_a_shifted = ez->vec_shift_right(undef_a, b, false, cell->parameters[ID(A_SIGNED)].as_bool() ? undef_a.back() : ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == ID($shift)) - undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID::B_SIGNED].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE); + undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID(B_SIGNED)].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == ID($shiftx)) - undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID::B_SIGNED].as_bool(), ez->CONST_TRUE, ez->CONST_TRUE); + undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID(B_SIGNED)].as_bool(), ez->CONST_TRUE, ez->CONST_TRUE); int undef_any_b = ez->expression(ezSAT::OpOr, undef_b); std::vector undef_all_y_bits(undef_y.size(), undef_any_b); @@ -935,7 +935,7 @@ struct SatGen return true; } - if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) + if (cell->type.in(ID($div), ID($mod))) { std::vector a = importDefSigSpec(cell->getPort(ID::A), timestep); std::vector b = importDefSigSpec(cell->getPort(ID::B), timestep); @@ -945,7 +945,7 @@ struct SatGen std::vector yy = model_undef ? ez->vec_var(y.size()) : y; std::vector a_u, b_u; - if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) { + if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()) { a_u = ez->vec_ite(a.back(), ez->vec_neg(a), a); b_u = ez->vec_ite(b.back(), ez->vec_neg(b), b); } else { @@ -970,49 +970,24 @@ struct SatGen } std::vector y_tmp = ignore_div_by_zero ? yy : ez->vec_var(y.size()); - - // modulo calculation - std::vector modulo_trunc; - int floored_eq_trunc; - if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) { - modulo_trunc = ez->vec_ite(a.back(), ez->vec_neg(chain_buf), chain_buf); - // floor == trunc when sgn(a) == sgn(b) or trunc == 0 - floored_eq_trunc = ez->OR(ez->IFF(a.back(), b.back()), ez->NOT(ez->expression(ezSAT::OpOr, modulo_trunc))); - } else { - modulo_trunc = chain_buf; - floored_eq_trunc = ez->CONST_TRUE; - } - if (cell->type == ID($div)) { - if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) + if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()) ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(ez->XOR(a.back(), b.back()), ez->vec_neg(y_u), y_u))); else ez->assume(ez->vec_eq(y_tmp, y_u)); - } else if (cell->type == ID($mod)) { - ez->assume(ez->vec_eq(y_tmp, modulo_trunc)); - } else if (cell->type == ID($divfloor)) { - if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) - ez->assume(ez->vec_eq(y_tmp, ez->vec_ite( - ez->XOR(a.back(), b.back()), - ez->vec_neg(ez->vec_ite( - ez->vec_reduce_or(modulo_trunc), - ez->vec_add(y_u, ez->vec_const_unsigned(1, y_u.size())), - y_u - )), - y_u - ))); + } else { + if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()) + ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(a.back(), ez->vec_neg(chain_buf), chain_buf))); else - ez->assume(ez->vec_eq(y_tmp, y_u)); - } else if (cell->type == ID($modfloor)) { - ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(floored_eq_trunc, modulo_trunc, ez->vec_add(modulo_trunc, b)))); + ez->assume(ez->vec_eq(y_tmp, chain_buf)); } if (ignore_div_by_zero) { ez->assume(ez->expression(ezSAT::OpOr, b)); } else { std::vector div_zero_result; - if (cell->type.in(ID($div), ID($divfloor))) { - if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) { + if (cell->type == ID($div)) { + if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()) { std::vector all_ones(y.size(), ez->CONST_TRUE); std::vector only_first_one(y.size(), ez->CONST_FALSE); only_first_one.at(0) = ez->CONST_TRUE; @@ -1021,11 +996,10 @@ struct SatGen div_zero_result.insert(div_zero_result.end(), cell->getPort(ID::A).size(), ez->CONST_TRUE); div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE); } - } else if (cell->type.in(ID($mod), ID($modfloor))) { - // a mod 0 = a + } else { int copy_a_bits = min(cell->getPort(ID::A).size(), cell->getPort(ID::B).size()); div_zero_result.insert(div_zero_result.end(), a.begin(), a.begin() + copy_a_bits); - if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) + if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()) div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), div_zero_result.back()); else div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE); @@ -1047,7 +1021,7 @@ struct SatGen std::vector y = importDefSigSpec(cell->getPort(ID::Y), timestep); std::vector lut; - for (auto bit : cell->getParam(ID::LUT).bits) + for (auto bit : cell->getParam(ID(LUT)).bits) lut.push_back(bit == State::S1 ? ez->CONST_TRUE : ez->CONST_FALSE); while (GetSize(lut) < (1 << GetSize(a))) lut.push_back(ez->CONST_FALSE); @@ -1096,10 +1070,10 @@ struct SatGen std::vector a = importDefSigSpec(cell->getPort(ID::A), timestep); int y = importDefSigSpec(cell->getPort(ID::Y), timestep).at(0); - int width = cell->getParam(ID::WIDTH).as_int(); - int depth = cell->getParam(ID::DEPTH).as_int(); + int width = cell->getParam(ID(WIDTH)).as_int(); + int depth = cell->getParam(ID(DEPTH)).as_int(); - vector table_raw = cell->getParam(ID::TABLE).bits; + vector table_raw = cell->getParam(ID(TABLE)).bits; while (GetSize(table_raw) < 2*width*depth) table_raw.push_back(State::S0); @@ -1177,9 +1151,9 @@ struct SatGen { std::vector a = importDefSigSpec(cell->getPort(ID::A), timestep); std::vector b = importDefSigSpec(cell->getPort(ID::B), timestep); - std::vector c = importDefSigSpec(cell->getPort(ID::C), timestep); + std::vector c = importDefSigSpec(cell->getPort(ID(C)), timestep); std::vector y = importDefSigSpec(cell->getPort(ID::Y), timestep); - std::vector x = importDefSigSpec(cell->getPort(ID::X), timestep); + std::vector x = importDefSigSpec(cell->getPort(ID(X)), timestep); std::vector yy = model_undef ? ez->vec_var(y.size()) : y; std::vector xx = model_undef ? ez->vec_var(x.size()) : x; @@ -1195,10 +1169,10 @@ struct SatGen { std::vector undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep); std::vector undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep); - std::vector undef_c = importUndefSigSpec(cell->getPort(ID::C), timestep); + std::vector undef_c = importUndefSigSpec(cell->getPort(ID(C)), timestep); std::vector undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep); - std::vector undef_x = importUndefSigSpec(cell->getPort(ID::X), timestep); + std::vector undef_x = importUndefSigSpec(cell->getPort(ID(X)), timestep); ez->assume(ez->vec_eq(undef_y, ez->vec_or(ez->vec_or(undef_a, undef_b), undef_c))); ez->assume(ez->vec_eq(undef_x, undef_y)); @@ -1211,10 +1185,10 @@ struct SatGen if (cell->type == ID($lcu)) { - std::vector p = importDefSigSpec(cell->getPort(ID::P), timestep); - std::vector g = importDefSigSpec(cell->getPort(ID::G), timestep); - std::vector ci = importDefSigSpec(cell->getPort(ID::CI), timestep); - std::vector co = importDefSigSpec(cell->getPort(ID::CO), timestep); + std::vector p = importDefSigSpec(cell->getPort(ID(P)), timestep); + std::vector g = importDefSigSpec(cell->getPort(ID(G)), timestep); + std::vector ci = importDefSigSpec(cell->getPort(ID(CI)), timestep); + std::vector co = importDefSigSpec(cell->getPort(ID(CO)), timestep); std::vector yy = model_undef ? ez->vec_var(co.size()) : co; @@ -1223,10 +1197,10 @@ struct SatGen if (model_undef) { - std::vector undef_p = importUndefSigSpec(cell->getPort(ID::P), timestep); - std::vector undef_g = importUndefSigSpec(cell->getPort(ID::G), timestep); - std::vector undef_ci = importUndefSigSpec(cell->getPort(ID::CI), timestep); - std::vector undef_co = importUndefSigSpec(cell->getPort(ID::CO), timestep); + std::vector undef_p = importUndefSigSpec(cell->getPort(ID(P)), timestep); + std::vector undef_g = importUndefSigSpec(cell->getPort(ID(G)), timestep); + std::vector undef_ci = importUndefSigSpec(cell->getPort(ID(CI)), timestep); + std::vector undef_co = importUndefSigSpec(cell->getPort(ID(CO)), timestep); int undef_any_p = ez->expression(ezSAT::OpOr, undef_p); int undef_any_g = ez->expression(ezSAT::OpOr, undef_g); @@ -1246,10 +1220,10 @@ struct SatGen std::vector a = importDefSigSpec(cell->getPort(ID::A), timestep); std::vector b = importDefSigSpec(cell->getPort(ID::B), timestep); std::vector y = importDefSigSpec(cell->getPort(ID::Y), timestep); - std::vector x = importDefSigSpec(cell->getPort(ID::X), timestep); - std::vector ci = importDefSigSpec(cell->getPort(ID::CI), timestep); - std::vector bi = importDefSigSpec(cell->getPort(ID::BI), timestep); - std::vector co = importDefSigSpec(cell->getPort(ID::CO), timestep); + std::vector x = importDefSigSpec(cell->getPort(ID(X)), timestep); + std::vector ci = importDefSigSpec(cell->getPort(ID(CI)), timestep); + std::vector bi = importDefSigSpec(cell->getPort(ID(BI)), timestep); + std::vector co = importDefSigSpec(cell->getPort(ID(CO)), timestep); extendSignalWidth(a, b, y, cell); extendSignalWidth(a, b, x, cell); @@ -1276,12 +1250,12 @@ struct SatGen { std::vector undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep); std::vector undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep); - std::vector undef_ci = importUndefSigSpec(cell->getPort(ID::CI), timestep); - std::vector undef_bi = importUndefSigSpec(cell->getPort(ID::BI), timestep); + std::vector undef_ci = importUndefSigSpec(cell->getPort(ID(CI)), timestep); + std::vector undef_bi = importUndefSigSpec(cell->getPort(ID(BI)), timestep); std::vector undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep); - std::vector undef_x = importUndefSigSpec(cell->getPort(ID::X), timestep); - std::vector undef_co = importUndefSigSpec(cell->getPort(ID::CO), timestep); + std::vector undef_x = importUndefSigSpec(cell->getPort(ID(X)), timestep); + std::vector undef_co = importUndefSigSpec(cell->getPort(ID(CO)), timestep); extendSignalWidth(undef_a, undef_b, undef_y, cell); extendSignalWidth(undef_a, undef_b, undef_x, cell); @@ -1311,7 +1285,7 @@ struct SatGen { RTLIL::SigSpec a = cell->getPort(ID::A); RTLIL::SigSpec y = cell->getPort(ID::Y); - ez->assume(signals_eq(a.extract(cell->parameters.at(ID::OFFSET).as_int(), y.size()), y, timestep)); + ez->assume(signals_eq(a.extract(cell->parameters.at(ID(OFFSET)).as_int(), y.size()), y, timestep)); return true; } @@ -1332,20 +1306,20 @@ struct SatGen { if (timestep == 1) { - initial_state.add((*sigmap)(cell->getPort(ID::Q))); + initial_state.add((*sigmap)(cell->getPort(ID(Q)))); } else { - std::vector d = importDefSigSpec(cell->getPort(ID::D), timestep-1); - std::vector q = importDefSigSpec(cell->getPort(ID::Q), timestep); + std::vector d = importDefSigSpec(cell->getPort(ID(D)), timestep-1); + std::vector q = importDefSigSpec(cell->getPort(ID(Q)), timestep); std::vector qq = model_undef ? ez->vec_var(q.size()) : q; ez->assume(ez->vec_eq(d, qq)); if (model_undef) { - std::vector undef_d = importUndefSigSpec(cell->getPort(ID::D), timestep-1); - std::vector undef_q = importUndefSigSpec(cell->getPort(ID::Q), timestep); + std::vector undef_d = importUndefSigSpec(cell->getPort(ID(D)), timestep-1); + std::vector undef_q = importUndefSigSpec(cell->getPort(ID(Q)), timestep); ez->assume(ez->vec_eq(undef_d, undef_q)); undefGating(q, qq, undef_q); @@ -1423,7 +1397,7 @@ struct SatGen { std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep)); asserts_a[pf].append((*sigmap)(cell->getPort(ID::A))); - asserts_en[pf].append((*sigmap)(cell->getPort(ID::EN))); + asserts_en[pf].append((*sigmap)(cell->getPort(ID(EN)))); return true; } @@ -1431,7 +1405,7 @@ struct SatGen { std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep)); assumes_a[pf].append((*sigmap)(cell->getPort(ID::A))); - assumes_en[pf].append((*sigmap)(cell->getPort(ID::EN))); + assumes_en[pf].append((*sigmap)(cell->getPort(ID(EN)))); return true; } diff --git a/kernel/sigtools.h b/kernel/sigtools.h index c631fa481da..2517d6de33a 100644 --- a/kernel/sigtools.h +++ b/kernel/sigtools.h @@ -39,7 +39,7 @@ struct SigPool bits.clear(); } - void add(const RTLIL::SigSpec &sig) + void add(RTLIL::SigSpec sig) { for (auto &bit : sig) if (bit.wire != NULL) @@ -52,7 +52,7 @@ struct SigPool bits.insert(bit); } - void del(const RTLIL::SigSpec &sig) + void del(RTLIL::SigSpec sig) { for (auto &bit : sig) if (bit.wire != NULL) @@ -65,7 +65,7 @@ struct SigPool bits.erase(bit); } - void expand(const RTLIL::SigSpec &from, const RTLIL::SigSpec &to) + void expand(RTLIL::SigSpec from, RTLIL::SigSpec to) { log_assert(GetSize(from) == GetSize(to)); for (int i = 0; i < GetSize(from); i++) { @@ -75,16 +75,16 @@ struct SigPool } } - RTLIL::SigSpec extract(const RTLIL::SigSpec &sig) const + RTLIL::SigSpec extract(RTLIL::SigSpec sig) { RTLIL::SigSpec result; for (auto &bit : sig) if (bit.wire != NULL && bits.count(bit)) - result.append(bit); + result.append_bit(bit); return result; } - RTLIL::SigSpec remove(const RTLIL::SigSpec &sig) const + RTLIL::SigSpec remove(RTLIL::SigSpec sig) { RTLIL::SigSpec result; for (auto &bit : sig) @@ -93,12 +93,12 @@ struct SigPool return result; } - bool check(const RTLIL::SigBit &bit) const + bool check(RTLIL::SigBit bit) { return bit.wire != NULL && bits.count(bit); } - bool check_any(const RTLIL::SigSpec &sig) const + bool check_any(RTLIL::SigSpec sig) { for (auto &bit : sig) if (bit.wire != NULL && bits.count(bit)) @@ -106,7 +106,7 @@ struct SigPool return false; } - bool check_all(const RTLIL::SigSpec &sig) const + bool check_all(RTLIL::SigSpec sig) { for (auto &bit : sig) if (bit.wire != NULL && bits.count(bit) == 0) @@ -114,14 +114,14 @@ struct SigPool return true; } - RTLIL::SigSpec export_one() const + RTLIL::SigSpec export_one() { for (auto &bit : bits) return RTLIL::SigSpec(bit.first, bit.second); return RTLIL::SigSpec(); } - RTLIL::SigSpec export_all() const + RTLIL::SigSpec export_all() { pool sig; for (auto &bit : bits) @@ -153,67 +153,67 @@ struct SigSet bits.clear(); } - void insert(const RTLIL::SigSpec &sig, T data) + void insert(RTLIL::SigSpec sig, T data) { - for (const auto &bit : sig) + for (auto &bit : sig) if (bit.wire != NULL) bits[bit].insert(data); } - void insert(const RTLIL::SigSpec& sig, const std::set &data) + void insert(RTLIL::SigSpec sig, const std::set &data) { - for (const auto &bit : sig) + for (auto &bit : sig) if (bit.wire != NULL) bits[bit].insert(data.begin(), data.end()); } - void erase(const RTLIL::SigSpec& sig) + void erase(RTLIL::SigSpec sig) { - for (const auto &bit : sig) + for (auto &bit : sig) if (bit.wire != NULL) bits[bit].clear(); } - void erase(const RTLIL::SigSpec &sig, T data) + void erase(RTLIL::SigSpec sig, T data) { - for (const auto &bit : sig) + for (auto &bit : sig) if (bit.wire != NULL) bits[bit].erase(data); } - void erase(const RTLIL::SigSpec &sig, const std::set &data) + void erase(RTLIL::SigSpec sig, const std::set &data) { - for (const auto &bit : sig) + for (auto &bit : sig) if (bit.wire != NULL) bits[bit].erase(data.begin(), data.end()); } - void find(const RTLIL::SigSpec &sig, std::set &result) + void find(RTLIL::SigSpec sig, std::set &result) { - for (const auto &bit : sig) + for (auto &bit : sig) if (bit.wire != NULL) { auto &data = bits[bit]; result.insert(data.begin(), data.end()); } } - void find(const RTLIL::SigSpec &sig, pool &result) + void find(RTLIL::SigSpec sig, pool &result) { - for (const auto &bit : sig) + for (auto &bit : sig) if (bit.wire != NULL) { auto &data = bits[bit]; result.insert(data.begin(), data.end()); } } - std::set find(const RTLIL::SigSpec &sig) + std::set find(RTLIL::SigSpec sig) { std::set result; find(sig, result); return result; } - bool has(const RTLIL::SigSpec &sig) + bool has(RTLIL::SigSpec sig) { for (auto &bit : sig) if (bit.wire != NULL && bits.count(bit)) @@ -262,7 +262,7 @@ struct SigMap add(it.first, it.second); } - void add(const RTLIL::SigSpec& from, const RTLIL::SigSpec& to) + void add(RTLIL::SigSpec from, RTLIL::SigSpec to) { log_assert(GetSize(from) == GetSize(to)); @@ -287,21 +287,15 @@ struct SigMap } } - void add(const RTLIL::SigBit &bit) - { - const auto &b = database.find(bit); - if (b.wire != nullptr) - database.promote(bit); - } - - void add(const RTLIL::SigSpec &sig) + void add(RTLIL::SigSpec sig) { - for (const auto &bit : sig) - add(bit); + for (auto &bit : sig) { + RTLIL::SigBit b = database.find(bit); + if (b.wire != nullptr) + database.promote(bit); + } } - inline void add(Wire *wire) { return add(RTLIL::SigSpec(wire)); } - void apply(RTLIL::SigBit &bit) const { bit = database.find(bit); @@ -335,7 +329,7 @@ struct SigMap RTLIL::SigSpec allbits() const { RTLIL::SigSpec sig; - for (const auto &bit : database) + for (auto &bit : database) if (bit.wire != nullptr) sig.append(bit); return sig; diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h deleted file mode 100644 index d818e580b96..00000000000 --- a/kernel/timinginfo.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * (C) 2020 Eddie Hung - * - * 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. - * - */ - -#ifndef TIMINGINFO_H -#define TIMINGINFO_H - -#include "kernel/yosys.h" - -YOSYS_NAMESPACE_BEGIN - -struct TimingInfo -{ - struct NameBit - { - RTLIL::IdString name; - int offset; - NameBit() : offset(0) {} - NameBit(const RTLIL::IdString name, int offset) : name(name), offset(offset) {} - explicit NameBit(const RTLIL::SigBit &b) : name(b.wire->name), offset(b.offset) {} - bool operator==(const NameBit& nb) const { return nb.name == name && nb.offset == offset; } - bool operator!=(const NameBit& nb) const { return !operator==(nb); } - unsigned int hash() const { return mkhash_add(name.hash(), offset); } - }; - struct BitBit - { - NameBit first, second; - BitBit(const NameBit &first, const NameBit &second) : first(first), second(second) {} - BitBit(const SigBit &first, const SigBit &second) : first(first), second(second) {} - bool operator==(const BitBit& bb) const { return bb.first == first && bb.second == second; } - unsigned int hash() const { return mkhash_add(first.hash(), second.hash()); } - }; - - struct ModuleTiming - { - RTLIL::IdString type; - dict comb; - dict arrival, required; - }; - - dict data; - - TimingInfo() - { - } - - TimingInfo(RTLIL::Design *design) - { - setup(design); - } - - void setup(RTLIL::Design *design) - { - for (auto module : design->modules()) { - if (!module->get_blackbox_attribute()) - continue; - setup_module(module); - } - } - - const ModuleTiming& setup_module(RTLIL::Module *module) - { - auto r = data.insert(module->name); - log_assert(r.second); - auto &t = r.first->second; - - for (auto cell : module->cells()) { - if (cell->type == ID($specify2)) { - auto en = cell->getPort(ID::EN); - if (en.is_fully_const() && !en.as_bool()) - continue; - auto src = cell->getPort(ID::SRC); - auto dst = cell->getPort(ID::DST); - for (const auto &c : src.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dst.chunks()) - if (!c.wire->port_output) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); - int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); - int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); - int max = std::max(rise_max,fall_max); - if (max < 0) - log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell)); - if (cell->getParam(ID::FULL).as_bool()) { - for (const auto &s : src) - for (const auto &d : dst) { - auto r = t.comb.insert(BitBit(s,d)); - if (!r.second) - log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); - r.first->second = max; - } - } - else { - log_assert(GetSize(src) == GetSize(dst)); - for (auto i = 0; i < GetSize(src); i++) { - const auto &s = src[i]; - const auto &d = dst[i]; - auto r = t.comb.insert(BitBit(s,d)); - if (!r.second) - log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); - r.first->second = max; - } - } - } - else if (cell->type == ID($specify3)) { - auto src = cell->getPort(ID::SRC); - auto dst = cell->getPort(ID::DST); - for (const auto &c : src.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dst.chunks()) - if (!c.wire->port_output) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); - int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); - int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); - int max = std::max(rise_max,fall_max); - if (max < 0) { - log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); - max = 0; - } - for (const auto &d : dst) { - auto &v = t.arrival[NameBit(d)]; - v = std::max(v, max); - } - } - else if (cell->type == ID($specrule)) { - auto type = cell->getParam(ID::TYPE).decode_string(); - if (type != "$setup" && type != "$setuphold") - continue; - auto src = cell->getPort(ID::SRC); - auto dst = cell->getPort(ID::DST); - for (const auto &c : src.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dst.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); - int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); - if (max < 0) { - log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); - max = 0; - } - for (const auto &s : src) { - auto &v = t.required[NameBit(s)]; - v = std::max(v, max); - } - } - } - - return t; - } - - decltype(data)::const_iterator find(RTLIL::IdString module_name) const { return data.find(module_name); } - decltype(data)::const_iterator end() const { return data.end(); } - int count(RTLIL::IdString module_name) const { return data.count(module_name); } - const ModuleTiming& at(RTLIL::IdString module_name) const { return data.at(module_name); } -}; - -YOSYS_NAMESPACE_END - -#endif diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 7e9f320e051..5018a48883f 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -45,10 +45,8 @@ # include # include # include +# include # include -# if !defined(YOSYS_DISABLE_SPAWN) -# include -# endif #endif #if !defined(_WIN32) && defined(YOSYS_ENABLE_GLOB) @@ -131,7 +129,7 @@ void yosys_banner() log(" | |\n"); log(" | yosys -- Yosys Open SYnthesis Suite |\n"); log(" | |\n"); - log(" | Copyright (C) 2012 - 2020 Claire Wolf |\n"); + log(" | Copyright (C) 2012 - 2019 Clifford Wolf |\n"); log(" | |\n"); log(" | Permission to use, copy, modify, and/or distribute this software for any |\n"); log(" | purpose with or without fee is hereby granted, provided that the above |\n"); @@ -338,7 +336,6 @@ bool patmatch(const char *pattern, const char *string) return false; } -#if !defined(YOSYS_DISABLE_SPAWN) int run_command(const std::string &command, std::function process_line) { if (!process_line) @@ -367,16 +364,10 @@ int run_command(const std::string &command, std::function [args]\n"); @@ -730,7 +719,7 @@ struct TclPass : public Pass { log("the standard $argc and $argv variables.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *) override { + void execute(std::vector args, RTLIL::Design *) YS_OVERRIDE { if (args.size() < 2) log_cmd_error("Missing script file.\n"); @@ -815,7 +804,7 @@ std::string proc_self_dirname() path += char(shortpath[i]); return path; } -#elif defined(EMSCRIPTEN) || defined(__wasm) +#elif defined(EMSCRIPTEN) std::string proc_self_dirname() { return "/"; @@ -824,7 +813,7 @@ std::string proc_self_dirname() #error "Don't know how to determine process executable base path!" #endif -#if defined(EMSCRIPTEN) || defined(__wasm) +#ifdef EMSCRIPTEN std::string proc_share_dirname() { return "/share/"; @@ -844,7 +833,7 @@ std::string proc_share_dirname() std::string proc_share_path = proc_self_path + "share/"; if (check_file_exists(proc_share_path, true)) return proc_share_path; - proc_share_path = proc_self_path + "../share/" + proc_program_prefix()+ "yosys/"; + proc_share_path = proc_self_path + "../share/yosys/"; if (check_file_exists(proc_share_path, true)) return proc_share_path; # ifdef YOSYS_DATDIR @@ -857,15 +846,6 @@ std::string proc_share_dirname() } #endif -std::string proc_program_prefix() -{ - std::string program_prefix; -#ifdef YOSYS_PROGRAM_PREFIX - program_prefix = YOSYS_PROGRAM_PREFIX; -#endif - return program_prefix; -} - bool fgetline(FILE *f, std::string &buffer) { buffer = ""; @@ -1052,8 +1032,6 @@ void run_backend(std::string filename, std::string command, RTLIL::Design *desig command = "verilog"; else if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0) command = "ilang"; - else if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".cc") == 0) - command = "cxxrtl"; else if (filename.size() > 4 && filename.compare(filename.size()-4, std::string::npos, ".aig") == 0) command = "aiger"; else if (filename.size() > 5 && filename.compare(filename.size()-5, std::string::npos, ".blif") == 0) @@ -1115,29 +1093,30 @@ static char *readline_obj_generator(const char *text, int state) if (design->selected_active_module.empty()) { - for (auto mod : design->modules()) - if (RTLIL::unescape_id(mod->name).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(mod->name))); + for (auto &it : design->modules_) + if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) + obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); } - else if (design->module(design->selected_active_module) != nullptr) + else + if (design->modules_.count(design->selected_active_module) > 0) { - RTLIL::Module *module = design->module(design->selected_active_module); + RTLIL::Module *module = design->modules_.at(design->selected_active_module); - for (auto w : module->wires()) - if (RTLIL::unescape_id(w->name).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(w->name))); + for (auto &it : module->wires_) + if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) + obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); for (auto &it : module->memories) if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(it.first))); + obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); - for (auto cell : module->cells()) - if (RTLIL::unescape_id(cell->name).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(cell->name))); + for (auto &it : module->cells_) + if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) + obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); for (auto &it : module->processes) if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(it.first))); + obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); } std::sort(obj_names.begin(), obj_names.end()); @@ -1220,7 +1199,7 @@ void shell(RTLIL::Design *design) struct ShellPass : public Pass { ShellPass() : Pass("shell", "enter interactive command mode") { } - void help() override { + void help() YS_OVERRIDE { log("\n"); log(" shell\n"); log("\n"); @@ -1252,7 +1231,7 @@ struct ShellPass : public Pass { log("Press Ctrl-D or type 'exit' to leave the interactive shell.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override { + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { extra_args(args, 1, design, false); shell(design); } @@ -1261,7 +1240,7 @@ struct ShellPass : public Pass { #if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE) struct HistoryPass : public Pass { HistoryPass() : Pass("history", "show last interactive commands") { } - void help() override { + void help() YS_OVERRIDE { log("\n"); log(" history\n"); log("\n"); @@ -1270,7 +1249,7 @@ struct HistoryPass : public Pass { log("from executed scripts.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override { + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { extra_args(args, 1, design, false); #ifdef YOSYS_ENABLE_READLINE for(HIST_ENTRY **list = history_list(); *list != NULL; list++) @@ -1285,7 +1264,7 @@ struct HistoryPass : public Pass { struct ScriptCmdPass : public Pass { ScriptCmdPass() : Pass("script", "execute commands from file or wire") { } - void help() override { + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" script [:]\n"); @@ -1308,7 +1287,7 @@ struct ScriptCmdPass : public Pass { log("'-module' mode can be exited by using the 'cd' command.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool scriptwire = false; diff --git a/kernel/yosys.h b/kernel/yosys.h index f1646d6bc53..179bfe07ae2 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -118,10 +118,6 @@ extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *p # define isatty _isatty # define fileno _fileno # endif - -// mingw and msvc include `wingdi.h` which defines a TRANSPARENT macro -// that conflicts with X(TRANSPARENT) entry in kernel/constids.inc -# undef TRANSPARENT #endif #ifndef PATH_MAX @@ -136,30 +132,23 @@ extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *p #define YOSYS_NAMESPACE_PREFIX Yosys:: #define USING_YOSYS_NAMESPACE using namespace Yosys; +#if __cplusplus >= 201103L +# define YS_OVERRIDE override +# define YS_FINAL final +#else +# define YS_OVERRIDE +# define YS_FINAL +#endif + #if defined(__GNUC__) || defined(__clang__) # define YS_ATTRIBUTE(...) __attribute__((__VA_ARGS__)) +# define YS_NORETURN #elif defined(_MSC_VER) # define YS_ATTRIBUTE(...) +# define YS_NORETURN __declspec(noreturn) #else # define YS_ATTRIBUTE(...) -#endif - -#if __cplusplus >= 201703L -# define YS_MAYBE_UNUSED [[maybe_unused]]; -#elif defined(__GNUC__) || defined(__clang__) -# define YS_MAYBE_UNUSED __attribute__((__unused__)) -#else -# define YS_MAYBE_UNUSED -#endif - -#if __cplusplus >= 201703L -# define YS_FALLTHROUGH [[fallthrough]]; -#elif defined(__clang__) -# define YS_FALLTHROUGH [[clang::fallthrough]]; -#elif defined(__GNUC__) -# define YS_FALLTHROUGH [[gnu::fallthrough]]; -#else -# define YS_FALLTHROUGH +# define YS_NORETURN #endif YOSYS_NAMESPACE_BEGIN @@ -218,7 +207,6 @@ namespace RTLIL { struct SigSpec; struct Wire; struct Cell; - struct Memory; struct Module; struct Design; struct Monitor; @@ -241,7 +229,6 @@ using RTLIL::Design; namespace hashlib { template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; - template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; @@ -249,7 +236,6 @@ namespace hashlib { template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; - template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; @@ -271,9 +257,7 @@ int readsome(std::istream &f, char *s, int n); std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false); std::vector split_tokens(const std::string &text, const char *sep = " \t\r\n"); bool patmatch(const char *pattern, const char *string); -#if !defined(YOSYS_DISABLE_SPAWN) int run_command(const std::string &command, std::function process_line = std::function()); -#endif std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX"); std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX"); bool check_file_exists(std::string filename, bool is_exec = false); @@ -322,9 +306,9 @@ RTLIL::IdString new_id(std::string file, int line, std::string func); #define NEW_ID \ YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__) -// Create a statically allocated IdString object, using for example ID::A or ID($add). +// Create a statically allocated IdString object, using for example ID(A) or ID($add). // -// Recipe for Converting old code that is using conversion of strings like ID::A and +// 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. // @@ -337,7 +321,6 @@ namespace ID = RTLIL::ID; RTLIL::Design *yosys_get_design(); std::string proc_self_dirname(); std::string proc_share_dirname(); -std::string proc_program_prefix(); const char *create_prompt(RTLIL::Design *design, int recursion_counter); std::vector glob_filename(const std::string &filename_pattern); void rewrite_filename(std::string &filename); diff --git a/libs/ezsat/ezminisat.cc b/libs/ezsat/ezminisat.cc index ac4defac386..4be5fd4931a 100644 --- a/libs/ezsat/ezminisat.cc +++ b/libs/ezsat/ezminisat.cc @@ -29,12 +29,11 @@ #include #include +#include #include -#if !defined(_WIN32) && !defined(__wasm) -# include +#ifndef _WIN32 # include -# define HAS_ALARM #endif #include "../minisat/Solver.h" @@ -85,7 +84,7 @@ bool ezMiniSAT::eliminated(int idx) } #endif -#if defined(HAS_ALARM) +#ifndef _WIN32 ezMiniSAT *ezMiniSAT::alarmHandlerThis = NULL; clock_t ezMiniSAT::alarmHandlerTimeout = 0; @@ -184,7 +183,7 @@ bool ezMiniSAT::solver(const std::vector &modelExpressions, std::vector &modelExpressions, std::vectorsolve(assumps); -#if defined(HAS_ALARM) +#ifndef _WIN32 if (solverTimeout > 0) { if (alarmHandlerTimeout == 0) solverTimoutStatus = true; diff --git a/libs/ezsat/ezsat.cc b/libs/ezsat/ezsat.cc index 8c666ca1f97..177bcd8a301 100644 --- a/libs/ezsat/ezsat.cc +++ b/libs/ezsat/ezsat.cc @@ -1371,39 +1371,24 @@ int ezSAT::onehot(const std::vector &vec, bool max_only) if (max_only == false) formula.push_back(expression(OpOr, vec)); - if (vec.size() < 8) - { - // fall-back to simple O(n^2) solution for small cases - for (size_t i = 0; i < vec.size(); i++) - for (size_t j = i+1; j < vec.size(); j++) { - std::vector clause; - clause.push_back(NOT(vec[i])); - clause.push_back(NOT(vec[j])); - formula.push_back(expression(OpOr, clause)); - } - } - else - { - // create binary vector - int num_bits = clog2(vec.size()); - std::vector bits; - for (int k = 0; k < num_bits; k++) - bits.push_back(literal()); - - // add at-most-one clauses using binary encoding - for (size_t i = 0; i < vec.size(); i++) - for (int k = 0; k < num_bits; k++) { - std::vector clause; - clause.push_back(NOT(vec[i])); - clause.push_back((i & (1 << k)) != 0 ? bits[k] : NOT(bits[k])); - formula.push_back(expression(OpOr, clause)); - } - } + // create binary vector + int num_bits = clog2(vec.size()); + std::vector bits; + for (int k = 0; k < num_bits; k++) + bits.push_back(literal()); + + // add at-most-one clauses using binary encoding + for (size_t i = 0; i < vec.size(); i++) + for (int k = 0; k < num_bits; k++) { + std::vector clause; + clause.push_back(NOT(vec[i])); + clause.push_back((i & (1 << k)) != 0 ? bits[k] : NOT(bits[k])); + formula.push_back(expression(OpOr, clause)); + } return expression(OpAnd, formula); } -#if 0 int ezSAT::manyhot(const std::vector &vec, int min_hot, int max_hot) { // many-hot encoding using a simple sorting network @@ -1441,123 +1426,6 @@ int ezSAT::manyhot(const std::vector &vec, int min_hot, int max_hot) return expression(OpAnd, formula); } -#else -static std::vector lfsr_sym(ezSAT *that, const std::vector &vec, int poly) -{ - std::vector out; - - for (int i = 0; i < int(vec.size()); i++) - if ((poly & (1 << (i+1))) != 0) { - if (out.empty()) - out.push_back(vec.at(i)); - else - out.at(0) = that->XOR(out.at(0), vec.at(i)); - } - - for (int i = 0; i+1 < int(vec.size()); i++) - out.push_back(vec.at(i)); - - return out; -} - -static int lfsr_num(int vec, int poly, int cnt = 1) -{ - int mask = poly >> 1; - mask |= mask >> 1; - mask |= mask >> 2; - mask |= mask >> 4; - mask |= mask >> 8; - mask |= mask >> 16; - - while (cnt-- > 0) { - int bits = vec & (poly >> 1); - bits = ((bits & 0xAAAAAAAA) >> 1) ^ (bits & 0x55555555); - bits = ((bits & 0x44444444) >> 2) ^ (bits & 0x11111111); - bits = ((bits & 0x10101010) >> 4) ^ (bits & 0x01010101); - bits = ((bits & 0x01000100) >> 8) ^ (bits & 0x00010001); - bits = ((bits & 0x00010000) >> 16) ^ (bits & 0x00000001); - vec = ((vec << 1) | bits) & mask; - } - - return vec; -} - -int ezSAT::manyhot(const std::vector &vec, int min_hot, int max_hot) -{ - // many-hot encoding using LFSR as counter - - int poly = 0; - int nbits = 0; - - if (vec.size() < 3) { - poly = (1 << 2) | (1 << 1) | 1; - nbits = 2; - } else - if (vec.size() < 7) { - poly = (1 << 3) | (1 << 2) | 1; - nbits = 3; - } else - if (vec.size() < 15) { - poly = (1 << 4) | (1 << 3) | 1; - nbits = 4; - } else - if (vec.size() < 31) { - poly = (1 << 5) | (1 << 3) | 1; - nbits = 5; - } else - if (vec.size() < 63) { - poly = (1 << 6) | (1 << 5) | 1; - nbits = 6; - } else - if (vec.size() < 127) { - poly = (1 << 7) | (1 << 6) | 1; - nbits = 7; - } else - // if (vec.size() < 255) { - // poly = (1 << 8) | (1 << 6) | (1 << 5) | (1 << 4) | 1; - // nbits = 8; - // } else - if (vec.size() < 511) { - poly = (1 << 9) | (1 << 5) | 1; - nbits = 9; - } else { - assert(0); - } - - std::vector min_val; - std::vector max_val; - - if (min_hot > 1) - min_val = vec_const_unsigned(lfsr_num(1, poly, min_hot), nbits); - - if (max_hot >= 0) - max_val = vec_const_unsigned(lfsr_num(1, poly, max_hot+1), nbits); - - std::vector state = vec_const_unsigned(1, nbits); - - std::vector match_min; - std::vector match_max; - - if (min_hot == 1) - match_min = vec; - - for (int i = 0; i < int(vec.size()); i++) - { - state = vec_ite(vec[i], lfsr_sym(this, state, poly), state); - - if (!min_val.empty() && i+1 >= min_hot) - match_min.push_back(vec_eq(min_val, state)); - - if (!max_val.empty() && i >= max_hot) - match_max.push_back(vec_eq(max_val, state)); - } - - int min_matched = min_hot ? vec_reduce_or(match_min) : CONST_TRUE; - int max_matched = vec_reduce_or(match_max); - - return AND(min_matched, NOT(max_matched)); -} -#endif int ezSAT::ordered(const std::vector &vec1, const std::vector &vec2, bool allow_equal) { diff --git a/libs/minisat/00_PATCH_wasm.patch b/libs/minisat/00_PATCH_wasm.patch deleted file mode 100644 index 38493004797..00000000000 --- a/libs/minisat/00_PATCH_wasm.patch +++ /dev/null @@ -1,46 +0,0 @@ ---- System.cc -+++ System.cc -@@ -101,7 +101,7 @@ double Minisat::memUsedPeak(bool) { return 0; } - #endif - - --#if !defined(_MSC_VER) && !defined(__MINGW32__) -+#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm) - void Minisat::limitMemory(uint64_t max_mem_mb) - { - // FIXME: OpenBSD does not support RLIMIT_AS. Not sure how well RLIMIT_DATA works instead. -@@ -133,7 +133,7 @@ void Minisat::limitMemory(uint64_t /*max_mem_mb*/) - #endif - - --#if !defined(_MSC_VER) && !defined(__MINGW32__) -+#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm) - void Minisat::limitTime(uint32_t max_cpu_time) - { - if (max_cpu_time != 0){ -@@ -156,9 +156,13 @@ void Minisat::limitTime(uint32_t /*max_cpu_time*/) - - void Minisat::sigTerm(void handler(int)) - { -+#if defined(__wasm) -+ (void)handler; -+#else - signal(SIGINT, handler); - signal(SIGTERM,handler); - #ifdef SIGXCPU - signal(SIGXCPU,handler); - #endif -+#endif - } ---- System.cc -+++ System.cc -@@ -24,7 +24,9 @@ - OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - **************************************************************************************************/ - -+#if !defined(__wasm) - #include -+#endif - #include - - #include "System.h" diff --git a/libs/minisat/00_UPDATE.sh b/libs/minisat/00_UPDATE.sh index 51107e4506a..ea26215ab2a 100755 --- a/libs/minisat/00_UPDATE.sh +++ b/libs/minisat/00_UPDATE.sh @@ -16,4 +16,4 @@ patch -p0 < 00_PATCH_mkLit_default_arg.patch patch -p0 < 00_PATCH_remove_zlib.patch patch -p0 < 00_PATCH_no_fpu_control.patch patch -p0 < 00_PATCH_typofixes.patch -patch -p0 < 00_PATCH_wasm.patch + diff --git a/libs/minisat/System.cc b/libs/minisat/System.cc index 807e46c694b..1921a1d7157 100644 --- a/libs/minisat/System.cc +++ b/libs/minisat/System.cc @@ -24,9 +24,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ -#if !defined(__wasm) #include -#endif #include #include "System.h" @@ -103,7 +101,7 @@ double Minisat::memUsedPeak(bool) { return 0; } #endif -#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm) +#if !defined(_MSC_VER) && !defined(__MINGW32__) void Minisat::limitMemory(uint64_t max_mem_mb) { // FIXME: OpenBSD does not support RLIMIT_AS. Not sure how well RLIMIT_DATA works instead. @@ -135,7 +133,7 @@ void Minisat::limitMemory(uint64_t /*max_mem_mb*/) #endif -#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm) +#if !defined(_MSC_VER) && !defined(__MINGW32__) void Minisat::limitTime(uint32_t max_cpu_time) { if (max_cpu_time != 0){ @@ -158,13 +156,9 @@ void Minisat::limitTime(uint32_t /*max_cpu_time*/) void Minisat::sigTerm(void handler(int)) { -#if defined(__wasm) - (void)handler; -#else signal(SIGINT, handler); signal(SIGTERM,handler); #ifdef SIGXCPU signal(SIGXCPU,handler); #endif -#endif } diff --git a/libs/sha1/sha1.h b/libs/sha1/sha1.h index b1346b548f3..9f526376e69 100644 --- a/libs/sha1/sha1.h +++ b/libs/sha1/sha1.h @@ -35,9 +35,9 @@ class SHA1 static std::string from_file(const std::string &filename); private: - static constexpr unsigned int DIGEST_INTS = 5; /* number of 32bit integers per SHA1 digest */ - static constexpr unsigned int BLOCK_INTS = 16; /* number of 32bit integers per SHA1 block */ - static constexpr unsigned int BLOCK_BYTES = BLOCK_INTS * 4; + static const unsigned int DIGEST_INTS = 5; /* number of 32bit integers per SHA1 digest */ + static const unsigned int BLOCK_INTS = 16; /* number of 32bit integers per SHA1 block */ + static const unsigned int BLOCK_BYTES = BLOCK_INTS * 4; uint32_t digest[DIGEST_INTS]; std::string buffer; diff --git a/libs/subcircuit/subcircuit.cc b/libs/subcircuit/subcircuit.cc index 4068dc09aa6..e8361a67e87 100644 --- a/libs/subcircuit/subcircuit.cc +++ b/libs/subcircuit/subcircuit.cc @@ -316,7 +316,7 @@ class SubCircuit::SolverWorker // helper functions for handling permutations - static constexpr int maxPermutationsLimit = 1000000; + static const int maxPermutationsLimit = 1000000; static int numberOfPermutations(const std::vector &list) { @@ -1689,3 +1689,4 @@ void SubCircuit::Solver::clearConfig() { worker->clearConfig(); } + diff --git a/manual/CHAPTER_Auxprogs.tex b/manual/CHAPTER_Auxprogs.tex index f09b18f7610..724d37f0b9c 100644 --- a/manual/CHAPTER_Auxprogs.tex +++ b/manual/CHAPTER_Auxprogs.tex @@ -19,8 +19,7 @@ \section{yosys-filterlib} \section{yosys-abc} -This is a fork of ABC \citeweblink{ABC} with a small set of custom modifications -that have not yet been accepted upstream. Not all versions of Yosys work with -all versions of ABC. So Yosys comes with its own yosys-abc to avoid +This is a unmodified copy of ABC \citeweblink{ABC}. Not all versions of Yosys +work with all versions of ABC. So Yosys comes with its own yosys-abc to avoid compatibility issues between the two. diff --git a/manual/CHAPTER_CellLib.tex b/manual/CHAPTER_CellLib.tex index 25adcda8614..00a88cc82d8 100644 --- a/manual/CHAPTER_CellLib.tex +++ b/manual/CHAPTER_CellLib.tex @@ -139,8 +139,6 @@ \subsection{Binary Operators} \lstinline[language=Verilog]; Y = A * B; & {\tt \$mul} \\ \lstinline[language=Verilog]; Y = A / B; & {\tt \$div} \\ \lstinline[language=Verilog]; Y = A % B; & {\tt \$mod} \\ -\multicolumn{1}{c}{\tt [N/A]} & {\tt \$divfloor} \\ -\multicolumn{1}{c}{\tt [N/A]} & {\tt \$modfoor} \\ \lstinline[language=Verilog]; Y = A ** B; & {\tt \$pow} \\ \end{tabular} \caption{Cell types for binary operators with their corresponding Verilog expressions.} @@ -163,27 +161,6 @@ \subsection{Binary Operators} {\tt \$gt}), when the \B{Y\_WIDTH} parameter is greater than 1, the output is zero-extended, and only the least significant bit varies. -Division and modulo cells are available in two rounding modes. The original {\tt \$div} and {\tt \$mod} -cells are based on truncating division, and correspond to the semantics of the verilog {\tt /} and -{\tt \%} operators. The {\tt \$divfloor} and {\tt \$modfloor} cells represent flooring division and -flooring modulo, the latter of which is also known as ``remainder'' in several languages. See -table~\ref{tab:CellLib_divmod} for a side-by-side comparison between the different semantics. - -\begin{table}[h] -\hfil -\begin{tabular}{lr|rr|rr} -\multirow{2}{*}{Division} & \multirow{2}{*}{Result} & \multicolumn{2}{c|}{Truncating} & \multicolumn{2}{c}{Flooring} \\ - & & {\tt \$div} & {\tt \$mod} & {\tt \$divfloor} & {\tt \$modfloor} \\ -\hline -{\tt -10 / 3} & {\tt -3.3} & {\tt -3} & {\tt -1} & {\tt -4} & {\tt 2} \\ -{\tt 10 / -3} & {\tt -3.3} & {\tt -3} & {\tt 1} & {\tt -4} & {\tt -2} \\ -{\tt -10 / -3} & {\tt 3.3} & {\tt 3} & {\tt -1} & {\tt 3} & {\tt -1} \\ -{\tt 10 / 3} & {\tt 3.3} & {\tt 3} & {\tt 1} & {\tt 3} & {\tt 1} \\ -\end{tabular} -\caption{Comparison between different rounding modes for division and modulo cells.} -\label{tab:CellLib_divmod} -\end{table} - \subsection{Multiplexers} Multiplexers are generated by the Verilog HDL frontend for {\tt @@ -221,8 +198,8 @@ \subsection{Multiplexers} \subsection{Registers} -D-type flip-flops are represented by {\tt \$dff} cells. These cells have a clock port \B{CLK}, -an input port \B{D} and an output port \B{Q}. The following parameters are available for {\tt \$dff} +D-Type Flip-Flops are represented by {\tt \$dff} cells. These cells have a clock port \B{CLK}, +an input port \B{D} and an output port \B{Q}. The following parameters are available for \$dff cells: \begin{itemize} @@ -234,72 +211,28 @@ \subsection{Registers} edge if this parameter is {\tt 1'b0}. \end{itemize} -D-type flip-flops with asynchronous reset are represented by {\tt \$adff} cells. As the {\tt \$dff} +D-Type Flip-Flops with asynchronous resets are represented by {\tt \$adff} cells. As the {\tt \$dff} cells they have \B{CLK}, \B{D} and \B{Q} ports. In addition they also have a single-bit \B{ARST} input port for the reset pin and the following additional two parameters: \begin{itemize} \item \B{ARST\_POLARITY} \\ -The asynchronous reset is active-high if this parameter has the value {\tt 1'b1} and active-low +The asynchronous reset is high-active if this parameter has the value {\tt 1'b1} and low-active if this parameter is {\tt 1'b0}. \item \B{ARST\_VALUE} \\ The state of \B{Q} will be set to this value when the reset is active. \end{itemize} +Note that the {\tt \$adff} cell can only be used when the reset value is constant. + \begin{sloppypar} Usually these cells are generated by the {\tt proc} pass using the information in the designs RTLIL::Process objects. \end{sloppypar} -D-type flip-flops with synchronous reset are represented by {\tt \$sdff} cells. As the {\tt \$dff} -cells they have \B{CLK}, \B{D} and \B{Q} ports. In addition they also have a single-bit \B{SRST} -input port for the reset pin and the following additional two parameters: - -\begin{itemize} -\item \B{SRST\_POLARITY} \\ -The synchronous reset is active-high if this parameter has the value {\tt 1'b1} and active-low -if this parameter is {\tt 1'b0}. - -\item \B{SRST\_VALUE} \\ -The state of \B{Q} will be set to this value when the reset is active. -\end{itemize} - -Note that the {\tt \$adff} and {\tt \$sdff} cells can only be used when the reset value is constant. - -D-type flip-flops with asynchronous set and reset are represented by {\tt \$dffsr} cells. -As the {\tt \$dff} cells they have \B{CLK}, \B{D} and \B{Q} ports. In addition they also have -a single-bit \B{SET} input port for the set pin, a single-bit \B{CLR} input port for the reset pin, -and the following two parameters: - -\begin{itemize} -\item \B{SET\_POLARITY} \\ -The set input is active-high if this parameter has the value {\tt 1'b1} and active-low -if this parameter is {\tt 1'b0}. - -\item \B{CLR\_POLARITY} \\ -The reset input is active-high if this parameter has the value {\tt 1'b1} and active-low -if this parameter is {\tt 1'b0}. -\end{itemize} - -When both the set and reset inputs of a {\tt \$dffsr} cell are active, the reset input takes -precedence. - -D-type flip-flops with enable are represented by {\tt \$dffe}, {\tt \$adffe}, {\tt \$dffsre}, -{\tt \$sdffe}, and {\tt \$sdffce} cells, which are enhanced variants of {\tt \$dff}, {\tt \$adff}, {\tt \$dffsr}, -{\tt \$sdff} (with reset over enable) and {\tt \$sdff} (with enable over reset) -cells, respectively. They have the same ports and parameters as their base cell. -In addition they also have a single-bit \B{EN} input port for the enable pin and the following parameter: - -\begin{itemize} -\item \B{EN\_POLARITY} \\ -The enable input is active-high if this parameter has the value {\tt 1'b1} and active-low -if this parameter is {\tt 1'b0}. -\end{itemize} - \begin{fixme} -Add information about {\tt \$sr} cells (set-reset flip-flops), {\tt \$dlatch} cells (d-type latches), -{\tt \$adlatch} and {\tt \$dlatchsr} cells (d-type latches with set/reset). +Add information about {\tt \$sr} cells (set-reset flip-flops) and d-type latches. \end{fixme} \subsection{Memories} @@ -505,131 +438,32 @@ \section{Gates} \lstinline[language=Verilog]; always @(negedge C) Q <= D; & {\tt \$\_DFF\_N\_} \\ \lstinline[language=Verilog]; always @(posedge C) Q <= D; & {\tt \$\_DFF\_P\_} \\ \end{tabular} -\caption{Cell types for gate level logic networks (main list)} -\label{tab:CellLib_gates} -\end{table} - -\begin{table}[t] \hfil \begin{tabular}[t]{llll} $ClkEdge$ & $RstLvl$ & $RstVal$ & Cell Type \\ \hline -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFF\_NN0\_}, {\tt \$\_SDFF\_NN0\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFF\_NN1\_}, {\tt \$\_SDFF\_NN1\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFF\_NP0\_}, {\tt \$\_SDFF\_NP0\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFF\_NP1\_}, {\tt \$\_SDFF\_NP1\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFF\_PN0\_}, {\tt \$\_SDFF\_PN0\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFF\_PN1\_}, {\tt \$\_SDFF\_PN1\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFF\_PP0\_}, {\tt \$\_SDFF\_PP0\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFF\_PP1\_}, {\tt \$\_SDFF\_PP1\_} \\ -\end{tabular} -\caption{Cell types for gate level logic networks (FFs with reset)} -\label{tab:CellLib_gates_adff} -\end{table} - -\begin{table}[t] -\hfil -\begin{tabular}[t]{lll} -$ClkEdge$ & $EnLvl$ & Cell Type \\ -\hline -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_NN\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_NP\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_PN\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_PP\_} \\ -\end{tabular} -\caption{Cell types for gate level logic networks (FFs with enable)} -\label{tab:CellLib_gates_dffe} -\end{table} - -\begin{table}[t] -\begin{tabular}[t]{lllll} -$ClkEdge$ & $RstLvl$ & $RstVal$ & $EnLvl$ & Cell Type \\ -\hline -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_NN0N\_}, {\tt \$\_SDFFE\_NN0N\_}, {\tt \$\_SDFFCE\_NN0N\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_NN0P\_}, {\tt \$\_SDFFE\_NN0P\_}, {\tt \$\_SDFFCE\_NN0P\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_NN1N\_}, {\tt \$\_SDFFE\_NN1N\_}, {\tt \$\_SDFFCE\_NN1N\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_NN1P\_}, {\tt \$\_SDFFE\_NN1P\_}, {\tt \$\_SDFFCE\_NN1P\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_NP0N\_}, {\tt \$\_SDFFE\_NP0N\_}, {\tt \$\_SDFFCE\_NP0N\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_NP0P\_}, {\tt \$\_SDFFE\_NP0P\_}, {\tt \$\_SDFFCE\_NP0P\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_NP1N\_}, {\tt \$\_SDFFE\_NP1N\_}, {\tt \$\_SDFFCE\_NP1N\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_NP1P\_}, {\tt \$\_SDFFE\_NP1P\_}, {\tt \$\_SDFFCE\_NP1P\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_PN0N\_}, {\tt \$\_SDFFE\_PN0N\_}, {\tt \$\_SDFFCE\_PN0N\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_PN0P\_}, {\tt \$\_SDFFE\_PN0P\_}, {\tt \$\_SDFFCE\_PN0P\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_PN1N\_}, {\tt \$\_SDFFE\_PN1N\_}, {\tt \$\_SDFFCE\_PN1N\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_PN1P\_}, {\tt \$\_SDFFE\_PN1P\_}, {\tt \$\_SDFFCE\_PN1P\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_PP0N\_}, {\tt \$\_SDFFE\_PP0N\_}, {\tt \$\_SDFFCE\_PP0N\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_PP0P\_}, {\tt \$\_SDFFE\_PP0P\_}, {\tt \$\_SDFFCE\_PP0P\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFE\_PP1N\_}, {\tt \$\_SDFFE\_PP1N\_}, {\tt \$\_SDFFCE\_PP1N\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFE\_PP1P\_}, {\tt \$\_SDFFE\_PP1P\_}, {\tt \$\_SDFFCE\_PP1P\_} \\ -\end{tabular} -\caption{Cell types for gate level logic networks (FFs with reset and enable)} -\label{tab:CellLib_gates_adffe} -\end{table} - -\begin{table}[t] -\hfil -\begin{tabular}[t]{llll} -$ClkEdge$ & $SetLvl$ & $RstLvl$ & Cell Type \\ -\hline -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSR\_NNN\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSR\_NNP\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSR\_NPN\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSR\_NPP\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSR\_PNN\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSR\_PNP\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSR\_PPN\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSR\_PPP\_} \\ -\end{tabular} -\caption{Cell types for gate level logic networks (FFs with set and reset)} -\label{tab:CellLib_gates_dffsr} -\end{table} - -\begin{table}[t] -\hfil -\begin{tabular}[t]{lllll} -$ClkEdge$ & $SetLvl$ & $RstLvl$ & $EnLvl$ & Cell Type \\ -\hline -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSRE\_NNNN\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSRE\_NNNP\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSRE\_NNPN\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSRE\_NNPP\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSRE\_NPNN\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSRE\_NPNP\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSRE\_NPPN\_} \\ -\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSRE\_NPPP\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSRE\_PNNN\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSRE\_PNNP\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSRE\_PNPN\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSRE\_PNPP\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSRE\_PPNN\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSRE\_PPNP\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFFSRE\_PPPN\_} \\ -\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFFSRE\_PPPP\_} \\ +\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFF\_NN0\_} \\ +\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFF\_NN1\_} \\ +\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFF\_NP0\_} \\ +\lstinline[language=Verilog];negedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFF\_NP1\_} \\ +\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DFF\_PN0\_} \\ +\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DFF\_PN1\_} \\ +\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DFF\_PP0\_} \\ +\lstinline[language=Verilog];posedge; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DFF\_PP1\_} \\ \end{tabular} -\caption{Cell types for gate level logic networks (FFs with set and reset and enable)} -\label{tab:CellLib_gates_dffsre} +\caption{Cell types for gate level logic networks} +\label{tab:CellLib_gates} \end{table} -Tables~\ref{tab:CellLib_gates}, \ref{tab:CellLib_gates_dffe}, \ref{tab:CellLib_gates_adff}, \ref{tab:CellLib_gates_adffe}, \ref{tab:CellLib_gates_dffsr} and \ref{tab:CellLib_gates_dffsre} list all cell types used for gate level logic. The cell types +Table~\ref{tab:CellLib_gates} lists all cell types used for gate level logic. The cell types {\tt \$\_NOT\_}, {\tt \$\_AND\_}, {\tt \$\_NAND\_}, {\tt \$\_ANDNOT\_}, {\tt \$\_OR\_}, {\tt \$\_NOR\_}, {\tt \$\_ORNOT\_}, {\tt \$\_XOR\_}, {\tt \$\_XNOR\_} and {\tt \$\_MUX\_} are used to model combinatorial logic. The cell type {\tt \$\_TBUF\_} is used to model tristate logic. - The cell types {\tt \$\_DFF\_N\_} and {\tt \$\_DFF\_P\_} represent d-type flip-flops. -The cell types {\tt \$\_DFFE\_NN\_}, {\tt \$\_DFFE\_NP\_}, {\tt \$\_DFFE\_PN\_} and {\tt \$\_DFFE\_PP\_} -implement d-type flip-flops with enable. The values in the table for these cell types relate to the -following Verilog code template. - -\begin{lstlisting}[mathescape,language=Verilog] - always @($ClkEdge$ C) - if (EN == $EnLvl$) - Q <= D; -\end{lstlisting} - The cell types {\tt \$\_DFF\_NN0\_}, {\tt \$\_DFF\_NN1\_}, {\tt \$\_DFF\_NP0\_}, {\tt \$\_DFF\_NP1\_}, {\tt \$\_DFF\_PN0\_}, {\tt \$\_DFF\_PN1\_}, {\tt \$\_DFF\_PP0\_} and {\tt \$\_DFF\_PP1\_} implement -d-type flip-flops with asynchronous reset. The values in the table for these cell types relate to the +d-type flip-flops with asynchronous resets. The values in the table for these cell types relate to the following Verilog code template, where \lstinline[mathescape,language=Verilog];$RstEdge$; is \lstinline[language=Verilog];posedge; if \lstinline[mathescape,language=Verilog];$RstLvl$; if \lstinline[language=Verilog];1;, and \lstinline[language=Verilog];negedge; otherwise. @@ -642,96 +476,6 @@ \section{Gates} Q <= D; \end{lstlisting} -The cell types {\tt \$\_SDFF\_NN0\_}, {\tt \$\_SDFF\_NN1\_}, {\tt \$\_SDFF\_NP0\_}, {\tt \$\_SDFF\_NP1\_}, -{\tt \$\_SDFF\_PN0\_}, {\tt \$\_SDFF\_PN1\_}, {\tt \$\_SDFF\_PP0\_} and {\tt \$\_SDFF\_PP1\_} implement -d-type flip-flops with synchronous reset. The values in the table for these cell types relate to the -following Verilog code template: - -\begin{lstlisting}[mathescape,language=Verilog] - always @($ClkEdge$ C) - if (R == $RstLvl$) - Q <= $RstVal$; - else - Q <= D; -\end{lstlisting} - -The cell types {\tt \$\_DFFE\_[NP][NP][01][NP]\_} implement -d-type flip-flops with asynchronous reset and enable. The values in the table for these cell types relate to the -following Verilog code template, where \lstinline[mathescape,language=Verilog];$RstEdge$; is \lstinline[language=Verilog];posedge; -if \lstinline[mathescape,language=Verilog];$RstLvl$; if \lstinline[language=Verilog];1;, and \lstinline[language=Verilog];negedge; -otherwise. - -\begin{lstlisting}[mathescape,language=Verilog] - always @($ClkEdge$ C, $RstEdge$ R) - if (R == $RstLvl$) - Q <= $RstVal$; - else if (EN == $EnLvl$) - Q <= D; -\end{lstlisting} - -The cell types {\tt \$\_SDFFE\_[NP][NP][01][NP]\_} implement d-type flip-flops -with synchronous reset and enable, with reset having priority over enable. -The values in the table for these cell types relate to the -following Verilog code template: - -\begin{lstlisting}[mathescape,language=Verilog] - always @($ClkEdge$ C) - if (R == $RstLvl$) - Q <= $RstVal$; - else if (EN == $EnLvl$) - Q <= D; -\end{lstlisting} - -The cell types {\tt \$\_SDFFCE\_[NP][NP][01][NP]\_} implement d-type flip-flops -with synchronous reset and enable, with enable having priority over reset. -The values in the table for these cell types relate to the -following Verilog code template: - -\begin{lstlisting}[mathescape,language=Verilog] - always @($ClkEdge$ C) - if (EN == $EnLvl$) - if (R == $RstLvl$) - Q <= $RstVal$; - else - Q <= D; -\end{lstlisting} - -The cell types {\tt \$\_DFFSR\_[NP][NP][NP]\_} implement -d-type flip-flops with asynchronous set and reset. The values in the table for these cell types relate to the -following Verilog code template, where \lstinline[mathescape,language=Verilog];$RstEdge$; is \lstinline[language=Verilog];posedge; -if \lstinline[mathescape,language=Verilog];$RstLvl$; if \lstinline[language=Verilog];1;, \lstinline[language=Verilog];negedge; -otherwise, and \lstinline[mathescape,language=Verilog];$SetEdge$; is \lstinline[language=Verilog];posedge; -if \lstinline[mathescape,language=Verilog];$SetLvl$; if \lstinline[language=Verilog];1;, \lstinline[language=Verilog];negedge; -otherwise. - -\begin{lstlisting}[mathescape,language=Verilog] - always @($ClkEdge$ C, $RstEdge$ R, $SetEdge$ S) - if (R == $RstLvl$) - Q <= 0; - else if (S == $SetLvl$) - Q <= 1; - else - Q <= D; -\end{lstlisting} - -The cell types {\tt \$\_DFFSRE\_[NP][NP][NP][NP]\_} implement -d-type flip-flops with asynchronous set and reset and enable. The values in the table for these cell types relate to the -following Verilog code template, where \lstinline[mathescape,language=Verilog];$RstEdge$; is \lstinline[language=Verilog];posedge; -if \lstinline[mathescape,language=Verilog];$RstLvl$; if \lstinline[language=Verilog];1;, \lstinline[language=Verilog];negedge; -otherwise, and \lstinline[mathescape,language=Verilog];$SetEdge$; is \lstinline[language=Verilog];posedge; -if \lstinline[mathescape,language=Verilog];$SetLvl$; if \lstinline[language=Verilog];1;, \lstinline[language=Verilog];negedge; -otherwise. - -\begin{lstlisting}[mathescape,language=Verilog] - always @($ClkEdge$ C, $RstEdge$ R, $SetEdge$ S) - if (R == $RstLvl$) - Q <= 0; - else if (S == $SetLvl$) - Q <= 1; - else if (E == $EnLvl$) - Q <= D; -\end{lstlisting} - In most cases gate level logic networks are created from RTL networks using the {\tt techmap} pass. The flip-flop cells from the gate level logic network can be mapped to physical flip-flop cells from a Liberty file using the {\tt dfflibmap} pass. The combinatorial logic cells can be mapped to physical cells from a Liberty file via ABC \citeweblink{ABC} @@ -763,7 +507,11 @@ \section{Gates} \end{fixme} \begin{fixme} -Add information about {\tt \$\_DLATCH\_?\_}, and {\tt \$\_DLATCHSR\_???\_} cells. +Add information about {\tt \$dffe}, {\tt \$dffsr}, {\tt \$dlatch}, and {\tt \$dlatchsr} cells. +\end{fixme} + +\begin{fixme} +Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLATCH\_?\_}, and {\tt \$\_DLATCHSR\_???\_} cells. \end{fixme} \begin{fixme} diff --git a/manual/CHAPTER_Overview.tex b/manual/CHAPTER_Overview.tex index 83cfa5cc460..3009bf2c030 100644 --- a/manual/CHAPTER_Overview.tex +++ b/manual/CHAPTER_Overview.tex @@ -184,22 +184,12 @@ \subsection{RTLIL Identifiers} disturbing external tools. For example the Verilog backend assigns names in the form {\tt \_{\it integer}\_}. \end{itemize} -Whitespace and control characters (any character with an ASCII code 32 or less) are not allowed -in RTLIL identifiers; most frontends and backends cannot support these characters in identifiers. - -In order to avoid programming errors, the RTLIL data structures check if all identifiers start -with either a backslash or a dollar sign, and contain no whitespace or control characters. -Violating these rules results in a runtime error. +In order to avoid programming errors, the RTLIL data structures check if all +identifiers start with either a backslash or a dollar sign and generate a +runtime error if this rule is violated. All RTLIL identifiers are case sensitive. -Some transformations, such as flattening, may have to change identifiers provided by the user -to avoid name collisions. When that happens, attribute ``{\tt hdlname}`` is attached to the object -with the changed identifier. This attribute contains one name (if emitted directly by the frontend, -or is a result of disambiguation) or multiple names separated by spaces (if a result of flattening). -All names specified in the ``{\tt hdlname}`` attribute are public and do not include the leading -``\textbackslash``. - \subsection{RTLIL::Design and RTLIL::Module} The RTLIL::Design object is basically just a container for RTLIL::Module objects. In addition to @@ -244,8 +234,6 @@ \subsection{RTLIL::Cell and RTLIL::Wire} \item The wire name \item A list of attributes \item A width (buses are just wires with a width > 1) -\item Bus direction (MSB to LSB or vice versa) -\item Lowest valid bit index (LSB or MSB depending on bus direction) \item If the wire is a port: port number and direction (input/output/inout) \end{itemize} @@ -258,11 +246,6 @@ \subsection{RTLIL::Cell and RTLIL::Wire} coarse grain synthesis where the cells of the target architecture operate on entire signal vectors instead of single bit wires. -In Verilog and VHDL, busses may have arbitrary bounds, and LSB can have either -the lowest or the highest bit index. In RTLIL, bit 0 always corresponds to LSB; -however, information from the HDL frontend is preserved so that the bus will be -correctly indexed in error messages, backend output, constraint files, etc. - An RTLIL::Cell object has the following properties: \begin{itemize} diff --git a/manual/CHAPTER_Prog/stubnets.cc b/manual/CHAPTER_Prog/stubnets.cc index 566d24b18df..8123e63db6f 100644 --- a/manual/CHAPTER_Prog/stubnets.cc +++ b/manual/CHAPTER_Prog/stubnets.cc @@ -98,7 +98,7 @@ static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool re // each pass contains a singleton object that is derived from Pass struct StubnetsPass : public Pass { StubnetsPass() : Pass("stubnets") { } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { // variables to mirror information from passed options bool report_bits = 0; diff --git a/manual/CHAPTER_Verilog.tex b/manual/CHAPTER_Verilog.tex index d4cc55647df..e9ca6114e01 100644 --- a/manual/CHAPTER_Verilog.tex +++ b/manual/CHAPTER_Verilog.tex @@ -93,7 +93,7 @@ \subsection{The Verilog Lexer} \begin{sloppypar} The Verilog Lexer is written using the lexer generator {\it flex} \citeweblink{flex}. Its source code -can be found in {\tt frontends/verilog/verilog\_lexer.l} in the Yosys source tree. +can be found in {\tt frontends/verilog/lexer.l} in the Yosys source tree. The lexer does little more than identifying all keywords and literals recognised by the Yosys Verilog frontend. \end{sloppypar} @@ -115,7 +115,7 @@ \subsection{The Verilog Lexer} \subsection{The Verilog Parser} The Verilog Parser is written using the parser generator {\it bison} \citeweblink{bison}. Its source code -can be found in {\tt frontends/verilog/verilog\_parser.y} in the Yosys source tree. +can be found in {\tt frontends/verilog/parser.y} in the Yosys source tree. It generates an AST using the \lstinline[language=C++]{AST::AstNode} data structure defined in {\tt frontends/ast/ast.h}. An \lstinline[language=C++]{AST::AstNode} object has diff --git a/manual/PRESENTATION_Prog.tex b/manual/PRESENTATION_Prog.tex index a9416f82a4a..b85eda89272 100644 --- a/manual/PRESENTATION_Prog.tex +++ b/manual/PRESENTATION_Prog.tex @@ -307,7 +307,7 @@ \subsubsection{The RTLIL::Cell Structure} \begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{6pt}{7pt}\selectfont] $not $pos $neg $and $or $xor $xnor $reduce_and $reduce_or $reduce_xor $reduce_xnor $reduce_bool $shl $shr $sshl $sshr $lt $le $eq $ne $eqx $nex $ge $gt $add $sub $mul $div $mod -$divfloor $modfloor $pow $logic_not $logic_and $logic_or $mux $pmux $slice $concat $lut $assert $sr $dff +$pow $logic_not $logic_and $logic_or $mux $pmux $slice $concat $lut $assert $sr $dff $dffsr $adff $dlatch $dlatchsr $memrd $memwr $mem $fsm $_NOT_ $_AND_ $_OR_ $_XOR_ $_MUX_ $_SR_NN_ $_SR_NP_ $_SR_PN_ $_SR_PP_ $_DFF_N_ $_DFF_P_ $_DFF_NN0_ $_DFF_NN1_ $_DFF_NP0_ $_DFF_NP1_ $_DFF_PN0_ $_DFF_PN1_ $_DFF_PP0_ $_DFF_PP1_ $_DFFSR_NNN_ $_DFFSR_NNP_ $_DFFSR_NPN_ $_DFFSR_NPP_ $_DFFSR_PNN_ diff --git a/manual/PRESENTATION_Prog/Makefile b/manual/PRESENTATION_Prog/Makefile index 7e3cf814b44..794f5c12c93 100644 --- a/manual/PRESENTATION_Prog/Makefile +++ b/manual/PRESENTATION_Prog/Makefile @@ -1,11 +1,8 @@ all: test0.log test1.log test2.log -CXXFLAGS=$(shell ../../yosys-config --cxxflags) -DATDIR=$(shell ../../yosys-config --datdir) - my_cmd.so: my_cmd.cc - ../../yosys-config --exec --cxx $(subst $(DATDIR),../../share,$(CXXFLAGS)) --ldflags -o my_cmd.so -shared my_cmd.cc --ldlibs + ../../yosys-config --exec --cxx --cxxflags --ldflags -o my_cmd.so -shared my_cmd.cc --ldlibs test0.log: my_cmd.so ../../yosys -Ql test0.log_new -m ./my_cmd.so -p 'my_cmd foo bar' absval_ref.v diff --git a/manual/PRESENTATION_Prog/my_cmd.cc b/manual/PRESENTATION_Prog/my_cmd.cc index 9cb4b8e38b1..5d9a7e13bfe 100644 --- a/manual/PRESENTATION_Prog/my_cmd.cc +++ b/manual/PRESENTATION_Prog/my_cmd.cc @@ -6,7 +6,7 @@ PRIVATE_NAMESPACE_BEGIN struct MyPass : public Pass { MyPass() : Pass("my_cmd", "just a simple test") { } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log("Arguments to my_cmd:\n"); for (auto &arg : args) @@ -22,7 +22,7 @@ struct MyPass : public Pass { struct Test1Pass : public Pass { Test1Pass() : Pass("test1", "creating the absval module") { } - void execute(std::vector, RTLIL::Design *design) override + void execute(std::vector, RTLIL::Design *design) YS_OVERRIDE { if (design->has("\\absval") != 0) log_error("A module with the name absval already exists!\n"); @@ -49,7 +49,7 @@ struct Test1Pass : public Pass { struct Test2Pass : public Pass { Test2Pass() : Pass("test2", "demonstrating sigmap on test module") { } - void execute(std::vector, RTLIL::Design *design) override + void execute(std::vector, RTLIL::Design *design) YS_OVERRIDE { if (design->selection_stack.back().empty()) log_cmd_error("This command can't operator on an empty selection!\n"); diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex index 988f034b4bc..bed6326e244 100644 --- a/manual/command-reference-manual.tex +++ b/manual/command-reference-manual.tex @@ -116,26 +116,20 @@ \section{abc -- use ABC for technology mapping} -g type1,type2,... Map to the specified list of gate types. Supported gates types are: - AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, - NMUX, AOI3, OAI3, AOI4, OAI4. + AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4. (The NOT gate is always added to this list automatically.) The following aliases can be used to reference common sets of gate types: simple: AND OR XOR MUX - cmos2: NAND NOR - cmos3: NAND NOR AOI3 OAI3 - cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4 - cmos: NAND NOR AOI3 OAI3 AOI4 OAI4 NMUX MUX XOR XNOR - gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT - aig: AND NAND OR NOR ANDNOT ORNOT - - The alias 'all' represent the full set of all gate types. + cmos2: NAND NOR + cmos3: NAND NOR AOI3 OAI3 + cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4 + gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT + aig: AND NAND OR NOR ANDNOT ORNOT Prefix a gate type with a '-' to remove it from the list. For example the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent. - The default is 'all,-NMUX,-AOI3,-OAI3,-AOI4,-OAI4'. - -dff also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many clock domains are automatically partitioned in clock domains and each @@ -162,11 +156,6 @@ \section{abc -- use ABC for technology mapping} this attribute is a unique integer for each ABC process started. This is useful for debugging the partitioning of clock domains. - -dress - run the 'dress' command after all other ABC commands. This aims to - preserve naming by an equivalence check between the original and post-ABC - netlists (experimental). - When neither -liberty nor -lut is used, the Yosys standard cell library is loaded into ABC before the ABC script is executed. @@ -174,251 +163,12 @@ \section{abc -- use ABC for technology mapping} internally. This is not going to "run ABC on your design". It will instead run ABC on logic snippets extracted from your design. You will not get any useful output when passing an ABC script that writes a file. Instead write your full -design as BLIF file with write_blif and then load that into ABC externally if -you want to use ABC to convert your design into another format. - -[1] http://www.eecs.berkeley.edu/~alanmi/abc/ -\end{lstlisting} - -\section{abc9 -- use ABC9 for technology mapping} -\label{cmd:abc9} -\begin{lstlisting}[numbers=left,frame=single] - abc9 [options] [selection] - -This script pass performs a sequence of commands to facilitate the use of the ABC -tool [1] for technology mapping of the current design to a target FPGA -architecture. Only fully-selected modules are supported. - - -run : - only run the commands between the labels (see below). an empty - from label is synonymous to 'begin', and empty to label is - synonymous to the end of the command list. - - -exe - use the specified command instead of "/yosys-abc" to execute ABC. - This can e.g. be used to call a specific version of ABC or a wrapper. - - -script - use the specified ABC script file instead of the default script. - - if starts with a plus sign (+), then the rest of the filename - string is interpreted as the command string to be passed to ABC. The - leading plus sign is removed and all commas (,) in the string are - replaced with blanks before the string is passed to ABC. - - if no -script parameter is given, the following scripts are used: - &scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -v; &mfs - - -fast - use different default scripts that are slightly faster (at the cost - of output quality): - &if {C} {W} {D} {R} -v - - -D - set delay target. the string {D} in the default scripts above is - replaced by this option when used, and an empty string otherwise - (indicating best possible delay). - - -lut - generate netlist using luts of (max) the specified width. - - -lut : - generate netlist using luts of (max) the specified width . All - luts with width <= have constant cost. for luts larger than - the area cost doubles with each additional input bit. the delay cost - is still constant for all lut widths. - - -lut - pass this file with lut library to ABC. - - -luts ,,,:,.. - generate netlist using luts. Use the specified costs for luts with 1, - 2, 3, .. inputs. - - -maxlut - when auto-generating the lut library, discard all luts equal to or - greater than this size (applicable when neither -lut nor -luts is - specified). - - -dff - also pass $_ABC9_FF_ cells through to ABC. modules with many clock - domains are marked as such and automatically partitioned by ABC. - - -nocleanup - when this option is used, the temporary files created by this pass - are not removed. this is useful for debugging. - - -showtmp - print the temp dir name in log. usually this is suppressed so that the - command output is identical across runs. - - -box - pass this file with box library to ABC. - -Note that this is a logic optimization pass within Yosys that is calling ABC -internally. This is not going to "run ABC on your design". It will instead run -ABC on logic snippets extracted from your design. You will not get any useful -output when passing an ABC script that writes a file. Instead write your full -design as an XAIGER file with `write_xaiger' and then load that into ABC -externally if you want to use ABC to convert your design into another format. - -[1] http://www.eecs.berkeley.edu/~alanmi/abc/ - - - pre: - abc9_ops -check - scc -set_attr abc9_scc_id {} - abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff] (option for -dff) - abc9_ops -prep_lut (skip if -lut or -luts) - abc9_ops -prep_box [-dff] (skip if -box) - select -set abc9_holes A:abc9_holes - flatten -wb @abc9_holes - techmap @abc9_holes - abc9_ops -prep_dff (only if -dff) - opt -purge @abc9_holes - aigmap - wbflip @abc9_holes - - map: - foreach module in selection - abc9_ops -write_lut /input.lut (skip if '-lut' or '-luts') - abc9_ops -write_box /input.box - write_xaiger -map /input.sym /input.xaig - abc9_exe [options] -cwd [-lut /input.lut] -box /input.box - read_aiger -xaiger -wideports -module_name $abc9 -map /input.sym /output.aig - abc9_ops -reintegrate -\end{lstlisting} - -\section{abc9\_exe -- use ABC9 for technology mapping} -\label{cmd:abc9_exe} -\begin{lstlisting}[numbers=left,frame=single] - abc9_exe [options] - - -This pass uses the ABC tool [1] for technology mapping of the top module -(according to the (* top *) attribute or if only one module is currently selected) -to a target FPGA architecture. - - -exe - use the specified command instead of "/yosys-abc" to execute ABC. - This can e.g. be used to call a specific version of ABC or a wrapper. - - -script - use the specified ABC script file instead of the default script. - - if starts with a plus sign (+), then the rest of the filename - string is interpreted as the command string to be passed to ABC. The - leading plus sign is removed and all commas (,) in the string are - replaced with blanks before the string is passed to ABC. - - if no -script parameter is given, the following scripts are used: - &scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -v; &mfs - - -fast - use different default scripts that are slightly faster (at the cost - of output quality): - &if {C} {W} {D} {R} -v - - -D - set delay target. the string {D} in the default scripts above is - replaced by this option when used, and an empty string otherwise - (indicating best possible delay). - - -lut - generate netlist using luts of (max) the specified width. - - -lut : - generate netlist using luts of (max) the specified width . All - luts with width <= have constant cost. for luts larger than - the area cost doubles with each additional input bit. the delay cost - is still constant for all lut widths. - - -lut - pass this file with lut library to ABC. - - -luts ,,,:,.. - generate netlist using luts. Use the specified costs for luts with 1, - 2, 3, .. inputs. - - -showtmp - print the temp dir name in log. usually this is suppressed so that the - command output is identical across runs. - - -box - pass this file with box library to ABC. - - -cwd - use this as the current working directory, inside which the 'input.xaig' - file is expected. temporary files will be created in this directory, and - the mapped result will be written to 'output.aig'. - -Note that this is a logic optimization pass within Yosys that is calling ABC -internally. This is not going to "run ABC on your design". It will instead run -ABC on logic snippets extracted from your design. You will not get any useful -output when passing an ABC script that writes a file. Instead write your full -design as BLIF file with write_blif and then load that into ABC externally if +design as BLIF file with write_blif and the load that into ABC externally if you want to use ABC to convert your design into another format. [1] http://www.eecs.berkeley.edu/~alanmi/abc/ \end{lstlisting} -\section{abc9\_ops -- helper functions for ABC9} -\label{cmd:abc9_ops} -\begin{lstlisting}[numbers=left,frame=single] - abc9_ops [options] [selection] - -This pass contains a set of supporting operations for use during ABC technology -mapping, and is expected to be called in conjunction with other operations from -the `abc9' script pass. Only fully-selected modules are supported. - - -check - check that the design is valid, e.g. (* abc9_box_id *) values are unique, - (* abc9_carry *) is only given for one input/output port, etc. - - -prep_delays - insert `$__ABC9_DELAY' blackbox cells into the design to account for - certain required times. - - -mark_scc - for an arbitrarily chosen cell in each unique SCC of each selected module - (tagged with an (* abc9_scc_id = *) attribute), temporarily mark all - wires driven by this cell's outputs with a (* keep *) attribute in order - to break the SCC. this temporary attribute will be removed on -reintegrate. - - -prep_xaiger - prepare the design for XAIGER output. this includes computing the - topological ordering of ABC9 boxes, as well as preparing the - '$holes' module that contains the logic behaviour of ABC9 - whiteboxes. - - -dff - consider flop cells (those instantiating modules marked with (* abc9_flop *)) - during -prep_{delays,xaiger,box}. - - -prep_dff - compute the clock domain and initial value of each flop in the design. - process the '$holes' module to support clock-enable functionality. - - -prep_lut - pre-compute the lut library by analysing all modules marked with - (* abc9_lut= *). - - -write_lut - write the pre-computed lut library to . - - -prep_box - pre-compute the box library by analysing all modules marked with - (* abc9_box *). - - -write_box - write the pre-computed box library to . - - -reintegrate - for each selected module, re-intergrate the module '$abc9' - by first recovering ABC9 boxes, and then stitching in the remaining primary - inputs and outputs. -\end{lstlisting} - \section{add -- add objects to the design} \label{cmd:add} \begin{lstlisting}[numbers=left,frame=single] @@ -439,17 +189,6 @@ \section{add -- add objects to the design} Like 'add -input', but also connect the signal between instances of the selected modules. - - - add {-assert|-assume|-live|-fair|-cover} [-if ] - -Add an $assert, $assume, etc. cell connected to a wire named name1, with its -enable signal optionally connected to a wire named name2 (default: 1'b1). - - - add -mod - -Add module[s] with the specified name[s]. \end{lstlisting} \section{aigmap -- map logic to and-inverter-graph circuit} @@ -462,10 +201,6 @@ \section{aigmap -- map logic to and-inverter-graph circuit} -nand Enable creation of $_NAND_ cells - - -select - Overwrite replaced cells in the current selection with new $_AND_, - $_NOT_, and $_NAND_, cells \end{lstlisting} \section{alumacc -- extract ALU and MACC cells} @@ -477,23 +212,7 @@ \section{alumacc -- extract ALU and MACC cells} and $macc cells. \end{lstlisting} -\section{anlogic\_eqn -- Anlogic: Calculate equations for luts} -\label{cmd:anlogic_eqn} -\begin{lstlisting}[numbers=left,frame=single] - anlogic_eqn [selection] - -Calculate equations for luts since bitstream generator depends on it. -\end{lstlisting} - -\section{anlogic\_fixcarry -- Anlogic: fix carry chain} -\label{cmd:anlogic_fixcarry} -\begin{lstlisting}[numbers=left,frame=single] - anlogic_fixcarry [options] [selection] - -Add Anlogic adders to fix carry chain if needed. -\end{lstlisting} - -\section{assertpmux -- adds asserts for parallel muxes} +\section{assertpmux -- convert internal signals to module ports} \label{cmd:assertpmux} \begin{lstlisting}[numbers=left,frame=single] assertpmux [options] [selection] @@ -506,8 +225,8 @@ \section{assertpmux -- adds asserts for parallel muxes} -always usually the $pmux condition is only checked when the $pmux output - is used by the mux tree it drives. this option will deactivate this - additional constraint and check the $pmux condition always. + is used be the mux tree it drives. this option will deactivate this + additional constrained and check the $pmux condition always. \end{lstlisting} \section{async2sync -- convert async FF inputs to sync circuits} @@ -523,7 +242,7 @@ \section{async2sync -- convert async FF inputs to sync circuits} reset value in the next cycle regardless of the data-in value at the time of the clock edge. -Currently only $adff, $dffsr, and $dlatch cells are supported by this pass. +Currently only $adff cells are supported by this pass. \end{lstlisting} \section{attrmap -- renaming attributes} @@ -531,7 +250,7 @@ \section{attrmap -- renaming attributes} \begin{lstlisting}[numbers=left,frame=single] attrmap [options] [selection] -This command renames attributes and/or maps key/value pairs to +This command renames attributes and/or mapps key/value pairs to other key/value pairs. -tocase @@ -588,16 +307,7 @@ \section{attrmvcp -- move or copy attributes from wires to driving cells} multiple times. \end{lstlisting} -\section{autoname -- automatically assign names to objects} -\label{cmd:autoname} -\begin{lstlisting}[numbers=left,frame=single] - autoname [selection] - -Assign auto-generated public names to objects with private names (the ones -with $-prefix). -\end{lstlisting} - -\section{blackbox -- convert modules into blackbox modules} +\section{blackbox -- change type of cells in the design} \label{cmd:blackbox} \begin{lstlisting}[numbers=left,frame=single] blackbox [options] [selection] @@ -606,58 +316,6 @@ \section{blackbox -- convert modules into blackbox modules} module attribute). \end{lstlisting} -\section{bugpoint -- minimize testcases} -\label{cmd:bugpoint} -\begin{lstlisting}[numbers=left,frame=single] - bugpoint [options] - -This command minimizes testcases that crash Yosys. It removes an arbitrary part -of the design and recursively invokes Yosys with a given script, repeating these -steps while it can find a smaller design that still causes a crash. Once this -command finishes, it replaces the current design with the smallest testcase it -was able to produce. - -It is possible to specify the kinds of design part that will be removed. If none -are specified, all parts of design will be removed. - - -yosys - use this Yosys binary. if not specified, `yosys` is used. - - -script - use this script to crash Yosys. required. - - -grep - only consider crashes that place this string in the log file. - - -fast - run `proc_clean; clean -purge` after each minimization step. converges - faster, but produces larger testcases, and may fail to produce any - testcase at all if the crash is related to dangling wires. - - -clean - run `proc_clean; clean -purge` before checking testcase and after - finishing. produces smaller and more useful testcases, but may fail to - produce any testcase at all if the crash is related to dangling wires. - - -modules - try to remove modules. - - -ports - try to remove module ports. - - -cells - try to remove cells. - - -connections - try to reconnect ports to 'x. - - -assigns - try to remove process assigns from cases. - - -updates - try to remove process updates from syncs. -\end{lstlisting} - \section{cd -- a shortcut for 'select -module '} \label{cmd:cd} \begin{lstlisting}[numbers=left,frame=single] @@ -696,24 +354,14 @@ \section{check -- check for obvious problems in the design} - used wires that do not have a driver -Options: - - -noinit - Also check for wires which have the 'init' attribute set. +When called with -noinit then this command also checks for wires which have +the 'init' attribute set. - -initdrv - Also check for wires that have the 'init' attribute set and are not - driven by an FF cell type. +When called with -initdrv then this command also checks for wires which have +the 'init' attribute set and aren't driven by a FF cell type. - -mapped - Also check for internal cells that have not been mapped to cells of the - target architecture. - - -allow-tbuf - Modify the -mapped behavior to still allow $_TBUF_ cells. - - -assert - Produce a runtime error if any problems are found in the current design. +When called with -assert then the command will produce an error if any +problems are found in the current design. \end{lstlisting} \section{chformal -- change formal constraints of the design} @@ -722,7 +370,7 @@ \section{chformal -- change formal constraints of the design} chformal [types] [mode] [options] [selection] Make changes to the formal constraints of the design. The [types] options -the type of constraint to operate on. If none of the following options are given, +the type of constraint to operate on. If none of the folling options is given, the command will operate on all constraint types: -assert $assert cells, representing assert(...) constraints @@ -749,7 +397,7 @@ \section{chformal -- change formal constraints of the design} -assume2assert -live2fair -fair2live - change the roles of cells as indicated. these options can be combined + change the roles of cells as indicated. this options can be combined \end{lstlisting} \section{chparam -- re-evaluate modules with new parameters} @@ -804,32 +452,6 @@ \section{clk2fflogic -- convert clocked FFs to generic \$ff cells} multiple clocks. \end{lstlisting} -\section{clkbufmap -- insert global buffers on clock networks} -\label{cmd:clkbufmap} -\begin{lstlisting}[numbers=left,frame=single] - clkbufmap [options] [selection] - -Inserts global buffers between nets connected to clock inputs and their drivers. - -In the absence of any selection, all wires without the 'clkbuf_inhibit' -attribute will be considered for global buffer insertion. -Alternatively, to consider all wires without the 'buffer_type' attribute set to -'none' or 'bufr' one would specify: - 'w:* a:buffer_type=none a:buffer_type=bufr %u %d' -as the selection. - - -buf : - Specifies the cell type to use for the global buffers - and its port names. The first port will be connected to - the clock network sinks, and the second will be connected - to the actual clock source. This option is required. - - -inpad : - If specified, a PAD cell of the given type is inserted on - clock nets that are also top module's inputs (in addition - to the global buffer). -\end{lstlisting} - \section{connect -- create or remove connections} \label{cmd:connect} \begin{lstlisting}[numbers=left,frame=single] @@ -861,50 +483,6 @@ \section{connect -- create or remove connections} This command does not operate on module with processes. \end{lstlisting} -\section{connect\_rpc -- connect to RPC frontend} -\label{cmd:connect_rpc} -\begin{lstlisting}[numbers=left,frame=single] - connect_rpc -exec [args...] - connect_rpc -path - -Load modules using an out-of-process frontend. - - -exec [args...] - run with arguments [args...]. send requests on stdin, read - responses from stdout. - - -path - connect to Unix domain socket at . (Unix) - connect to bidirectional byte-type named pipe at . (Windows) - -A simple JSON-based, newline-delimited protocol is used for communicating with -the frontend. Yosys requests data from the frontend by sending exactly 1 line -of JSON. Frontend responds with data or error message by replying with exactly -1 line of JSON as well. - - -> {"method": "modules"} - <- {"modules": ["", ...]} - <- {"error": ""} - request for the list of modules that can be derived by this frontend. - the 'hierarchy' command will call back into this frontend if a cell - with type is instantiated in the design. - - -> {"method": "derive", "module": ", "parameters": { - "": {"type": "[unsigned|signed|string|real]", - "value": ""}, ...}} - <- {"frontend": "[ilang|verilog|...]","source": ""}} - <- {"error": ""} - request for the module to be derived for a specific set of - parameters. starts with \ for named parameters, and with $ - for unnamed parameters, which are numbered starting at 1. - for integer parameters is always specified as a binary string of unlimited - precision. the returned by the frontend is hygienically parsed - by a built-in Yosys , allowing the RPC frontend to return any - convenient representation of the module. the derived module is cached, - so the response should be the same whenever the same set of parameters - is provided. -\end{lstlisting} - \section{connwrappers -- match width of input-output port pairs} \label{cmd:connwrappers} \begin{lstlisting}[numbers=left,frame=single] @@ -926,14 +504,6 @@ \section{connwrappers -- match width of input-output port pairs} The options -signed, -unsigned, and -port can be specified multiple times. \end{lstlisting} -\section{coolrunner2\_fixup -- insert necessary buffer cells for CoolRunner-II architecture} -\label{cmd:coolrunner2_fixup} -\begin{lstlisting}[numbers=left,frame=single] - coolrunner2_fixup [options] [selection] - -Insert necessary buffer cells for CoolRunner-II architecture. -\end{lstlisting} - \section{coolrunner2\_sop -- break \$sop cells into ANDTERM/ORTERM cells} \label{cmd:coolrunner2_sop} \begin{lstlisting}[numbers=left,frame=single] @@ -998,26 +568,6 @@ \section{cover -- print code coverage counters} Coverage counters are only available in Yosys for Linux. \end{lstlisting} -\section{cutpoint -- adds formal cut points to the design} -\label{cmd:cutpoint} -\begin{lstlisting}[numbers=left,frame=single] - cutpoint [options] [selection] - -This command adds formal cut points to the design. - - -undef - set cupoint nets to undef (x). the default behavior is to create a - $anyseq cell and drive the cutpoint net from that -\end{lstlisting} - -\section{debug -- run command with debug log messages enabled} -\label{cmd:debug} -\begin{lstlisting}[numbers=left,frame=single] - debug cmd - -Execute the specified command with debug log messages enabled -\end{lstlisting} - \section{delete -- delete objects in the design} \label{cmd:delete} \begin{lstlisting}[numbers=left,frame=single] @@ -1064,11 +614,6 @@ \section{design -- save, restore and reset current design} Push the current design to the stack and then clear the current design. - design -push-copy - -Push the current design to the stack without clearing the current design. - - design -pop Reset the current design and pop the last design from the stack. @@ -1104,14 +649,6 @@ \section{design -- save, restore and reset current design} between calls to 'read_verilog'. This command resets this memory. \end{lstlisting} -\section{determine\_init -- Determine the init value of cells} -\label{cmd:determine_init} -\begin{lstlisting}[numbers=left,frame=single] - determine_init [selection] - -Determine the init value of cells that doesn't allow unknown init value. -\end{lstlisting} - \section{dff2dffe -- transform \$dff cells to \$dffe cells} \label{cmd:dff2dffe} \begin{lstlisting}[numbers=left,frame=single] @@ -1123,11 +660,7 @@ \section{dff2dffe -- transform \$dff cells to \$dffe cells} -unmap operate in the opposite direction: replace $dffe cells with combinations - of $dff and $mux cells. the options below are ignored in unmap mode. - - -unmap-mince N - Same as -unmap but only unmap $dffe where the clock enable port - signal is used by less $dffe than the specified number + of $dff and $mux cells. the options below are ignore in unmap mode. -direct map directly to external gate type. can @@ -1153,10 +686,6 @@ \section{dff2dffs -- process sync set/reset with SR over CE priority} Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before dff2dffe for SR over CE priority. - - -match-init - Disallow merging synchronous set/reset that has polarity opposite of the - output wire's init attribute (if any). \end{lstlisting} \section{dffinit -- set INIT param on FF cells} @@ -1175,16 +704,6 @@ \section{dffinit -- set INIT param on FF cells} use the string values "high" and "low" to represent a single-bit initial value of 1 or 0. (multi-bit values are not supported in this mode.) - - -strinit - use string values in the command line to represent a single-bit - initial value of 1 or 0. (multi-bit values are not supported in this - mode.) - - -noreinit - fail if the FF cell has already a defined initial value set in other - passes and the initial value of the net it drives is not equal to - the already defined initial value. \end{lstlisting} \section{dfflibmap -- technology mapping of flip-flops} @@ -1203,6 +722,15 @@ \section{dfflibmap -- technology mapping of flip-flops} liberty file. \end{lstlisting} +\section{dffsr2dff -- convert DFFSR cells to simpler FF cell types} +\label{cmd:dffsr2dff} +\begin{lstlisting}[numbers=left,frame=single] + dffsr2dff [options] [selection] + +This pass converts DFFSR cells ($dffsr, $_DFFSR_???_) and ADFF cells ($adff, +$_DFF_???_) to simpler FF cell types when any of the set/reset inputs is unused. +\end{lstlisting} + \section{dump -- print parts of the design in ilang format} \label{cmd:dump} \begin{lstlisting}[numbers=left,frame=single] @@ -1238,29 +766,6 @@ \section{echo -- turning echoing back of commands on and off} Do not print all commands to log before executing them. (default) \end{lstlisting} -\section{ecp5\_ffinit -- ECP5: handle FF init values} -\label{cmd:ecp5_ffinit} -\begin{lstlisting}[numbers=left,frame=single] - ecp5_ffinit [options] [selection] - -Remove init values for FF output signals when equal to reset value. -If reset is not used, set the reset value to the init value, otherwise -unmap out the reset (if not an async reset). -\end{lstlisting} - -\section{ecp5\_gsr -- ECP5: handle GSR} -\label{cmd:ecp5_gsr} -\begin{lstlisting}[numbers=left,frame=single] - ecp5_gsr [options] [selection] - -Trim active low async resets connected to GSR and resolve GSR parameter, -if a GSR or SGSR primitive is used in the design. - -If any cell has the GSR parameter set to "AUTO", this will be resolved -to "ENABLED" if a GSR primitive is present and the (* nogsr *) attribute -is not set, otherwise it will be resolved to "DISABLED". -\end{lstlisting} - \section{edgetypes -- list all types of edges in selection} \label{cmd:edgetypes} \begin{lstlisting}[numbers=left,frame=single] @@ -1270,22 +775,6 @@ \section{edgetypes -- list all types of edges in selection} is a 4-tuple of source and sink cell type and port name. \end{lstlisting} -\section{efinix\_fixcarry -- Efinix: fix carry chain} -\label{cmd:efinix_fixcarry} -\begin{lstlisting}[numbers=left,frame=single] - efinix_fixcarry [options] [selection] - -Add Efinix adders to fix carry chain if needed. -\end{lstlisting} - -\section{efinix\_gbuf -- Efinix: insert global clock buffers} -\label{cmd:efinix_gbuf} -\begin{lstlisting}[numbers=left,frame=single] - efinix_gbuf [options] [selection] - -Add Efinix global clock buffers to top module as needed. -\end{lstlisting} - \section{equiv\_add -- add a \$equiv cell} \label{cmd:equiv_add} \begin{lstlisting}[numbers=left,frame=single] @@ -1383,65 +872,6 @@ \section{equiv\_miter -- extract miter from equiv circuit} Create compare logic that handles undefs correctly \end{lstlisting} -\section{equiv\_opt -- prove equivalence for optimized circuit} -\label{cmd:equiv_opt} -\begin{lstlisting}[numbers=left,frame=single] - equiv_opt [options] [command] - -This command uses temporal induction to check circuit equivalence before and -after an optimization pass. - - -run : - only run the commands between the labels (see below). an empty - from label is synonymous to the start of the command list, and empty to - label is synonymous to the end of the command list. - - -map - expand the modules in this file before proving equivalence. this is - useful for handling architecture-specific primitives. - - -blacklist - Do not match cells or signals that match the names in the file - (passed to equiv_make). - - -assert - produce an error if the circuits are not equivalent. - - -multiclock - run clk2fflogic before equivalence checking. - - -async2sync - run async2sync before equivalence checking. - - -undef - enable modelling of undef states during equiv_induct. - -The following commands are executed by this verification command: - - run_pass: - hierarchy -auto-top - design -save preopt - [command] - design -stash postopt - - prepare: - design -copy-from preopt -as gold A:top - design -copy-from postopt -as gate A:top - - techmap: (only with -map) - techmap -wb -D EQUIV -autoproc -map ... - - prove: - clk2fflogic (only with -multiclock) - async2sync (only with -async2sync) - equiv_make -blacklist ... gold gate equiv - equiv_induct [-undef] equiv - equiv_status [-assert] equiv - - restore: - design -load preopt -\end{lstlisting} - \section{equiv\_purge -- purge equivalence checking module} \label{cmd:equiv_purge} \begin{lstlisting}[numbers=left,frame=single] @@ -1554,37 +984,6 @@ \section{eval -- evaluate the circuit given an input} then all output ports of the current module are used. \end{lstlisting} -\section{exec -- execute commands in the operating system shell} -\label{cmd:exec} -\begin{lstlisting}[numbers=left,frame=single] - exec [options] -- [command] - -Execute a command in the operating system shell. All supplied arguments are -concatenated and passed as a command to popen(3). Whitespace is not guaranteed -to be preserved, even if quoted. stdin and stderr are not connected, while stdout is -logged unless the "-q" option is specified. - - - -q - Suppress stdout and stderr from subprocess - - -expect-return - Generate an error if popen() does not return specified value. - May only be specified once; the final specified value is controlling - if specified multiple times. - - -expect-stdout - Generate an error if the specified regex does not match any line - in subprocess's stdout. May be specified multiple times. - - -not-expect-stdout - Generate an error if the specified regex matches any line - in subprocess's stdout. May be specified multiple times. - - - Example: exec -q -expect-return 0 -- echo "bananapie" | grep "nana" -\end{lstlisting} - \section{expose -- convert internal signals to module ports} \label{cmd:expose} \begin{lstlisting}[numbers=left,frame=single] @@ -1718,16 +1117,7 @@ \section{extract\_counter -- Extract GreenPak4 counter cells} to the actual target cells. -maxwidth N - Only extract counters up to N bits wide (default 64) - - -minwidth N - Only extract counters at least N bits wide (default 2) - - -allow_arst yes|no - Allow counters to have async reset (default yes) - - -dir up|down|both - Look for up-counters, down-counters, or both (default down) + Only extract counters up to N bits wide -pout X,Y,... Only allow parallel output from the counter to the listed cell types @@ -1775,30 +1165,10 @@ \section{extract\_reduce -- converts gate chains into \$reduce\_* cells} cell will remain, driving its original loads. \end{lstlisting} -\section{extractinv -- extract explicit inverter cells for invertible cell pins} -\label{cmd:extractinv} -\begin{lstlisting}[numbers=left,frame=single] - extractinv [options] [selection] - -Searches the design for all cells with invertible pins controlled by a cell -parameter (eg. IS_CLK_INVERTED on many Xilinx cells) and removes the parameter. -If the parameter was set to 1, inserts an explicit inverter cell in front of -the pin instead. Normally used for output to ISE, which does not support the -inversion parameters. - -To mark a cell port as invertible, use (* invertible_pin = "param_name" *) -on the wire in the blackbox module. The parameter value should have -the same width as the port, and will be effectively XORed with it. - - -inv : - Specifies the cell type to use for the inverters and its port names. - This option is required. -\end{lstlisting} - \section{flatten -- flatten design} \label{cmd:flatten} \begin{lstlisting}[numbers=left,frame=single] - flatten [options] [selection] + flatten [selection] This pass flattens the design by replacing cells by their implementation. This pass is very similar to the 'techmap' pass. The only difference is that this @@ -1806,105 +1176,6 @@ \section{flatten -- flatten design} Cells and/or modules with the 'keep_hierarchy' attribute set will not be flattened by this command. - - -wb - Ignore the 'whitebox' attribute on cell implementations. -\end{lstlisting} - -\section{flowmap -- pack LUTs with FlowMap} -\label{cmd:flowmap} -\begin{lstlisting}[numbers=left,frame=single] - flowmap [options] [selection] - -This pass uses the FlowMap technology mapping algorithm to pack logic gates -into k-LUTs with optimal depth. It allows mapping any circuit elements that can -be evaluated with the `eval` pass, including cells with multiple output ports -and multi-bit input and output ports. - - -maxlut k - perform technology mapping for a k-LUT architecture. if not specified, - defaults to 3. - - -minlut n - only produce n-input or larger LUTs. if not specified, defaults to 1. - - -cells [,,...] - map specified cells. if not specified, maps $_NOT_, $_AND_, $_OR_, - $_XOR_ and $_MUX_, which are the outputs of the `simplemap` pass. - - -relax - perform depth relaxation and area minimization. - - -r-alpha n, -r-beta n, -r-gamma n - parameters of depth relaxation heuristic potential function. - if not specified, alpha=8, beta=2, gamma=1. - - -optarea n - optimize for area by trading off at most n logic levels for fewer LUTs. - n may be zero, to optimize for area without increasing depth. - implies -relax. - - -debug - dump intermediate graphs. - - -debug-relax - explain decisions performed during depth relaxation. -\end{lstlisting} - -\section{fmcombine -- combine two instances of a cell into one} -\label{cmd:fmcombine} -\begin{lstlisting}[numbers=left,frame=single] - fmcombine [options] module_name gold_cell gate_cell - -This pass takes two cells, which are instances of the same module, and replaces -them with one instance of a special 'combined' module, that effectively -contains two copies of the original module, plus some formal properties. - -This is useful for formal test benches that check what differences in behavior -a slight difference in input causes in a module. - - -initeq - Insert assumptions that initially all FFs in both circuits have the - same initial values. - - -anyeq - Do not duplicate $anyseq/$anyconst cells. - - -fwd - Insert forward hint assumptions into the combined module. - - -bwd - Insert backward hint assumptions into the combined module. - (Backward hints are logically equivalend to fordward hits, but - some solvers are faster with bwd hints, or even both -bwd and -fwd.) - - -nop - Don't insert hint assumptions into the combined module. - (This should not provide any speedup over the original design, but - strangely sometimes it does.) - -If none of -fwd, -bwd, and -nop is given, then -fwd is used as default. -\end{lstlisting} - -\section{fminit -- set init values/sequences for formal} -\label{cmd:fminit} -\begin{lstlisting}[numbers=left,frame=single] - fminit [options] - -This pass creates init constraints (for example for reset sequences) in a formal -model. - - -seq - Set sequence using comma-separated list of values, use 'z for - unconstrained bits. The last value is used for the remainder of the - trace. - - -set - Add constant value constraint - - -posedge - -negedge - Set clock for init sequences \end{lstlisting} \section{freduce -- perform functional reduction} @@ -2122,16 +1393,15 @@ \section{hierarchy -- check, expand and clean up design hierarchy} In parametric designs, a module might exists in several variations with different parameter values. This pass looks at all modules in the current design an re-runs the language frontends for the parametric modules as -needed. It also resolves assignments to wired logic data types (wand/wor), -resolves positional module parameters, unroll array instances, and more. +needed. -check also check the design hierarchy. this generates an error when an unknown module is used as cell type. -simcheck - like -check, but also throw an error if blackbox modules are - instantiated, and throw an error if the design has no top module. + like -check, but also thow an error if blackbox modules are + instantiated, and throw an error if the design has no top module -purge_lib by default the hierarchy command will not remove library (blackbox) @@ -2144,23 +1414,20 @@ \section{hierarchy -- check, expand and clean up design hierarchy} -keep_positionals per default this pass also converts positional arguments in cells - to arguments using port names. This option disables this behavior. + to arguments using port names. this option disables this behavior. -keep_portwidths per default this pass adjusts the port width on cells that are - module instances when the width does not match the module port. This + module instances when the width does not match the module port. this option disables this behavior. - -nodefaults - do not resolve input port default values - -nokeep_asserts per default this pass sets the "keep" attribute on all modules - that directly or indirectly contain one or more formal properties. - This option disables this behavior. + that directly or indirectly contain one or more $assert cells. this + option disables this behavior. -top - use the specified top module to build the design hierarchy. Modules + use the specified top module to built a design hierarchy. modules outside this tree (unused modules) are removed. when the -top option is used, the 'top' attribute will be set on the @@ -2170,12 +1437,6 @@ \section{hierarchy -- check, expand and clean up design hierarchy} -auto-top automatically determine the top of the design hierarchy and mark it. - -chparam name value - elaborate the top module using this parameter value. Modules on which - this parameter does not exist may cause a warning message to be output. - This option can be specified multiple times to override multiple - parameters. String values must be passed in double quotes ("). - In -generate mode this pass generates blackbox modules for the given cell types (wildcards supported). For this the design is searched for cells that match the given types and then the given port declarations are used to @@ -2222,33 +1483,6 @@ \section{history -- show last interactive commands} from executed scripts. \end{lstlisting} -\section{ice40\_braminit -- iCE40: perform SB\_RAM40\_4K initialization from file} -\label{cmd:ice40_braminit} -\begin{lstlisting}[numbers=left,frame=single] - ice40_braminit - -This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE -parameter and converts it into the required INIT_x attributes -\end{lstlisting} - -\section{ice40\_dsp -- iCE40: map multipliers} -\label{cmd:ice40_dsp} -\begin{lstlisting}[numbers=left,frame=single] - ice40_dsp [options] [selection] - -Map multipliers ($mul/SB_MAC16) and multiply-accumulate ($mul/SB_MAC16 + $add) -cells into iCE40 DSP resources. -Currently, only the 16x16 multiply mode is supported and not the 2 x 8x8 mode. - -Pack input registers (A, B, {C,D}; with optional hold), pipeline registers -({F,J,K,G}, H), output registers (O -- full 32-bits or lower 16-bits only; with -optional hold), and post-adder into into the SB_MAC16 resource. - -Multiply-accumulate operations using the post-adder with feedback on the {C,D} -input will be folded into the DSP. In this scenario only, resetting the -the accumulator to an arbitrary value can be inferred to use the {C,D} input. -\end{lstlisting} - \section{ice40\_ffinit -- iCE40: handle FF init values} \label{cmd:ice40_ffinit} \begin{lstlisting}[numbers=left,frame=single] @@ -2280,24 +1514,9 @@ \section{ice40\_opt -- iCE40: perform simple optimizations} opt_rmdff opt_clean while -\end{lstlisting} - -\section{ice40\_wrapcarry -- iCE40: wrap carries} -\label{cmd:ice40_wrapcarry} -\begin{lstlisting}[numbers=left,frame=single] - ice40_wrapcarry [selection] - -Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUT4s, -into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology -mapping. -Attributes on both cells will have their names prefixed with 'SB_CARRY.' or -'SB_LUT4.' and attached to the wrapping cell. -A (* keep *) attribute on either cell will be logically OR-ed together. - - -unwrap - unwrap $__ICE40_CARRY_WRAPPER cells back into SB_CARRYs and SB_LUT4s, - including restoring their attributes. +When called with the option -unlut, this command will transform all already +mapped SB_LUT4 cells back to logic. \end{lstlisting} \section{insbuf -- insert buffer cells for connected wires} @@ -2342,11 +1561,6 @@ \section{iopadmap -- technology mapping of i/o pads (or buffers)} of the tristate driver and the 2nd portname is the internal output buffering the external signal. - -ignore [:]* - Skips mapping inputs/outputs that are already connected to given - ports of the given cell. Can be used multiple times. This is in - addition to the cells specified as mapping targets. - -widthparam Use the specified parameter name to set the port width. @@ -2374,10 +1588,6 @@ \section{json -- write design in JSON format} -aig also include AIG models for the different gate types - -compat-int - emit 32-bit or smaller fully-defined parameter values directly - as JSON numbers (for compatibility with old parsers) - See 'help write_json' for a description of the JSON format used. \end{lstlisting} @@ -2405,44 +1615,6 @@ \section{log -- print text and log files} do not append a newline \end{lstlisting} -\section{logger -- set logger properties} -\label{cmd:logger} -\begin{lstlisting}[numbers=left,frame=single] - logger [options] - -This command sets global logger properties, also available using command line -options. - - -[no]time - enable/disable display of timestamp in log output. - - -[no]stderr - enable/disable logging errors to stderr. - - -warn regex - print a warning for all log messages matching the regex. - - -nowarn regex - if a warning message matches the regex, it is printed as regular - message instead. - - -werror regex - if a warning message matches the regex, it is printed as error - message instead and the tool terminates with a nonzero return code. - - -[no]debug - globally enable/disable debug log messages. - - -experimental - do not print warnings for the specified experimental feature - - -expect - expect log,warning or error to appear. In case of error return code is 0. - - -expect-no-warnings - gives error in case there is at least one warning that is not expected. -\end{lstlisting} - \section{ls -- list modules or objects in modules} \label{cmd:ls} \begin{lstlisting}[numbers=left,frame=single] @@ -2489,7 +1661,6 @@ \section{memory -- translate memories to basic cells} This pass calls all the other memory_* passes in a useful order: - opt_mem memory_dff [-nordff] (-memx implies -nordff) opt_clean memory_share @@ -2512,13 +1683,8 @@ \section{memory\_bram -- map memories to block rams} The given rules file describes the available resources and how they should be used. -The rules file contains configuration options, a set of block ram description -and a sequence of match rules. - -The option 'attr_icase' configures how attribute values are matched. The value 0 -means case-sensitive, 1 means case-insensitive. - -A block ram description looks like this: +The rules file contains a set of block ram description and a sequence of match +rules. A block ram description looks like this: bram RAMB1024X32 # name of BRAM cell init 1 # set to '1' if BRAM can be initialized @@ -2579,13 +1745,6 @@ \section{memory\_bram -- map memories to block rams} dcells ....... number of cells in 'data-direction' cells ........ total number of cells (acells*dcells*dups) -A match containing the command 'attribute' followed by a list of space -separated 'name[=string_value]' values requires that the memory contains any -one of the given attribute name and string values (where specified), or name -and integer 1 value (if no string_value given, since Verilog will interpret -'(* attr *)' as '(* attr=1 *)'). -A name prefixed with '!' indicates that the attribute must not exist. - The interface for the created bram instances is derived from the bram description. Use 'techmap' to convert the created bram instances into instances of the actual bram cells of your target architecture. @@ -2629,22 +1788,10 @@ \section{memory\_dff -- merge input/output DFFs into memories} \section{memory\_map -- translate multiport memories to basic cells} \label{cmd:memory_map} \begin{lstlisting}[numbers=left,frame=single] - memory_map [options] [selection] + memory_map [selection] This pass converts multiport memory cells as generated by the memory_collect pass to word-wide DFFs and address decoders. - - -attr ! - do not map memories that have attribute set. - - -attr [=] - for memories that have attribute set, only map them if its value - is a string (if specified), or an integer 1 (otherwise). if this - option is specified multiple times, map the memory if the attribute is - to any of the values. - - -iattr - for -attr, ignore case of . \end{lstlisting} \section{memory\_memx -- emulate vlog sim behavior for mem ports} @@ -2725,7 +1872,7 @@ \section{miter -- automatically create a miter circuit} also create an 'assert' cell that checks if trigger is always low. -flatten - call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit. + call 'flatten; opt_expr -keepdc -undriven;;' on the miter circuit. miter -assert [options] module [miter_name] @@ -2739,70 +1886,7 @@ \section{miter -- automatically create a miter circuit} keep module output ports. -flatten - call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit. -\end{lstlisting} - -\section{mutate -- generate or apply design mutations} -\label{cmd:mutate} -\begin{lstlisting}[numbers=left,frame=single] - mutate -list N [options] [selection] - -Create a list of N mutations using an even sampling. - - -o filename - Write list to this file instead of console output - - -s filename - Write a list of all src tags found in the design to the specified file - - -seed N - RNG seed for selecting mutations - - -none - Include a "none" mutation in the output - - -ctrl name width value - Add -ctrl options to the output. Use 'value' for first mutation, then - simply count up from there. - - -mode name - -module name - -cell name - -port name - -portbit int - -ctrlbit int - -wire name - -wirebit int - -src string - Filter list of mutation candidates to those matching - the given parameters. - - -cfg option int - Set a configuration option. Options available: - weight_pq_w weight_pq_b weight_pq_c weight_pq_s - weight_pq_mw weight_pq_mb weight_pq_mc weight_pq_ms - weight_cover pick_cover_prcnt - - - mutate -mode MODE [options] - -Apply the given mutation. - - -ctrl name width value - Add a control signal with the given name and width. The mutation is - activated if the control signal equals the given value. - - -module name - -cell name - -port name - -portbit int - -ctrlbit int - Mutation parameters, as generated by 'mutate -list N'. - - -wire name - -wirebit int - -src string - Ignored. (They are generated by -list for documentation purposes.) + call 'flatten; opt_expr -keepdc -undriven;;' on the miter circuit. \end{lstlisting} \section{muxcover -- cover trees of MUX cells with wider MUXes} @@ -2812,43 +1896,14 @@ \section{muxcover -- cover trees of MUX cells with wider MUXes} Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells - -mux4[=cost], -mux8[=cost], -mux16[=cost] - Cover $_MUX_ trees using the specified types of MUXes (with optional - integer costs). If none of these options are given, the effect is the - same as if all of them are. - Default costs: $_MUX4_ = 220, $_MUX8_ = 460, - $_MUX16_ = 940 - - -mux2=cost - Use the specified cost for $_MUX_ cells when making covering decisions. - Default cost: $_MUX_ = 100 - - -dmux=cost - Use the specified cost for $_MUX_ cells used in decoders. - Default cost: 90 + -mux4, -mux8, -mux16 + Use the specified types of MUXes. If none of those options are used, + the effect is the same as if all of them where used. -nodecode Do not insert decoder logic. This reduces the number of possible substitutions, but guarantees that the resulting circuit is not less efficient than the original circuit. - - -nopartial - Do not consider mappings that use $_MUX_ to select from less - than different signals. -\end{lstlisting} - -\section{muxpack -- \$mux/\$pmux cascades to \$pmux} -\label{cmd:muxpack} -\begin{lstlisting}[numbers=left,frame=single] - muxpack [selection] - -This pass converts cascaded chains of $pmux cells (e.g. those create from case -constructs) and $mux cells (e.g. those created by if-else constructs) into -$pmux cells. - -This optimisation is conservative --- it will only pack $mux or $pmux cells -whose select lines are driven by '$eq' cells with other such cells if it can be -certain that their select inputs are mutually exclusive. \end{lstlisting} \section{nlutmap -- map to LUTs of different sizes} @@ -2870,17 +1925,6 @@ \section{nlutmap -- map to LUTs of different sizes} to generic logic gates ($_AND_, etc.). \end{lstlisting} -\section{onehot -- optimize \$eq cells for onehot signals} -\label{cmd:onehot} -\begin{lstlisting}[numbers=left,frame=single] - onehot [options] [selection] - -This pass optimizes $eq cells that compare one-hot signals against constants - - -v, -vv - verbose output -\end{lstlisting} - \section{opt -- perform simple optimizations} \label{cmd:opt} \begin{lstlisting}[numbers=left,frame=single] @@ -2897,8 +1941,7 @@ \section{opt -- perform simple optimizations} opt_muxtree opt_reduce [-fine] [-full] opt_merge [-share_all] - opt_share (-full only) - opt_rmdff [-keepdc] [-sat] + opt_rmdff [-keepdc] opt_clean [-purge] opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc] while @@ -2908,7 +1951,7 @@ \section{opt -- perform simple optimizations} do opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc] opt_merge [-share_all] - opt_rmdff [-keepdc] [-sat] + opt_rmdff [-keepdc] opt_clean [-purge] while @@ -2947,7 +1990,7 @@ \section{opt\_expr -- perform const folding and simple expression rewriting} opt_expr [options] [selection] This pass performs const folding on internal cell types with constant inputs. -It also performs some simple expression rewriting. +It also performs some simple expression rewritring. -mux_undef remove 'undef' inputs from $mux, $pmux and $_MUX_ cells @@ -2974,47 +2017,6 @@ \section{opt\_expr -- perform const folding and simple expression rewriting} replaced by 'a'. the -keepdc option disables all such optimizations. \end{lstlisting} -\section{opt\_lut -- optimize LUT cells} -\label{cmd:opt_lut} -\begin{lstlisting}[numbers=left,frame=single] - opt_lut [options] [selection] - -This pass combines cascaded $lut cells with unused inputs. - - -dlogic :=[:=...] - preserve connections to dedicated logic cell that has ports - connected to LUT inputs . this includes - the case where both LUT and dedicated logic input are connected to - the same constant. - - -limit N - only perform the first N combines, then stop. useful for debugging. -\end{lstlisting} - -\section{opt\_lut\_ins -- discard unused LUT inputs} -\label{cmd:opt_lut_ins} -\begin{lstlisting}[numbers=left,frame=single] - opt_lut_ins [options] [selection] - -This pass removes unused inputs from LUT cells (that is, inputs that can not -influence the output signal given this LUT's value). While such LUTs cannot -be directly emitted by ABC, they can be a result of various post-ABC -transformations, such as mapping wide LUTs (not all sub-LUTs will use the -full set of inputs) or optimizations such as xilinx_dffopt. - - -tech - Instead of generic $lut cells, operate on LUT cells specific - to the given technology. Valid values are: xilinx, ecp5, gowin. -\end{lstlisting} - -\section{opt\_mem -- optimize memories} -\label{cmd:opt_mem} -\begin{lstlisting}[numbers=left,frame=single] - opt_mem [options] [selection] - -This pass performs various optimizations on memories in the design. -\end{lstlisting} - \section{opt\_merge -- consolidate identical cells} \label{cmd:opt_merge} \begin{lstlisting}[numbers=left,frame=single] @@ -3065,65 +2067,10 @@ \section{opt\_reduce -- simplify large MUXes and AND/OR gates} \section{opt\_rmdff -- remove DFFs with constant inputs} \label{cmd:opt_rmdff} \begin{lstlisting}[numbers=left,frame=single] - opt_rmdff [-keepdc] [-sat] [selection] + opt_rmdff [-keepdc] [selection] This pass identifies flip-flops with constant inputs and replaces them with a constant driver. - - -sat - additionally invoke SAT solver to detect and remove flip-flops (with - non-constant inputs) that can also be replaced with a constant driver -\end{lstlisting} - -\section{opt\_share -- merge mutually exclusive cells of the same type that share an input signal} -\label{cmd:opt_share} -\begin{lstlisting}[numbers=left,frame=single] - opt_share [selection] - -This pass identifies mutually exclusive cells of the same type that: - (a) share an input signal, - (b) drive the same $mux, $_MUX_, or $pmux multiplexing cell, - -allowing the cell to be merged and the multiplexer to be moved from -multiplexing its output to multiplexing the non-shared input signals. -\end{lstlisting} - -\section{paramap -- renaming cell parameters} -\label{cmd:paramap} -\begin{lstlisting}[numbers=left,frame=single] - paramap [options] [selection] - -This command renames cell parameters and/or maps key/value pairs to -other key/value pairs. - - -tocase - Match attribute names case-insensitively and set it to the specified - name. - - -rename - Rename attributes as specified - - -map = = - Map key/value pairs as indicated. - - -imap = = - Like -map, but use case-insensitive match for when - it is a string value. - - -remove = - Remove attributes matching this pattern. - -For example, mapping Diamond-style ECP5 "init" attributes to Yosys-style: - - paramap -tocase INIT t:LUT4 -\end{lstlisting} - -\section{peepopt -- collection of peephole optimizers} -\label{cmd:peepopt} -\begin{lstlisting}[numbers=left,frame=single] - peepopt [options] [selection] - -This pass applies a collection of peephole optimizers to the current design. \end{lstlisting} \section{plugin -- load and list loaded plugins} @@ -3143,51 +2090,12 @@ \section{plugin -- load and list loaded plugins} List loaded plugins \end{lstlisting} -\section{pmux2shiftx -- transform \$pmux cells to \$shiftx cells} -\label{cmd:pmux2shiftx} -\begin{lstlisting}[numbers=left,frame=single] - pmux2shiftx [options] [selection] - -This pass transforms $pmux cells to $shiftx cells. - - -v, -vv - verbose output - - -min_density - specifies the minimum density for the shifter - default: 50 - - -min_choices - specified the minimum number of choices for a control signal - default: 3 - - -onehot ignore|pmux|shiftx - select strategy for one-hot encoded control signals - default: pmux - - -norange - disable $sub inference for "range decoders" -\end{lstlisting} - \section{pmuxtree -- transform \$pmux cells to trees of \$mux cells} \label{cmd:pmuxtree} \begin{lstlisting}[numbers=left,frame=single] - pmuxtree [selection] + pmuxtree [options] [selection] -This pass transforms $pmux cells to trees of $mux cells. -\end{lstlisting} - -\section{portlist -- list (top-level) ports} -\label{cmd:portlist} -\begin{lstlisting}[numbers=left,frame=single] - portlist [options] [selection] - -This command lists all module ports found in the selected modules. - -If no selection is provided then it lists the ports on the top module. - - -m - print verilog blackbox module definitions instead of port lists +This pass transforms $pmux cells to a trees of $mux cells. \end{lstlisting} \section{prep -- generic synthesis script} @@ -3245,7 +2153,7 @@ \section{prep -- generic synthesis script} opt_clean check opt -keepdc - wreduce -keepdc [-memx] + wreduce [-memx] memory_dff [-nordff] memory_memx (if -memx) opt_clean @@ -3266,7 +2174,6 @@ \section{proc -- translate processes to netlists} proc_clean proc_rmdead - proc_prune proc_init proc_arst proc_mux @@ -3307,10 +2214,7 @@ \section{proc\_arst -- detect asynchronous resets} \section{proc\_clean -- remove empty parts of processes} \label{cmd:proc_clean} \begin{lstlisting}[numbers=left,frame=single] - proc_clean [options] [selection] - - -quiet - do not print any messages. + proc_clean [selection] This pass removes empty parts of processes and ultimately removes a process if it contains only empty structures. @@ -3357,15 +2261,6 @@ \section{proc\_mux -- convert decision trees to multiplexers} 'case' expressions and 'if' conditions. \end{lstlisting} -\section{proc\_prune -- remove redundant assignments} -\label{cmd:proc_prune} -\begin{lstlisting}[numbers=left,frame=single] - proc_prune [selection] - -This pass identifies assignments in processes that are always overwritten by -a later assignment to the same signal and removes them. -\end{lstlisting} - \section{proc\_rmdead -- eliminate dead trees in decision trees} \label{cmd:proc_rmdead} \begin{lstlisting}[numbers=left,frame=single] @@ -3433,45 +2328,12 @@ \section{read -- load HDL designs} read -incdir Add directory to global Verilog/SystemVerilog include directories. - - - read -verific - read -noverific - -Subsequent calls to 'read' will either use or not use Verific. Calling 'read' -with -verific will result in an error on Yosys binaries that are built without -Verific support. The default is to use Verific if it is available. -\end{lstlisting} - -\section{read\_aiger -- read AIGER file} -\label{cmd:read_aiger} -\begin{lstlisting}[numbers=left,frame=single] - read_aiger [options] [filename] - -Load module from an AIGER file into the current design. - - -module_name - name of module to be created (default: ) - - -clk_name - if specified, AIGER latches to be transformed into $_DFF_P_ cells - clocked by wire of this name. otherwise, $_FF_ cells will be used - - -map - read file with port and latch symbols - - -wideports - merge ports that match the pattern 'name[int]' into a single - multi-bit port 'name' - - -xaiger - read XAIGER extensions \end{lstlisting} \section{read\_blif -- read BLIF file} \label{cmd:read_blif} \begin{lstlisting}[numbers=left,frame=single] - read_blif [options] [filename] + read_blif [filename] Load modules from a BLIF file into the current design. @@ -3490,17 +2352,6 @@ \section{read\_ilang -- read modules from ilang file} Load modules from an ilang file to the current design. (ilang is a text representation of a design in yosys's internal format.) - - -nooverwrite - ignore re-definitions of modules. (the default behavior is to - create an error message if the existing module is not a blackbox - module, and overwrite the existing module if it is a blackbox module.) - - -overwrite - overwrite existing modules with the same name - - -lib - only create empty blackbox modules \end{lstlisting} \section{read\_json -- read JSON file} @@ -3560,24 +2411,12 @@ \section{read\_verilog -- read modules from Verilog file} enable support for SystemVerilog assertions and some Yosys extensions replace the implicit -D SYNTHESIS with -D FORMAL - -noassert - ignore assert() statements - - -noassume - ignore assume() statements - -norestrict - ignore restrict() statements + ignore restrict() assertions -assume-asserts treat all assert() statements like assume() statements - -assert-assumes - treat all assume() statements like assert() statements - - -debug - alias for -dump_ast1 -dump_ast2 -dump_vlog1 -dump_vlog2 -yydebug - -dump_ast1 dump abstract syntax tree (before simplification) @@ -3587,10 +2426,7 @@ \section{read\_verilog -- read modules from Verilog file} -no_dump_ptr do not include hex memory addresses in dump (easier to diff dumps) - -dump_vlog1 - dump ast as Verilog code (before simplification) - - -dump_vlog2 + -dump_vlog dump ast as Verilog code (after simplification) -dump_rtlil @@ -3639,21 +2475,8 @@ \section{read\_verilog -- read modules from Verilog file} -nodpi disable DPI-C support - -noblackbox - do not automatically add a (* blackbox *) attribute to an - empty module. - -lib only create empty blackbox modules. This implies -DBLACKBOX. - modules with the (* whitebox *) attribute will be preserved. - (* lib_whitebox *) will be treated like (* whitebox *). - - -nowb - delete (* whitebox *) and (* lib_whitebox *) attributes from - all modules. - - -specify - parse and import specify blocks -noopt don't perform basic optimizations (such as const folding) in the @@ -3662,9 +2485,6 @@ \section{read\_verilog -- read modules from Verilog file} -icells interpret cell types starting with '$' as internal cell types - -pwires - add a wire for each module parameter - -nooverwrite ignore re-definitions of modules. (the default behavior is to create an error message if the existing module is not a black box @@ -3717,25 +2537,6 @@ \section{rename -- rename object in the design} by this command. - - rename -output old_name new_name - -Like above, but also make the wire an output. This will fail if the object is -not a wire. - - - rename -src [selection] - -Assign names auto-generated from the src attribute to all selected wires and -cells with private names. - - - rename -wire [selection] - -Assign auto-generated names based on the wires they drive to all selected -cells with private names. Ignores cells driving privatly named wires. - - rename -enumerate [-pattern ] [selection] Assign short auto-generated names to all selected wires and cells with private @@ -3743,13 +2544,11 @@ \section{rename -- rename object in the design} The character % in the pattern is replaced with a integer number. The default pattern is '_%_'. - rename -hide [selection] Assign private names (the ones with $-prefix) to all selected wires and cells with public names. This ignores all selected ports. - rename -top new_name Rename top module. @@ -3979,61 +2778,20 @@ \section{scc -- detect strongly connected components (logic loops)} that are part of a found logic loop \end{lstlisting} -\section{scratchpad -- get/set values in the scratchpad} -\label{cmd:scratchpad} -\begin{lstlisting}[numbers=left,frame=single] - scratchpad [options] - -This pass allows to read and modify values from the scratchpad of the current -design. Options: - - -get - print the value saved in the scratchpad under the given identifier. - - -set - save the given value in the scratchpad under the given identifier. - - -unset - remove the entry for the given identifier from the scratchpad. - - -copy - copy the value of the first identifier to the second identifier. - - -assert - assert that the entry for the given identifier is set to the given value. - - -assert-set - assert that the entry for the given identifier exists. - - -assert-unset - assert that the entry for the given identifier does not exist. - -The identifier may not contain whitespace. By convention, it is usually prefixed -by the name of the pass that uses it, e.g. 'opt.did_something'. If the value -contains whitespace, it must be enclosed in double quotes. -\end{lstlisting} - -\section{script -- execute commands from file or wire} +\section{script -- execute commands from script file} \label{cmd:script} \begin{lstlisting}[numbers=left,frame=single] script [:] - script -scriptwire [selection] -This command executes the yosys commands in the specified file (default -behaviour), or commands embedded in the constant text value connected to the -selected wires. +This command executes the yosys commands in the specified file. -In the default (file) case, the 2nd argument can be used to only execute the -section of the file between the specified labels. An empty from label is -synonymous with the beginning of the file and an empty to label is synonymous -with the end of the file. +The 2nd argument can be used to only execute the section of the +file between the specified labels. An empty from label is synonymous +for the beginning of the file and an empty to label is synonymous +for the end of the file. If only one label is specified (without ':') then only the block marked with that label (until the next label) is executed. - -In "-scriptwire" mode, the commands on the selected wire(s) will be executed -in the scope of (and thus, relative to) the wires' owning module(s). This -'-module' mode can be exited by using the 'cd' command. \end{lstlisting} \section{select -- modify and view the list of selected objects} @@ -4049,7 +2807,7 @@ \section{select -- modify and view the list of selected objects} list of selected objects. Note that many commands support an optional [selection] argument that can be -used to override the global selection for the command. The syntax of this +used to YS_OVERRIDE the global selection for the command. The syntax of this optional argument is identical to the syntax of the argument described here. @@ -4139,10 +2897,6 @@ \section{select -- modify and view the list of selected objects} all modules with an attribute matching the given pattern in addition to = also <, <=, >=, and > are supported - N: - all modules with a name matching the given pattern - (i.e. 'N:' is optional as it is the default matching rule) - An can be an object name, wildcard expression, or one of the following: @@ -4308,25 +3062,11 @@ \section{setundef -- replace undef values with defined constants} replace with $anyconst drivers (for formal) -random - replace with random bits using the specified integer as seed + replace with random bits using the specified integer als seed value for the random number generator. -init also create/update init values for flip-flops - - -params - replace undef in cell parameters -\end{lstlisting} - -\section{sf2\_iobs -- SF2: insert IO buffers} -\label{cmd:sf2_iobs} -\begin{lstlisting}[numbers=left,frame=single] - sf2_iobs [options] [selection] - -Add SF2 I/O buffers and global buffers to top module as needed. - - -clkbuf - Insert PAD->global_net clock buffers \end{lstlisting} \section{share -- perform sat-based resource sharing} @@ -4442,7 +3182,7 @@ \section{show -- generate schematics using graphviz} assigned to each unique value of this attribute. -width - annotate buses with a label indicating the width of the bus. + annotate busses with a label indicating the width of the bus. -signed mark ports (A, B) that are declared as signed (using the [AB]_SIGNED @@ -4464,10 +3204,6 @@ \section{show -- generate schematics using graphviz} -notitle do not add the module name as graph title to the dot file - -nobg - don't run viewer in the background, IE wait for the viewer tool to - exit before returning - When no is specified, 'dot' is used. When no and is specified, 'xdot' is used to display the schematic (POSIX systems only). @@ -4668,10 +3404,6 @@ \section{stat -- print some statistics} -liberty use cell area information from the provided liberty file - -tech - print area estemate for the specified technology. Currently supported - values for : xilinx, cmos - -width annotate internal cell types with their word width. e.g. $add_8 for an 8 bit wide $add cell. @@ -4680,7 +3412,7 @@ \section{stat -- print some statistics} \section{submod -- moving part of a module to a new submodule} \label{cmd:submod} \begin{lstlisting}[numbers=left,frame=single] - submod [options] [selection] + submod [-copy] [selection] This pass identifies all cells with the 'submod' attribute and moves them to a newly created module. The value of the attribute is used as name for the @@ -4692,29 +3424,16 @@ \section{submod -- moving part of a module to a new submodule} This pass only operates on completely selected modules with no processes or memories. - -copy - by default the cells are 'moved' from the source module and the source - module will use an instance of the new module after this command is - finished. call with -copy to not modify the source module. - - -name - don't use the 'submod' attribute but instead use the selection. only - objects from one module might be selected. the value of the -name option - is used as the value of the 'submod' attribute instead. - -hidden - instead of creating submodule ports with public names, create ports with - private names so that a subsequent 'flatten; clean' call will restore the - original module with original public names. -\end{lstlisting} + submod -name [-copy] [selection] -\section{supercover -- add hi/lo cover cells for each wire bit} -\label{cmd:supercover} -\begin{lstlisting}[numbers=left,frame=single] - supercover [options] [selection] +As above, but don't use the 'submod' attribute but instead use the selection. +Only objects from one module might be selected. The value of the -name option +is used as the value of the 'submod' attribute above. -This command adds two cover cells for each bit of each selected wire, one -checking for a hi signal level and one checking for lo level. +By default the cells are 'moved' from the source module and the source module +will use an instance of the new module after this command is finished. Call +with -copy to not modify the source module. \end{lstlisting} \section{synth -- generic synthesis script} @@ -4738,9 +3457,6 @@ \section{synth -- generic synthesis script} -encfile passed to 'fsm_recode' via 'fsm' - -lut - perform synthesis for a k-LUT architecture. - -nofsm do not run FSM optimization @@ -4762,12 +3478,6 @@ \section{synth -- generic synthesis script} from label is synonymous to 'begin', and empty to label is synonymous to the end of the command list. - -abc9 - use new ABC9 flow (EXPERIMENTAL) - - -flowmap - use FlowMap LUT techmapping instead of ABC - The following commands are executed by this synthesis command: @@ -4776,19 +3486,16 @@ \section{synth -- generic synthesis script} coarse: proc - flatten (if -flatten) + flatten (if -flatten) opt_expr opt_clean check opt wreduce - peepopt - opt_clean - techmap -map +/cmp2lut.v -map +/cmp2lcu.v (if -lut) - alumacc (unless -noalumacc) - share (unless -noshare) + alumacc + share opt - fsm (unless -nofsm) + fsm opt -fast memory -nomap opt_clean @@ -4798,13 +3505,9 @@ \section{synth -- generic synthesis script} memory_map opt -full techmap - techmap -map +/gate2lut.v (if -noabc and -lut) - clean; opt_lut (if -noabc and -lut) - flowmap -maxlut K (if -flowmap and -lut) opt -fast - abc -fast (unless -noabc, unless -lut) - abc -fast -lut k (unless -noabc, if -lut) - opt -fast (unless -noabc) + abc -fast + opt -fast check: hierarchy -check @@ -4835,7 +3538,7 @@ \section{synth\_achronix -- synthesis for Acrhonix Speedster22i FPGAs.} do not flatten design before synthesis -retime - run 'abc' with '-dff -D 1' options + run 'abc' with -dff option The following commands are executed by this synthesis command: @@ -4857,13 +3560,14 @@ \section{synth\_achronix -- synthesis for Acrhonix Speedster22i FPGAs.} opt -fast -mux_undef -undriven -fine -full memory_map opt -undriven -fine + dffsr2dff dff2dffe -direct-match $_DFF_* opt -fine techmap -map +/techmap.v opt -full clean -purge setundef -undriven -zero - abc -markgroups -dff -D 1 (only if -retime) + abc -markgroups -dff (only if -retime) map_luts: abc -lut 4 @@ -4883,99 +3587,6 @@ \section{synth\_achronix -- synthesis for Acrhonix Speedster22i FPGAs.} write_verilog -nodec -attr2comment -defparam -renameprefix syn_ \end{lstlisting} -\section{synth\_anlogic -- synthesis for Anlogic FPGAs} -\label{cmd:synth_anlogic} -\begin{lstlisting}[numbers=left,frame=single] - synth_anlogic [options] - -This command runs synthesis for Anlogic FPGAs. - - -top - use the specified module as top module - - -edif - write the design to the specified EDIF file. writing of an output file - is omitted if this parameter is not specified. - - -json - write the design to the specified JSON file. writing of an output file - is omitted if this parameter is not specified. - - -run : - only run the commands between the labels (see below). an empty - from label is synonymous to 'begin', and empty to label is - synonymous to the end of the command list. - - -noflatten - do not flatten design before synthesis - - -retime - run 'abc' with '-dff -D 1' options - - -nolutram - do not use EG_LOGIC_DRAM16X4 cells in output netlist - - -The following commands are executed by this synthesis command: - - begin: - read_verilog -lib +/anlogic/cells_sim.v +/anlogic/eagle_bb.v - hierarchy -check -top - - flatten: (unless -noflatten) - proc - flatten - tribuf -logic - deminout - - coarse: - synth -run coarse - - map_lutram: (skip if -nolutram) - memory_bram -rules +/anlogic/lutrams.txt - techmap -map +/anlogic/lutrams_map.v - setundef -zero -params t:EG_LOGIC_DRAM16X4 - - map_ffram: - opt -fast -mux_undef -undriven -fine - memory_map - opt -undriven -fine - - map_gates: - techmap -map +/techmap.v -map +/anlogic/arith_map.v - opt -fast - abc -dff -D 1 (only if -retime) - - map_ffs: - techmap -D NO_LUT -map +/anlogic/cells_map.v - dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit - opt_expr -mux_undef - simplemap - - map_luts: - abc -lut 4:6 - clean - - map_cells: - techmap -map +/anlogic/cells_map.v - clean - - map_anlogic: - anlogic_fixcarry - anlogic_eqn - - check: - hierarchy -check - stat - check -noinit - - edif: - write_edif - - json: - write_json -\end{lstlisting} - \section{synth\_coolrunner2 -- synthesis for Xilinx Coolrunner-II CPLDs} \label{cmd:synth_coolrunner2} \begin{lstlisting}[numbers=left,frame=single] @@ -5001,7 +3612,7 @@ \section{synth\_coolrunner2 -- synthesis for Xilinx Coolrunner-II CPLDs} do not flatten design before synthesis -retime - run 'abc' with '-dff -D 1' options + run 'abc' with -dff option The following commands are executed by this synthesis command: @@ -5019,12 +3630,9 @@ \section{synth\_coolrunner2 -- synthesis for Xilinx Coolrunner-II CPLDs} synth -run coarse fine: - extract_counter -dir up -allow_arst no - techmap -map +/coolrunner2/cells_counter_map.v - clean opt -fast -full - techmap -map +/techmap.v -map +/coolrunner2/cells_latch.v - opt -fast + techmap + techmap -map +/coolrunner2/cells_latch.v dfflibmap -prepare -liberty +/coolrunner2/xc2_dff.lib map_tff: @@ -5045,11 +3653,9 @@ \section{synth\_coolrunner2 -- synthesis for Xilinx Coolrunner-II CPLDs} dffinit -ff LDCP Q INIT dffinit -ff LDCP_N Q INIT coolrunner2_sop - clean iopadmap -bits -inpad IBUF O:I -outpad IOBUFE I:IO -inoutpad IOBUFE O:IO -toutpad IOBUFE E:I:IO -tinoutpad IOBUFE E:O:I:IO attrmvcp -attr src -attr LOC t:IOBUFE n:* attrmvcp -attr src -attr LOC -driven t:IBUF n:* - coolrunner2_fixup splitnets clean @@ -5088,7 +3694,7 @@ \section{synth\_easic -- synthesis for eASIC platform} do not flatten design before synthesis -retime - run 'abc' with '-dff -D 1' options + run 'abc' with -dff option The following commands are executed by this synthesis command: @@ -5111,7 +3717,7 @@ \section{synth\_easic -- synthesis for eASIC platform} opt -undriven -fine techmap opt -fast - abc -dff -D 1 (only if -retime) + abc -dff (only if -retime) opt_clean (only if -retime) map: @@ -5159,7 +3765,7 @@ \section{synth\_ecp5 -- synthesis for ECP5 FPGAs} do not flatten design before synthesis -retime - run 'abc' with '-dff -D 1' options + run 'abc' with -dff option -noccu2 do not use CCU2 cells in output netlist @@ -5168,105 +3774,69 @@ \section{synth\_ecp5 -- synthesis for ECP5 FPGAs} do not use flipflops with CE in output netlist -nobram - do not use block RAM cells in output netlist + do not use BRAM cells in output netlist - -nolutram - do not use LUT RAM cells in output netlist + -nodram + do not use distributed RAM cells in output netlist - -nowidelut + -nomux do not use PFU muxes to implement LUTs larger than LUT4s - -asyncprld - use async PRLD mode to implement DLATCH and DFFSR (EXPERIMENTAL) - -abc2 run two passes of 'abc' for slightly improved logic density - -abc9 - use new ABC9 flow (EXPERIMENTAL) - -vpr generate an output netlist (and BLIF file) suitable for VPR (this feature is experimental and incomplete) - -nodsp - do not map multipliers to MULT18X18D - The following commands are executed by this synthesis command: begin: - read_verilog -lib -specify +/ecp5/cells_sim.v +/ecp5/cells_bb.v + read_verilog -lib +/ecp5/cells_sim.v hierarchy -check -top - coarse: + flatten: (unless -noflatten) proc flatten tribuf -logic deminout - opt_expr - opt_clean - check - opt - wreduce - peepopt - opt_clean - share - techmap -map +/cmp2lut.v -D LUT_WIDTH=4 - opt_expr - opt_clean - techmap -map +/mul2dsp.v -map +/ecp5/dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18 (unless -nodsp) - chtype -set $mul t:$__soft_mul (unless -nodsp) - alumacc - opt - fsm - opt -fast - memory -nomap - opt_clean - map_bram: (skip if -nobram) - memory_bram -rules +/ecp5/brams.txt - techmap -map +/ecp5/brams_map.v + coarse: + synth -run coarse + + bram: (skip if -nobram) - map_lutram: (skip if -nolutram) - memory_bram -rules +/ecp5/lutrams.txt - techmap -map +/ecp5/lutrams_map.v + dram: (skip if -nodram) + memory_bram -rules +/ecp5/dram.txt + techmap -map +/ecp5/drams_map.v - map_ffram: + fine: opt -fast -mux_undef -undriven -fine - memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block -attr syn_ramstyle=auto -attr syn_ramstyle=registers -attr syn_romstyle=auto -attr syn_romstyle=logic + memory_map opt -undriven -fine - - map_gates: techmap -map +/techmap.v -map +/ecp5/arith_map.v - opt -fast - abc -dff -D 1 (only if -retime) + abc -dff (only if -retime) map_ffs: + dffsr2dff dff2dffs opt_clean dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_* - techmap -D NO_LUT [-D ASYNC_PRLD] -map +/ecp5/cells_map.v - opt_expr -undriven -mux_undef + techmap -D NO_LUT -map +/ecp5/cells_map.v + opt_expr -mux_undef simplemap - ecp5_ffinit - ecp5_gsr - attrmvcp -copy -attr syn_useioff - opt_clean map_luts: abc (only if -abc2) - techmap -map +/ecp5/latches_map.v - abc -lut 4:7 -dress + abc -lut 4:7 clean map_cells: techmap -map +/ecp5/cells_map.v (with -D NO_LUT in vpr mode) - opt_lut_ins -tech ecp5 clean check: - autoname hierarchy -check stat check -noinit @@ -5283,98 +3853,6 @@ \section{synth\_ecp5 -- synthesis for ECP5 FPGAs} write_json \end{lstlisting} -\section{synth\_efinix -- synthesis for Efinix FPGAs} -\label{cmd:synth_efinix} -\begin{lstlisting}[numbers=left,frame=single] - synth_efinix [options] - -This command runs synthesis for Efinix FPGAs. - - -top - use the specified module as top module - - -edif - write the design to the specified EDIF file. writing of an output file - is omitted if this parameter is not specified. - - -json - write the design to the specified JSON file. writing of an output file - is omitted if this parameter is not specified. - - -run : - only run the commands between the labels (see below). an empty - from label is synonymous to 'begin', and empty to label is - synonymous to the end of the command list. - - -noflatten - do not flatten design before synthesis - - -retime - run 'abc' with '-dff -D 1' options - - -nobram - do not use EFX_RAM_5K cells in output netlist - - -The following commands are executed by this synthesis command: - - begin: - read_verilog -lib +/efinix/cells_sim.v - hierarchy -check -top - - flatten: (unless -noflatten) - proc - flatten - tribuf -logic - deminout - - coarse: - synth -run coarse - memory_bram -rules +/efinix/brams.txt - techmap -map +/efinix/brams_map.v - setundef -zero -params t:EFX_RAM_5K - - map_ffram: - opt -fast -mux_undef -undriven -fine - memory_map - opt -undriven -fine - - map_gates: - techmap -map +/techmap.v -map +/efinix/arith_map.v - opt -fast - abc -dff -D 1 (only if -retime) - - map_ffs: - techmap -D NO_LUT -map +/efinix/cells_map.v - dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit - opt_expr -mux_undef - simplemap - - map_luts: - abc -lut 4 - clean - - map_cells: - techmap -map +/efinix/cells_map.v - clean - - map_gbuf: - efinix_gbuf - efinix_fixcarry - clean - - check: - hierarchy -check - stat - check -noinit - - edif: - write_edif - - json: - write_json -\end{lstlisting} - \section{synth\_gowin -- synthesis for Gowin FPGAs} \label{cmd:synth_gowin} \begin{lstlisting}[numbers=left,frame=single] @@ -5394,26 +3872,8 @@ \section{synth\_gowin -- synthesis for Gowin FPGAs} from label is synonymous to 'begin', and empty to label is synonymous to the end of the command list. - -nodffe - do not use flipflops with CE in output netlist - - -nobram - do not use BRAM cells in output netlist - - -nolutram - do not use distributed RAM cells in output netlist - - -noflatten - do not flatten design before synthesis - -retime - run 'abc' with '-dff -D 1' options - - -nowidelut - do not use muxes to implement LUTs larger than LUT4s - - -noiopads - do not emit IOB at top level ports + run 'abc' with -dff option The following commands are executed by this synthesis command: @@ -5422,7 +3882,7 @@ \section{synth\_gowin -- synthesis for Gowin FPGAs} read_verilog -lib +/gowin/cells_sim.v hierarchy -check -top - flatten: (unless -noflatten) + flatten: proc flatten tribuf -logic @@ -5431,45 +3891,25 @@ \section{synth\_gowin -- synthesis for Gowin FPGAs} coarse: synth -run coarse - map_bram: (skip if -nobram) - memory_bram -rules +/gowin/brams.txt - techmap -map +/gowin/brams_map.v - - map_lutram: (skip if -nolutram) - memory_bram -rules +/gowin/lutrams.txt - techmap -map +/gowin/lutrams_map.v - determine_init - - map_ffram: + fine: opt -fast -mux_undef -undriven -fine memory_map opt -undriven -fine - - map_gates: - techmap -map +/techmap.v -map +/gowin/arith_map.v - opt -fast - abc -dff -D 1 (only if -retime) - splitnets - - map_ffs: - dff2dffs -match-init - opt_clean - dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_* - techmap -map +/gowin/cells_map.v - opt_expr -mux_undef - simplemap + techmap + clean -purge + splitnets -ports + setundef -undriven -zero + abc -dff (only if -retime) map_luts: - abc -lut 4:8 + abc -lut 4 clean map_cells: techmap -map +/gowin/cells_map.v - opt_lut_ins -tech gowin - setundef -undriven -params -zero - hilomap -singleton -hicell VCC V -locell GND G - iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O -toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO (unless -noiopads) - clean + hilomap -hicell VCC V -locell GND G + iopadmap -inpad IBUF O:I -outpad OBUF I:O + clean -purge check: hierarchy -check @@ -5477,7 +3917,7 @@ \section{synth\_gowin -- synthesis for Gowin FPGAs} check -noinit vout: - write_verilog -decimal -attr2comment -defparam -renameprefix gen + write_verilog -nodec -attr2comment -defparam -renameprefix gen \end{lstlisting} \section{synth\_greenpak4 -- synthesis for GreenPAK4 FPGAs} @@ -5509,7 +3949,7 @@ \section{synth\_greenpak4 -- synthesis for GreenPAK4 FPGAs} do not flatten design before synthesis -retime - run 'abc' with '-dff -D 1' options + run 'abc' with -dff option The following commands are executed by this synthesis command: @@ -5532,10 +3972,11 @@ \section{synth\_greenpak4 -- synthesis for GreenPAK4 FPGAs} opt -fast -mux_undef -undriven -fine memory_map opt -undriven -fine - techmap -map +/techmap.v -map +/greenpak4/cells_latch.v + techmap + techmap -map +/greenpak4/cells_latch.v dfflibmap -prepare -liberty +/greenpak4/gp_dff.lib opt -fast - abc -dff -D 1 (only if -retime) + abc -dff (only if -retime) map_luts: nlutmap -assert -luts 0,6,8,2 (for -part SLG46140V) @@ -5573,10 +4014,6 @@ \section{synth\_ice40 -- synthesis for iCE40 FPGAs} This command runs synthesis for iCE40 FPGAs. - -device < hx | lp | u > - relevant only for '-abc9' flow, optimise timing for the specified device. - default: hx - -top use the specified module as top module @@ -5601,7 +4038,7 @@ \section{synth\_ice40 -- synthesis for iCE40 FPGAs} do not flatten design before synthesis -retime - run 'abc' with '-dff -D 1' options + run 'abc' with -dff option -nocarry do not use SB_CARRY cells in output netlist @@ -5609,18 +4046,8 @@ \section{synth\_ice40 -- synthesis for iCE40 FPGAs} -nodffe do not use SB_DFFE* cells in output netlist - -dffe_min_ce_use - do not use SB_DFFE* cells if the resulting CE line would go to less - than min_ce_use SB_DFFE* in output netlist - - -nobram - do not use SB_RAM40_4K* cells in output netlist - - -dsp - use iCE40 UltraPlus DSP cells for large arithmetic - - -noabc - use built-in Yosys LUT techmapping instead of abc + -nobram + do not use SB_RAM40_4K* cells in output netlist -abc2 run two passes of 'abc' for slightly improved logic density @@ -5629,74 +4056,38 @@ \section{synth\_ice40 -- synthesis for iCE40 FPGAs} generate an output netlist (and BLIF file) suitable for VPR (this feature is experimental and incomplete) - -abc9 - use new ABC9 flow (EXPERIMENTAL) - - -flowmap - use FlowMap LUT techmapping instead of abc (EXPERIMENTAL) - The following commands are executed by this synthesis command: begin: - read_verilog -D ICE40_HX -lib -specify +/ice40/cells_sim.v + read_verilog -lib +/ice40/cells_sim.v hierarchy -check -top - proc flatten: (unless -noflatten) + proc flatten tribuf -logic deminout coarse: - opt_expr - opt_clean - check - opt - wreduce - peepopt - opt_clean - share - techmap -map +/cmp2lut.v -D LUT_WIDTH=4 - opt_expr - opt_clean - memory_dff - wreduce t:$mul - techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D DSP_NAME=$__MUL16X16 (if -dsp) - select a:mul2dsp (if -dsp) - setattr -unset mul2dsp (if -dsp) - opt_expr -fine (if -dsp) - wreduce (if -dsp) - select -clear (if -dsp) - ice40_dsp (if -dsp) - chtype -set $mul t:$__soft_mul (if -dsp) - alumacc - opt - fsm - opt -fast - memory -nomap - opt_clean + synth -run coarse - map_bram: (skip if -nobram) + bram: (skip if -nobram) memory_bram -rules +/ice40/brams.txt techmap -map +/ice40/brams_map.v - ice40_braminit - map_ffram: + fine: opt -fast -mux_undef -undriven -fine - memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block -attr syn_ramstyle=auto -attr syn_ramstyle=registers -attr syn_romstyle=auto -attr syn_romstyle=logic + memory_map opt -undriven -fine - - map_gates: - ice40_wrapcarry techmap -map +/techmap.v -map +/ice40/arith_map.v - opt -fast - abc -dff -D 1 (only if -retime) + abc -dff (only if -retime) ice40_opt map_ffs: + dffsr2dff dff2dffe -direct-match $_DFF_* - techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v + techmap -D NO_LUT -map +/ice40/cells_map.v opt_expr -mux_undef simplemap ice40_ffinit @@ -5707,21 +4098,14 @@ \section{synth\_ice40 -- synthesis for iCE40 FPGAs} abc (only if -abc2) ice40_opt (only if -abc2) techmap -map +/ice40/latches_map.v - simplemap (if -noabc or -flowmap) - techmap -map +/gate2lut.v -D LUT_WIDTH=4 (only if -noabc) - flowmap -maxlut 4 (only if -flowmap) - abc -dress -lut 4 (skip if -noabc) - ice40_wrapcarry -unwrap - techmap -D NO_LUT -map +/ice40/cells_map.v + abc -lut 4 clean - opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0 map_cells: techmap -map +/ice40/cells_map.v (with -D NO_LUT in vpr mode) clean check: - autoname hierarchy -check stat check -noinit @@ -5745,11 +4129,11 @@ \section{synth\_intel -- synthesis for Intel (Altera) FPGAs.} This command runs synthesis for Intel FPGAs. - -family + -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive> generate the synthesis netlist for the specified family. - MAX10 is the default target if no family argument specified. - For Cyclone IV GX devices, use cycloneiv argument; for Cyclone IV E, use cycloneive. - Cyclone V and Arria 10 GX devices are experimental. + MAX10 is the default target if not family argument specified. + For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive. + Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument. -top use the specified module as top module (default='top') @@ -5757,8 +4141,6 @@ \section{synth\_intel -- synthesis for Intel (Altera) FPGAs.} -vqm write the design to the specified Verilog Quartus Mapping File. Writing of an output file is omitted if this parameter is not specified. - Note that this backend has not been tested and is likely incompatible - with recent versions of Quartus. -vpr write BLIF files for VPR flow experiments. The synthesized BLIF output file is not @@ -5770,17 +4152,17 @@ \section{synth\_intel -- synthesis for Intel (Altera) FPGAs.} from label is synonymous to 'begin', and empty to label is synonymous to the end of the command list. - -iopads - use IO pad cells in output netlist + -noiopads + do not use altsyncram cells in output netlist -nobram - do not use block RAM cells in output netlist + do not use altsyncram cells in output netlist -noflatten do not flatten design before synthesis -retime - run 'abc' with '-dff -D 1' options + run 'abc' with -dff option The following commands are executed by this synthesis command: @@ -5801,28 +4183,29 @@ \section{synth\_intel -- synthesis for Intel (Altera) FPGAs.} coarse: synth -run coarse - map_bram: (skip if -nobram) - memory_bram -rules +/intel/common/brams_m9k.txt (if applicable for family) - techmap -map +/intel/common/brams_map_m9k.v (if applicable for family) + bram: (skip if -nobram) + memory_bram -rules +/intel/common/brams.txt + techmap -map +/intel/common/brams_map.v - map_ffram: + fine: opt -fast -mux_undef -undriven -fine -full memory_map opt -undriven -fine + dffsr2dff dff2dffe -direct-match $_DFF_* opt -fine techmap -map +/techmap.v opt -full clean -purge setundef -undriven -zero - abc -markgroups -dff -D 1 (only if -retime) + abc -markgroups -dff (only if -retime) map_luts: abc -lut 4 clean map_cells: - iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I (if -iopads) + iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I (unless -noiopads) techmap -map +/intel/max10/cells_map.v dffinit -highlow -ff dffeas q power_up clean -purge @@ -5838,104 +4221,6 @@ \section{synth\_intel -- synthesis for Intel (Altera) FPGAs.} vpr: opt_clean -purge write_blif - - -WARNING: THE 'synth_intel' COMMAND IS EXPERIMENTAL. -\end{lstlisting} - -\section{synth\_sf2 -- synthesis for SmartFusion2 and IGLOO2 FPGAs} -\label{cmd:synth_sf2} -\begin{lstlisting}[numbers=left,frame=single] - synth_sf2 [options] - -This command runs synthesis for SmartFusion2 and IGLOO2 FPGAs. - - -top - use the specified module as top module - - -edif - write the design to the specified EDIF file. writing of an output file - is omitted if this parameter is not specified. - - -vlog - write the design to the specified Verilog file. writing of an output file - is omitted if this parameter is not specified. - - -json - write the design to the specified JSON file. writing of an output file - is omitted if this parameter is not specified. - - -run : - only run the commands between the labels (see below). an empty - from label is synonymous to 'begin', and empty to label is - synonymous to the end of the command list. - - -noflatten - do not flatten design before synthesis - - -noiobs - run synthesis in "block mode", i.e. do not insert IO buffers - - -clkbuf - insert direct PAD->global_net buffers - - -retime - run 'abc' with '-dff -D 1' options - - -The following commands are executed by this synthesis command: - - begin: - read_verilog -lib +/sf2/cells_sim.v - hierarchy -check -top - - flatten: (unless -noflatten) - proc - flatten - tribuf -logic - deminout - - coarse: - synth -run coarse - - fine: - opt -fast -mux_undef -undriven -fine - memory_map - opt -undriven -fine - techmap -map +/techmap.v -map +/sf2/arith_map.v - opt -fast - abc -dff -D 1 (only if -retime) - - map_ffs: - techmap -D NO_LUT -map +/sf2/cells_map.v - opt_expr -mux_undef - simplemap - - map_luts: - abc -lut 4 - clean - - map_cells: - techmap -map +/sf2/cells_map.v - clean - - map_iobs: - sf2_iobs [-clkbuf] (unless -noiobs) - clean - - check: - hierarchy -check - stat - check -noinit - - edif: - write_edif -gndvccy - - vlog: - write_verilog - - json: - write_json \end{lstlisting} \section{synth\_xilinx -- synthesis for Xilinx FPGAs} @@ -5950,26 +4235,6 @@ \section{synth\_xilinx -- synthesis for Xilinx FPGAs} -top use the specified module as top module - -family - run synthesis for the specified Xilinx architecture - generate the synthesis netlist for the specified family. - supported values: - - xcup: Ultrascale Plus - - xcu: Ultrascale - - xc7: Series 7 (default) - - xc6s: Spartan 6 - - xc6v: Virtex 6 - - xc5v: Virtex 5 (EXPERIMENTAL) - - xc4v: Virtex 4 (EXPERIMENTAL) - - xc3sda: Spartan 3A DSP (EXPERIMENTAL) - - xc3sa: Spartan 3A (EXPERIMENTAL) - - xc3se: Spartan 3E (EXPERIMENTAL) - - xc3s: Spartan 3 (EXPERIMENTAL) - - xc2vp: Virtex 2 Pro (EXPERIMENTAL) - - xc2v: Virtex 2 (EXPERIMENTAL) - - xcve: Virtex E, Spartan 2E (EXPERIMENTAL) - - xcv: Virtex, Spartan 2 (EXPERIMENTAL) - -edif write the design to the specified edif file. writing of an output file is omitted if this parameter is not specified. @@ -5982,42 +4247,6 @@ \section{synth\_xilinx -- synthesis for Xilinx FPGAs} generate an output netlist (and BLIF file) suitable for VPR (this feature is experimental and incomplete) - -ise - generate an output netlist suitable for ISE - - -nobram - do not use block RAM cells in output netlist - - -nolutram - do not use distributed RAM cells in output netlist - - -nosrl - do not use distributed SRL cells in output netlist - - -nocarry - do not use XORCY/MUXCY/CARRY4 cells in output netlist - - -nowidelut - do not use MUXF[5-9] resources to implement LUTs larger than native for the target - - -nodsp - do not use DSP48*s to implement multipliers and associated logic - - -noiopad - disable I/O buffer insertion (useful for hierarchical or - out-of-context flows) - - -noclkbuf - disable automatic clock buffer insertion - - -uram - infer URAM288s for large memories (xcup only) - - -widemux - enable inference of hard multiplexer resources (MUXF[78]) for muxes at or - above this number of inputs (minimum value 2, recommended value >= 5). - default: 0 (no inference) - -run : only run the commands between the labels (see below). an empty from label is synonymous to 'begin', and empty to label is @@ -6026,125 +4255,67 @@ \section{synth\_xilinx -- synthesis for Xilinx FPGAs} -flatten flatten design before synthesis - -dff - run 'abc'/'abc9' with -dff option - -retime - run 'abc' with '-D 1' option to enable flip-flop retiming. - implies -dff. - - -abc9 - use new ABC9 flow (EXPERIMENTAL) + run 'abc' with -dff option The following commands are executed by this synthesis command: begin: - read_verilog -lib -specify +/xilinx/cells_sim.v + read_verilog -lib +/xilinx/cells_sim.v read_verilog -lib +/xilinx/cells_xtra.v - hierarchy -check -auto-top + read_verilog -lib +/xilinx/brams_bb.v + hierarchy -check -top - prepare: + flatten: (only if -flatten) proc - flatten (with '-flatten') - tribuf -logic - deminout - opt_expr - opt_clean - check - opt - wreduce [-keepdc] (option for '-widemux') - peepopt - opt_clean - muxpack ('-widemux' only) - pmux2shiftx (skip if '-nosrl' and '-widemux=0') - clean (skip if '-nosrl' and '-widemux=0') - - map_dsp: (skip if '-nodsp') - memory_dff - techmap -map +/mul2dsp.v -map +/xilinx/{family}_dsp_map.v {options} - select a:mul2dsp - setattr -unset mul2dsp - opt_expr -fine - wreduce - select -clear - xilinx_dsp -family - chtype -set $mul t:$__soft_mul + flatten coarse: - techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=[46] - alumacc - share - opt - fsm - opt -fast - memory -nomap - opt_clean - - map_uram: (only if '-uram') - memory_bram -rules +/xilinx/{family}_urams.txt - techmap -map +/xilinx/{family}_urams_map.v + synth -run coarse - map_bram: (skip if '-nobram') - memory_bram -rules +/xilinx/{family}_brams.txt - techmap -map +/xilinx/{family}_brams_map.v + bram: + memory_bram -rules +/xilinx/brams.txt + techmap -map +/xilinx/brams_map.v - map_lutram: (skip if '-nolutram') - memory_bram -rules +/xilinx/lut[46]_lutrams.txt - techmap -map +/xilinx/lutrams_map.v + dram: + memory_bram -rules +/xilinx/drams.txt + techmap -map +/xilinx/drams_map.v - map_ffram: - simplemap t:$dff t:$adff t:$mux - dff2dffs [-match-init] (-match-init for xc6s only) + fine: opt -fast -full memory_map - - fine: - dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_* - muxcover ('-widemux' only) + dffsr2dff + dff2dffe opt -full - xilinx_srl -variable -minlen 3 (skip if '-nosrl') - techmap -map +/techmap.v -D LUT_SIZE=[46] [-map +/xilinx/mux_map.v] -map +/xilinx/arith_map.v + techmap -map +/techmap.v -map +/xilinx/arith_map.v opt -fast - map_cells: - iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top (skip if '-noiopad') - techmap -map +/techmap.v -map +/xilinx/cells_map.v - clean - - map_ffs: - techmap -map +/xilinx/{family}_ff_map.v ('-abc9' only) - map_luts: - opt_expr -mux_undef - abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1] (option for 'nowidelut', '-dff', '-retime') + abc -luts 2:2,3,6:5,10,20 [-dff] clean - xilinx_srl -fixed -minlen 3 (skip if '-nosrl') - techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v -map +/xilinx/{family}_ff_map.v -D LUT_WIDTH=[46] - xilinx_dffopt [-lut4] - opt_lut_ins -tech xilinx - - finalize: - clkbufmap -buf BUFG O:I (skip if '-noclkbuf') - extractinv -inv INV O:I (only if '-ise') + + map_cells: + techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode) + dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT clean check: hierarchy -check - stat -tech xilinx + stat check -noinit - edif: - write_edif -pvector bra + edif: (only if -edif) + write_edif - blif: - write_blif + blif: (only if -blif) + write_blif \end{lstlisting} \section{tcl -- execute a TCL script file} \label{cmd:tcl} \begin{lstlisting}[numbers=left,frame=single] - tcl [args] + tcl This command executes the tcl commands in the specified file. Use 'yosys cmd' to run the yosys command 'cmd' from tcl. @@ -6153,9 +4324,6 @@ \section{tcl -- execute a TCL script file} commands directly as tcl commands to the tcl shell. Yosys commands 'proc' and 'rename' are wrapped to tcl commands 'procs' and 'renames' in order to avoid a name collision with the built in commands. - -If any arguments are specified, these arguments are provided to the script via -the standard $argc and $argv variables. \end{lstlisting} \section{techmap -- generic technology mapper} @@ -6181,8 +4349,7 @@ \section{techmap -- generic technology mapper} instead of inlining them. -max_iter - only run the specified number of iterations on each module. - default: unlimited + only run the specified number of iterations. -recursive instead of the iterative breadth-first algorithm use a recursive @@ -6192,9 +4359,6 @@ \section{techmap -- generic technology mapper} -autoproc Automatically call "proc" on implementations that contain processes. - -wb - Ignore the 'whitebox' attribute on cell implementations. - -assert this option will cause techmap to exit with an error if it can't map a selected cell. only cell types that end on an underscore are accepted @@ -6219,11 +4383,6 @@ \section{techmap -- generic technology mapper} will create a wrapper for the cell and then run the command string that the attribute is set to on the wrapper module. -When a port on a module in the map file has the 'techmap_autopurge' attribute -set, and that port is not connected in the instantiation that is mapped, then -then a cell port connected only to such wires will be omitted in the mapped -version of the circuit. - All wires in the modules from the map file matching the pattern _TECHMAP_* or *._TECHMAP_* are special wires that are used to pass instructions from the mapping module to the techmap command. At the moment the following special @@ -6262,13 +4421,6 @@ \section{techmap -- generic technology mapper} It is possible to combine both prefixes to 'RECURSION; CONSTMAP; '. - _TECHMAP_REMOVEINIT__ - When this wire is set to a constant value, the init attribute of the wire(s) - connected to this port will be consumed. This wire must have the same - width as the given port, and for every bit that is set to 1 in the value, - the corresponding init attribute bit will be changed to 1'bx. If all - bits of an init attribute are left as x, it will be removed. - In addition to this special wires, techmap also supports special parameters in modules in the map file: @@ -6282,13 +4434,6 @@ \section{techmap -- generic technology mapper} former has a 1-bit for each constant input bit and the latter has the value for this bit. The unused bits of the latter are set to undef (x). - _TECHMAP_WIREINIT__ - When a parameter with this name exists, it will be set to the initial - value of the wire(s) connected to the given port, as specified by the init - attribute. If the attribute doesn't exist, x will be filled for the - missing bits. To remove the init attribute bits used, use the - _TECHMAP_REMOVEINIT_*_ wires. - _TECHMAP_BITS_CONNMAP_ _TECHMAP_CONNMAP__ For an N-bit port, the _TECHMAP_CONNMAP__ parameter, if it @@ -6304,12 +4449,6 @@ \section{techmap -- generic technology mapper} A cell with the name _TECHMAP_REPLACE_ in the map file will inherit the name and attributes of the cell that is being replaced. -A cell with a name of the form `_TECHMAP_REPLACE_.` in the map file will -be named thus but with the `_TECHMAP_REPLACE_' prefix substituted with the name -of the cell being replaced. -Similarly, a wire named in the form `_TECHMAP_REPLACE_.` will cause a -new wire alias to be created and named as above but with the `_TECHMAP_REPLACE_' -prefix also substituted. See 'help extract' for a pass that does the opposite thing. @@ -6326,7 +4465,7 @@ \section{tee -- redirect command output to file} specified logfile(s). -q - Do not print output to the normal destination (console and/or log file). + Do not print output to the normal destination (console and/or log file) -o logfile Write output to this file, truncate if exists. @@ -6335,7 +4474,7 @@ \section{tee -- redirect command output to file} Write output to this file, append if exists. +INT, -INT - Add/subtract INT from the -v setting for this command. + Add/subract INT from the -v setting for this command. \end{lstlisting} \section{test\_abcloop -- automatically test handling of loops in abc command} @@ -6372,16 +4511,8 @@ \section{test\_autotb -- generate simple test benches} value after initialization. This can e.g. be used to force a reset signal low in order to explore more inner states in a state machine. -The attribute 'gentb_skip' can be attached to modules to suppress testbench -generation. - -n number of iterations the test bench should run (default = 1000) - - -seed - seed used for pseudo-random number generation (default = 0). - a value of 0 will cause an arbitrary seed to be chosen, based on - the current system time. \end{lstlisting} \section{test\_cell -- automatically test the implementation of a cell type} @@ -6443,29 +4574,6 @@ \section{test\_cell -- automatically test the implementation of a cell type} create a Verilog test bench to test simlib and write_verilog \end{lstlisting} -\section{test\_pmgen -- test pass for pmgen} -\label{cmd:test_pmgen} -\begin{lstlisting}[numbers=left,frame=single] - test_pmgen -reduce_chain [options] [selection] - -Demo for recursive pmgen patterns. Map chains of AND/OR/XOR to $reduce_*. - - - test_pmgen -reduce_tree [options] [selection] - -Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*. - - - test_pmgen -eqpmux [options] [selection] - -Demo for recursive pmgen patterns. Optimize EQ/NE/PMUX circuits. - - - test_pmgen -generate [options] - -Create modules that match the specified pattern. -\end{lstlisting} - \section{torder -- print cells in topological order} \label{cmd:torder} \begin{lstlisting}[numbers=left,frame=single] @@ -6548,18 +4656,12 @@ \section{verific -- load Verilog and VHDL designs using Verific} Load the specified VHDL files into Verific. - verific [-work ] {-sv|-vhdl|...} + verific -work {-sv|-vhdl|...} Load the specified Verilog/SystemVerilog/VHDL file into the specified library. (default library when -work is not present: "work") - verific [-L ] {-sv|-vhdl|...} - -Look up external definitions in the specified library. -(-L may be used more than once) - - verific -vlog-incdir .. Add Verilog include directories. @@ -6613,16 +4715,6 @@ \section{verific -- load Verilog and VHDL designs using Verific} -autocover Generate automatic cover statements for all asserts - -fullinit - Keep all register initializations, even those for non-FF registers. - - -chparam name value - Elaborate the specified top modules (all modules when -all given) using - this parameter value. Modules on which this parameter does not exist will - cause Verific to produce a VERI-1928 or VHDL-1676 message. This option - can be specified multiple times to override multiple parameters. - String values must be passed in double quotes ("). - -v, -vv Verbose log messages. (-vv is even more verbose than -v.) @@ -6651,12 +4743,7 @@ \section{verific -- load Verilog and VHDL designs using Verific} -d Dump the Verific netlist as a verilog file. - -Use Symbiotic EDA Suite if you need Yosys+Verifc. -https://www.symbioticeda.com/seda-suite - -Contact office@symbioticeda.com for free evaluation -binaries of Symbiotic EDA Suite. +Visit http://verific.com/ for more information on Verific. \end{lstlisting} \section{verilog\_defaults -- set default options for read\_verilog} @@ -6692,21 +4779,6 @@ \section{verilog\_defines -- define and undefine verilog defines} -Uname[=definition] undefine the preprocessor symbol 'name' - - -reset - clear list of defined preprocessor symbols - - -list - list currently defined preprocessor symbols -\end{lstlisting} - -\section{wbflip -- flip the whitebox attribute} -\label{cmd:wbflip} -\begin{lstlisting}[numbers=left,frame=single] - wbflip [selection] - -Flip the whitebox attribute on selected cells. I.e. if it's set, unset it, and -vice-versa. Blackbox cells are not effected by this command. \end{lstlisting} \section{wreduce -- reduce the word size of operations if possible} @@ -6726,9 +4798,6 @@ \section{wreduce -- reduce the word size of operations if possible} -memx Do not change the width of memory address ports. Use this options in flows that use the 'memory_memx' pass. - - -keepdc - Do not optimize explicit don't-care values. \end{lstlisting} \section{write\_aiger -- write design to AIGER file} @@ -6744,7 +4813,7 @@ \section{write\_aiger -- write design to AIGER file} invariant constraints. -ascii - write ASCII version of AIGER format + write ASCII version of AGIER format -zinit convert FFs to zero-initialized FFs, adding additional inputs for @@ -6761,11 +4830,6 @@ \section{write\_aiger -- write design to AIGER file} -vmap like -map, but more verbose - - -I, -O, -B, -L - If the design contains no input/output/assert/flip-flop then create one - dummy input/output/bad_state-pin or latch to make the tools reading the - AIGER file happy. \end{lstlisting} \section{write\_blif -- write design to BLIF file} @@ -6849,58 +4913,6 @@ \section{write\_btor -- write design to BTOR file} -s Output only a single bad property for all asserts - - -c - Output cover properties using 'bad' statements instead of asserts - - -i - Create additional info file with auxiliary information -\end{lstlisting} - -\section{write\_cxxrtl -- convert design to C++ RTL simulation} -\label{cmd:write_cxxrtl} -\begin{lstlisting}[numbers=left,frame=single] - write_cxxrtl [options] [filename] - -Write C++ code for simulating the design. The generated code requires a driver; -the following simple driver is provided as an example: - - #include "top.cc" - - int main() { - cxxrtl_design::p_top top; - while (1) { - top.p_clk.next = value<1> {1u}; - top.step(); - top.p_clk.next = value<1> {0u}; - top.step(); - } - } - -The following options are supported by this backend: - - -O - set the optimization level. the default is -O5. higher optimization - levels dramatically decrease compile and run time, and highest level - possible for a design should be used. - - -O0 - no optimization. - - -O1 - elide internal wires if possible. - - -O2 - like -O1, and localize internal wires if possible. - - -O3 - like -O2, and elide public wires not marked (*keep*) if possible. - - -O4 - like -O3, and localize public wires not marked (*keep*) if possible. - - -O5 - like -O4, and run `splitnets -driver; opt_clean -purge` first. \end{lstlisting} \section{write\_edif -- write design to EDIF netlist file} @@ -6918,13 +4930,6 @@ \section{write\_edif -- write design to EDIF netlist file} if the design contains constant nets. use "hilomap" to map to custom constant drivers first) - -gndvccy - create "GND" and "VCC" cells with "Y" outputs. (the default is "G" - for "GND" and "P" for "VCC".) - - -attrprop - create EDIF properties for cell attributes - -pvector {par|bra|ang} sets the delimiting character for module port rename clauses to parentheses, square brackets, or angle brackets. @@ -6959,8 +4964,6 @@ \section{write\_firrtl -- write design to a FIRRTL file} write_firrtl [options] [filename] Write a FIRRTL netlist of the current design. -The following commands are executed by this command: - pmuxtree \end{lstlisting} \section{write\_ilang -- write design to ilang file} @@ -7009,10 +5012,6 @@ \section{write\_json -- write design to a JSON file} -aig include AIG models for the different gate types - -compat-int - emit 32-bit or smaller fully-defined parameter values directly - as JSON numbers (for compatibility with old parsers) - The general syntax of the JSON output created by this command is as follows: @@ -7084,10 +5083,12 @@ \section{write\_json -- write design to a JSON file} Module and cell ports and nets can be single bit wide or vectors of multiple bits. Each individual signal bit is assigned a unique integer. The values referenced above are vectors of this integers. Signal bits that are -connected to a constant driver are denoted as string "0", "1", "x", or -"z" instead of a number. +connected to a constant driver are denoted as string "0" or "1" instead of +a number. -Bit vectors (including integers) are written as string holding the binaryrepresentation of the value. Strings are written as strings, with an appendedblank in cases of strings of the form /[01xz]* */. +Numeric parameter and attribute values up to 32 bits are written as decimal +values. Numbers larger than that are written as string holding the binary +representation of the value. For example the following Verilog code: @@ -7213,7 +5214,7 @@ \section{write\_simplec -- convert design to simple C code} \begin{lstlisting}[numbers=left,frame=single] write_simplec [options] [filename] -Write simple C code for simulating the design. The C code written can be used to +Write simple C code for simulating the design. The C code writen can be used to simulate the design in a C environment, but the purpose of this command is to generate code that works well with C-based formal verification. @@ -7349,7 +5350,7 @@ \section{write\_smt2 -- write design to SMT-LIBv2 file} For this proof we create the following template (test.tpl). - ; we need QF_UFBV for this proof + ; we need QF_UFBV for this poof (set-logic QF_UFBV) ; insert the auto-generated code here @@ -7470,10 +5471,6 @@ \section{write\_verilog -- write design to Verilog file} without this option all internal cells are converted to Verilog expressions. - -siminit - add initial statements with hierarchical refs to initialize FFs when - in -noexpr mode. - -nodec 32-bit constant values are by default dumped as decimal numbers, not bit pattern. This option deactivates this feature and instead @@ -7493,16 +5490,8 @@ \section{write\_verilog -- write design to Verilog file} deactivates this feature and instead will write string constants as binary numbers. - -extmem - instead of initializing memories using assignments to individual - elements, use the '$readmemh' function to read initialization data - from a file. This data is written to a file named by appending - a sequential index to the Verilog filename and replacing the extension - with '.mem', e.g. 'write_verilog -extmem foo.v' writes 'foo-1.mem', - 'foo-2.mem' and so on. - -defparam - use 'defparam' statements instead of the Verilog-2001 syntax for + Use 'defparam' statements instead of the Verilog-2001 syntax for cell parameters. -blackboxes @@ -7524,97 +5513,6 @@ \section{write\_verilog -- write design to Verilog file} this command is called on a design with RTLIL processes. \end{lstlisting} -\section{write\_xaiger -- write design to XAIGER file} -\label{cmd:write_xaiger} -\begin{lstlisting}[numbers=left,frame=single] - write_xaiger [options] [filename] - -Write the top module (according to the (* top *) attribute or if only one module -is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, ornon (* abc9_box_id *) cells will be converted into psuedo-inputs and -pseudo-outputs. Whitebox contents will be taken from the '$holes' -module, if it exists. - - -ascii - write ASCII version of AIGER format - - -map - write an extra file with port and box symbols -\end{lstlisting} - -\section{xilinx\_dffopt -- Xilinx: optimize FF control signal usage} -\label{cmd:xilinx_dffopt} -\begin{lstlisting}[numbers=left,frame=single] - xilinx_dffopt [options] [selection] - -Converts hardware clock enable and set/reset signals on FFs to emulation -using LUTs, if doing so would improve area. Operates on post-techmap Xilinx -cells (LUT*, FD*). - - -lut4 - Assume a LUT4-based device (instead of a LUT6-based device). -\end{lstlisting} - -\section{xilinx\_dsp -- Xilinx: pack resources into DSPs} -\label{cmd:xilinx_dsp} -\begin{lstlisting}[numbers=left,frame=single] - xilinx_dsp [options] [selection] - -Pack input registers (A2, A1, B2, B1, C, D, AD; with optional enable/reset), -pipeline registers (M; with optional enable/reset), output registers (P; with -optional enable/reset), pre-adder and/or post-adder into Xilinx DSP resources. - -Multiply-accumulate operations using the post-adder with feedback on the 'C' -input will be folded into the DSP. In this scenario only, the 'C' input can be -used to override the current accumulation result with a new value, which will -be added to the multiplier result to form the next accumulation result. - -Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C' -connections (optionally, where 'P' is right-shifted by 17-bits and used as an -input to the post-adder -- a pattern common for summing partial products to -implement wide multipliers). Limited support also exists for similar cascading -for A and B using '[AB]COUT' -> '[AB]CIN'. Currently, cascade chains are limited -to a maximum length of 20 cells, corresponding to the smallest Xilinx 7 Series -device. - -This pass is a no-op if the scratchpad variable 'xilinx_dsp.multonly' is set -to 1. - - -Experimental feature: addition/subtractions less than 12 or 24 bits with the -'(* use_dsp="simd" *)' attribute attached to the output wire or attached to -the add/subtract operator will cause those operations to be implemented using -the 'SIMD' feature of DSPs. - -Experimental feature: the presence of a `$ge' cell attached to the registered -P output implementing the operation "(P >= )" will be transformed -into using the DSP48E1's pattern detector feature for overflow detection. - - -family {xcup|xcu|xc7|xc6v|xc5v|xc4v|xc6s|xc3sda} - select the family to target - default: xc7 -\end{lstlisting} - -\section{xilinx\_srl -- Xilinx shift register extraction} -\label{cmd:xilinx_srl} -\begin{lstlisting}[numbers=left,frame=single] - xilinx_srl [options] [selection] - -This pass converts chains of built-in flops (bit-level: $_DFF_[NP]_, $_DFFE_* -and word-level: $dff, $dffe) as well as Xilinx flops (FDRE, FDRE_1) into a -$__XILINX_SHREG cell. Chains must be of the same cell type, clock, clock polarity, -enable, and enable polarity (where relevant). -Flops with resets cannot be mapped to Xilinx devices and will not be inferred. - -minlen N - min length of shift register (default = 3) - - -fixed - infer fixed-length shift registers. - - -variable - infer variable-length shift registers (i.e. fixed-length shifts where - each element also fans-out to a $shiftx cell). -\end{lstlisting} - \section{zinit -- add inverters so all FF are zero-initialized} \label{cmd:zinit} \begin{lstlisting}[numbers=left,frame=single] diff --git a/manual/manual.tex b/manual/manual.tex index 75f087ecae4..67982cbc816 100644 --- a/manual/manual.tex +++ b/manual/manual.tex @@ -146,7 +146,7 @@ \chapter*{Abstract} In special cases such as synthesis for coarse-grain cell libraries or when testing new synthesis algorithms it might be necessary to write a custom HDL -synthesis tool or add new features to an existing one. In these cases the +synthesis tool or add new features to an existing one. It this cases the availability of a Free and Open Source (FOSS) synthesis tool that can be used as basis for custom tools would be helpful. diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index 38bd6129eea..c58c3f66a93 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -312,16 +312,16 @@ def translate(c, varname, types, prefix): text += prefix + "\t" + known_containers[types[0].name].typename + " " + tmp_name + " = boost::python::extract<" + known_containers[types[0].name].typename + ">(" + varname + "[" + cntr_name + "]);" text += known_containers[types[0].name].translate(tmp_name, types[0].cont.args, prefix+"\t") tmp_name = tmp_name + "___tmp" - text += prefix + "\t" + varname + "___tmp" + c.insert_name + "(" + tmp_name + ");" + text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + ");" elif types[0].name in classnames: text += prefix + "\t" + types[0].name + "* " + tmp_name + " = boost::python::extract<" + types[0].name + "*>(" + varname + "[" + cntr_name + "]);" if types[0].attr_type == attr_types.star: - text += prefix + "\t" + varname + "___tmp" + c.insert_name + "(" + tmp_name + "->get_cpp_obj());" + text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + "->get_cpp_obj());" else: - text += prefix + "\t" + varname + "___tmp" + c.insert_name + "(*" + tmp_name + "->get_cpp_obj());" + text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(*" + tmp_name + "->get_cpp_obj());" else: text += prefix + "\t" + types[0].name + " " + tmp_name + " = boost::python::extract<" + types[0].name + ">(" + varname + "[" + cntr_name + "]);" - text += prefix + "\t" + varname + "___tmp" + c.insert_name + "(" + tmp_name + ");" + text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + ");" text += prefix + "}" return text @@ -349,24 +349,19 @@ def translate_cpp(c, varname, types, prefix, ref): text += prefix + "}" return text -class IDictTranslator(PythonListTranslator): - typename = "boost::python::list" - orig_name = "idict" - insert_name = "" - #Sub-type for std::set class SetTranslator(PythonListTranslator): - insert_name = ".insert" + insert_name = "insert" orig_name = "std::set" #Sub-type for std::vector class VectorTranslator(PythonListTranslator): - insert_name = ".push_back" + insert_name = "push_back" orig_name = "std::vector" #Sub-type for pool class PoolTranslator(PythonListTranslator): - insert_name = ".insert" + insert_name = "insert" orig_name = "pool" #Translates dict-types (dict, std::map), that only differ in their name and @@ -533,7 +528,6 @@ def translate_cpp(c, varname, types, prefix, ref): "std::set" : SetTranslator, "std::vector" : VectorTranslator, "pool" : PoolTranslator, - "idict" : IDictTranslator, "dict" : DictTranslator, "std::pair" : TupleTranslator, "std::map" : MapTranslator @@ -727,7 +721,6 @@ class WClass: name = None namespace = None link_type = None - base_class = None id_ = None string_id = None hash_id = None @@ -739,7 +732,6 @@ class WClass: def __init__(self, name, link_type, id_, string_id = None, hash_id = None, needs_clone = False): self.name = name self.namespace = None - self.base_class = None self.link_type = link_type self.id_ = id_ self.string_id = string_id @@ -812,8 +804,6 @@ def gen_decl(self, filename): for con in self.found_constrs: text += con.gen_decl() - if self.base_class is not None: - text += "\n\t\tvirtual ~" + self.name + "() { };" for var in self.found_vars: text += var.gen_decl() for fun in self.found_funs: @@ -918,19 +908,15 @@ def gen_boost_py_body(self): def gen_boost_py(self): body = self.gen_boost_py_body() - base_info = "" - if self.base_class is not None: - base_info = ", bases<" + (self.base_class.name) + ">" - if self.link_type == link_types.derive: - text = "\n\t\tclass_<" + self.name + base_info + ">(\"Cpp" + self.name + "\"" + text = "\n\t\tclass_<" + self.name + ">(\"Cpp" + self.name + "\"" text += body text += "\n\t\tclass_<" + self.name text += "Wrap, boost::noncopyable" text += ">(\"" + self.name + "\"" text += body else: - text = "\n\t\tclass_<" + self.name + base_info + ">(\"" + self.name + "\"" + text = "\n\t\tclass_<" + self.name + ">(\"" + self.name + "\"" text += body return text @@ -1414,7 +1400,7 @@ def gen_decl_virtual(self): text += ", " if len(self.args) > 0: text = text[:-2] - text += ") override;\n" + text += ") YS_OVERRIDE;\n" return text def gen_decl_hash_py(self): @@ -1949,19 +1935,6 @@ def parse_header(source): line = source_text[i].replace("YOSYS_NAMESPACE_BEGIN", " namespace YOSYS_NAMESPACE{").replace("YOSYS_NAMESPACE_END"," }") ugly_line = unpretty_string(line) - # for anonymous unions, ignore union enclosure by skipping start line and replacing end line with new line - if 'union {' in line: - j = i+1 - while j < len(source_text): - union_line = source_text[j] - if '};' in union_line: - source_text[j] = '\n' - break - j += 1 - if j != len(source_text): - i += 1 - continue - if str.startswith(ugly_line, "namespace "):# and ugly_line.find("std") == -1 and ugly_line.find("__") == -1: namespace_name = ugly_line[10:].replace("{","").strip() namespaces.append((namespace_name, ugly_line.count("{"))) @@ -1985,21 +1958,9 @@ def parse_header(source): for namespace in impl_namespaces: complete_namespace += "::" + namespace debug("\tFound " + struct_name + " in " + complete_namespace,2) - - base_class_name = None - if len(ugly_line.split(" : ")) > 1: # class is derived - deriv_str = ugly_line.split(" : ")[1] - if len(deriv_str.split("::")) > 1: # namespace of base class is given - base_class_name = deriv_str.split("::", 1)[1] - else: - base_class_name = deriv_str.split(" ")[0] - debug("\t " + struct_name + " is derived from " + base_class_name,2) - base_class = class_by_name(base_class_name) - class_ = (class_by_name(struct_name), ugly_line.count("{"))#calc_ident(line)) if struct_name in classnames: class_[0].namespace = complete_namespace - class_[0].base_class = base_class i += 1 continue @@ -2168,21 +2129,6 @@ def expand_functions(): new_funs.extend(expand_function(fun)) class_.found_funs = new_funs -def inherit_members(): - for source in sources: - for class_ in source.classes: - if class_.base_class: - base_funs = copy.deepcopy(class_.base_class.found_funs) - for fun in base_funs: - fun.member_of = class_ - fun.namespace = class_.namespace - base_vars = copy.deepcopy(class_.base_class.found_vars) - for var in base_vars: - var.member_of = class_ - var.namespace = class_.namespace - class_.found_funs.extend(base_funs) - class_.found_vars.extend(base_vars) - def clean_duplicates(): for source in sources: for class_ in source.classes: @@ -2219,7 +2165,6 @@ def gen_wrappers(filename, debug_level_ = 0): parse_header(source) expand_functions() - inherit_members() clean_duplicates() import shutil diff --git a/misc/yosys-config.in b/misc/yosys-config.in index a31ef38c2be..1473948cf51 100644 --- a/misc/yosys-config.in +++ b/misc/yosys-config.in @@ -6,7 +6,7 @@ help() { echo "Usage: $0 [--exec] [--prefix pf] args.." echo " $0 --build modname.so cppsources.." echo "" - echo "Replacement args:" + echo "Replecement args:" echo " --cxx @CXX@" echo " --cxxflags $( echo '@CXXFLAGS@' | fmt -w60 | sed ':a;N;$!ba;s/\n/ \\\n /g' )" echo " --ldflags @LDFLAGS@" @@ -18,21 +18,21 @@ help() { echo "" echo "Use --exec to call a command instead of generating output. Example usage:" echo "" - echo " $0 --exec --cxx --cxxflags --ldflags -o plugin.so -shared plugin.cc --ldlibs" + echo " yosys-config --exec --cxx --cxxflags --ldflags -o plugin.so -shared plugin.cc --ldlibs" echo "" echo "The above command can be abbreviated as:" echo "" - echo " $0 --build plugin.so plugin.cc" + echo " yosys-config --build plugin.so plugin.cc" echo "" echo "Use --prefix to change the prefix for the special args from '--' to" echo "something else. Example:" echo "" - echo " $0 --prefix @ bindir: @bindir" + echo " yosys-config --prefix @ bindir: @bindir" echo "" echo "The args --bindir and --datdir can be directly followed by a slash and" echo "additional text. Example:" echo "" - echo " $0 --datdir/simlib.v" + echo " yosys-config --datdir/simlib.v" echo "" } >&2 exit 1 diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index 53bfd40c64a..c7edc30fbdb 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -1,7 +1,4 @@ -ifeq ($(DISABLE_SPAWN),0) -OBJS += passes/cmds/exec.o -endif OBJS += passes/cmds/add.o OBJS += passes/cmds/delete.o OBJS += passes/cmds/design.o @@ -34,9 +31,4 @@ OBJS += passes/cmds/chformal.o OBJS += passes/cmds/chtype.o OBJS += passes/cmds/blackbox.o OBJS += passes/cmds/ltp.o -ifeq ($(DISABLE_SPAWN),0) OBJS += passes/cmds/bugpoint.o -endif -OBJS += passes/cmds/scratchpad.o -OBJS += passes/cmds/logger.o -OBJS += passes/cmds/printattrs.o diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc index a2f4a91000f..dd05ac81f31 100644 --- a/passes/cmds/add.cc +++ b/passes/cmds/add.cc @@ -22,61 +22,26 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -static bool is_formal_celltype(const std::string &celltype) -{ - if(celltype == "assert" || celltype == "assume" || celltype == "live" || celltype == "fair" || celltype == "cover") - return true; - else - return false; -} - -static void add_formal(RTLIL::Module *module, const std::string &celltype, const std::string &name, const std::string &enable_name) -{ - std::string escaped_name = RTLIL::escape_id(name); - std::string escaped_enable_name = (enable_name != "") ? RTLIL::escape_id(enable_name) : ""; - RTLIL::Wire *wire = module->wire(escaped_name); - log_assert(is_formal_celltype(celltype)); - - if (wire == nullptr) { - log_error("Could not find wire with name \"%s\".\n", name.c_str()); - } - else { - RTLIL::Cell *formal_cell = module->addCell(NEW_ID, "$" + celltype); - formal_cell->setPort(ID::A, wire); - if(enable_name == "") { - formal_cell->setPort(ID::EN, State::S1); - log("Added $%s cell for wire \"%s.%s\"\n", celltype.c_str(), module->name.str().c_str(), name.c_str()); - } - else { - RTLIL::Wire *enable_wire = module->wire(escaped_enable_name); - if(enable_wire == nullptr) - log_error("Could not find enable wire with name \"%s\".\n", enable_name.c_str()); - - formal_cell->setPort(ID::EN, enable_wire); - log("Added $%s cell for wire \"%s.%s\" enabled by wire \"%s.%s\".\n", celltype.c_str(), module->name.str().c_str(), name.c_str(), module->name.str().c_str(), enable_name.c_str()); - } - } -} - static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output, bool flag_global) { - RTLIL::Wire *wire = nullptr; + RTLIL::Wire *wire = NULL; name = RTLIL::escape_id(name); if (module->count_id(name) != 0) { - wire = module->wire(name); + if (module->wires_.count(name) > 0) + wire = module->wires_.at(name); - if (wire != nullptr && wire->width != width) - wire = nullptr; + if (wire != NULL && wire->width != width) + wire = NULL; - if (wire != nullptr && wire->port_input != flag_input) - wire = nullptr; + if (wire != NULL && wire->port_input != flag_input) + wire = NULL; - if (wire != nullptr && wire->port_output != flag_output) - wire = nullptr; + if (wire != NULL && wire->port_output != flag_output) + wire = NULL; - if (wire == nullptr) + if (wire == NULL) log_cmd_error("Found incompatible object with same name in module %s!\n", module->name.c_str()); log("Module %s already has such an object.\n", module->name.c_str()); @@ -88,6 +53,7 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n wire->port_output = flag_output; if (flag_input || flag_output) { + wire->port_id = module->wires_.size(); module->fixup_ports(); } @@ -97,26 +63,27 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n if (!flag_global) return; - for (auto cell : module->cells()) + for (auto &it : module->cells_) { - RTLIL::Module *mod = design->module(cell->type); - if (mod == nullptr) + if (design->modules_.count(it.second->type) == 0) continue; + + RTLIL::Module *mod = design->modules_.at(it.second->type); if (!design->selected_whole_module(mod->name)) continue; if (mod->get_blackbox_attribute()) continue; - if (cell->hasPort(name)) + if (it.second->hasPort(name)) continue; - cell->setPort(name, wire); - log("Added connection %s to cell %s.%s (%s).\n", name.c_str(), module->name.c_str(), cell->name.c_str(), cell->type.c_str()); + it.second->setPort(name, wire); + log("Added connection %s to cell %s.%s (%s).\n", name.c_str(), module->name.c_str(), it.first.c_str(), it.second->type.c_str()); } } struct AddPass : public Pass { AddPass() : Pass("add", "add objects to the design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -139,22 +106,15 @@ struct AddPass : public Pass { log("selected modules.\n"); log("\n"); log("\n"); - log(" add {-assert|-assume|-live|-fair|-cover} [-if ]\n"); - log("\n"); - log("Add an $assert, $assume, etc. cell connected to a wire named name1, with its\n"); - log("enable signal optionally connected to a wire named name2 (default: 1'b1).\n"); - log("\n"); - log("\n"); log(" add -mod \n"); log("\n"); log("Add module[s] with the specified name[s].\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string command; std::string arg_name; - std::string enable_name = ""; bool arg_flag_input = false; bool arg_flag_output = false; bool arg_flag_global = false; @@ -184,17 +144,6 @@ struct AddPass : public Pass { argidx++; break; } - if (arg.length() > 0 && arg[0] == '-' && is_formal_celltype(arg.substr(1))) { - if (argidx + 1 >= args.size()) - break; - command = arg.substr(1); - arg_name = args[++argidx]; - if (argidx + 2 < args.size() && args[argidx + 1] == "-if") { - enable_name = args[argidx + 2]; - argidx += 2; - } - continue; - } break; } @@ -206,23 +155,17 @@ struct AddPass : public Pass { extra_args(args, argidx, design); - bool selected_anything = false; - for (auto module : design->modules()) + for (auto &mod : design->modules_) { - log_assert(module != nullptr); + RTLIL::Module *module = mod.second; if (!design->selected_whole_module(module->name)) continue; - if (module->get_bool_attribute(ID::blackbox)) + if (module->get_bool_attribute("\\blackbox")) continue; - selected_anything = true; - if (is_formal_celltype(command)) - add_formal(module, command, arg_name, enable_name); - else if (command == "wire") + if (command == "wire") add_wire(design, module, arg_name, arg_width, arg_flag_input, arg_flag_output, arg_flag_global); } - if (!selected_anything) - log_warning("No modules selected, or only blackboxes. Nothing was added.\n"); } } AddPass; diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc index 28d4012c443..4614a81534c 100644 --- a/passes/cmds/autoname.cc +++ b/passes/cmds/autoname.cc @@ -56,7 +56,7 @@ int autoname_worker(Module *module) for (auto &conn : cell->connections()) { string suffix = stringf("_%s", log_id(conn.first)); for (auto bit : conn.second) - if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) { + if (bit.wire != nullptr && bit.wire->name[0] == '$') { IdString new_name(cell->name.str() + suffix); int score = wire_score.at(bit.wire); if (cell->output(conn.first)) score = 0; @@ -92,7 +92,7 @@ int autoname_worker(Module *module) struct AutonamePass : public Pass { AutonamePass() : Pass("autoname", "automatically assign names to objects") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -102,7 +102,7 @@ struct AutonamePass : public Pass { log("with $-prefix).\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc index 08a6355148e..d09ed872ebc 100644 --- a/passes/cmds/blackbox.cc +++ b/passes/cmds/blackbox.cc @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN struct BlackboxPass : public Pass { BlackboxPass() : Pass("blackbox", "convert modules into blackbox modules") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -34,7 +34,7 @@ struct BlackboxPass : public Pass { log("module attribute).\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -48,8 +48,32 @@ struct BlackboxPass : public Pass { for (auto module : design->selected_whole_modules_warn()) { - module->makeblackbox(); - module->set_bool_attribute(ID::blackbox); + pool remove_cells; + pool remove_wires; + + for (auto cell : module->cells()) + remove_cells.insert(cell); + + for (auto wire : module->wires()) + if (wire->port_id == 0) + remove_wires.insert(wire); + + for (auto it = module->memories.begin(); it != module->memories.end(); ++it) + delete it->second; + module->memories.clear(); + + for (auto it = module->processes.begin(); it != module->processes.end(); ++it) + delete it->second; + module->processes.clear(); + + module->new_connections(std::vector()); + + for (auto cell : remove_cells) + module->remove(cell); + + module->remove(remove_wires); + + module->set_bool_attribute("\\blackbox"); } } } BlackboxPass; diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index 98d42aa83ba..5a47988ec38 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -26,25 +26,27 @@ PRIVATE_NAMESPACE_BEGIN struct BugpointPass : public Pass { BugpointPass() : Pass("bugpoint", "minimize testcases") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" bugpoint [options] -script \n"); + log(" bugpoint [options]\n"); log("\n"); - log("This command minimizes the current design that is known to crash Yosys with the\n"); - log("given script into a smaller testcase. It does this by removing an arbitrary part\n"); - log("of the design and recursively invokes a new Yosys process with this modified design\n"); - log("and the same script, repeating these steps while it can find a smaller design that\n"); - log("still causes a crash. Once this command finishes, it replaces the current design\n"); - log("with the smallest testcase it was able to produce.\n"); + log("This command minimizes testcases that crash Yosys. It removes an arbitrary part\n"); + log("of the design and recursively invokes Yosys with a given script, repeating these\n"); + log("steps while it can find a smaller design that still causes a crash. Once this\n"); + log("command finishes, it replaces the current design with the smallest testcase it\n"); + log("was able to produce.\n"); log("\n"); - log(" -script \n"); - log(" use this script to crash Yosys. required.\n"); + log("It is possible to specify the kinds of design part that will be removed. If none\n"); + log("are specified, all parts of design will be removed.\n"); log("\n"); log(" -yosys \n"); log(" use this Yosys binary. if not specified, `yosys` is used.\n"); log("\n"); + log(" -script \n"); + log(" use this script to crash Yosys. required.\n"); + log("\n"); log(" -grep \n"); log(" only consider crashes that place this string in the log file.\n"); log("\n"); @@ -58,21 +60,14 @@ struct BugpointPass : public Pass { log(" finishing. produces smaller and more useful testcases, but may fail to\n"); log(" produce any testcase at all if the crash is related to dangling wires.\n"); log("\n"); - log("It is possible to constrain which parts of the design will be considered for\n"); - log("removal. Unless one or more of the following options are specified, all parts\n"); - log("will be considered.\n"); - log("\n"); log(" -modules\n"); - log(" try to remove modules. modules with a (* bugpoint_keep *) attribute\n"); - log(" will be skipped.\n"); + log(" try to remove modules.\n"); log("\n"); log(" -ports\n"); - log(" try to remove module ports. ports with a (* bugpoint_keep *) attribute\n"); - log(" will be skipped (useful for clocks, resets, etc.)\n"); + log(" try to remove module ports.\n"); log("\n"); log(" -cells\n"); - log(" try to remove cells. cells with a (* bugpoint_keep *) attribute will\n"); - log(" be skipped.\n"); + log(" try to remove cells.\n"); log("\n"); log(" -connections\n"); log(" try to reconnect ports to 'x.\n"); @@ -119,8 +114,8 @@ struct BugpointPass : public Pass { return design; RTLIL::Design *design_copy = new RTLIL::Design; - for (auto module : design->modules()) - design_copy->add(module->clone()); + for (auto &it : design->modules_) + design_copy->add(it.second->clone()); Pass::call(design_copy, "proc_clean -quiet"); Pass::call(design_copy, "clean -purge"); @@ -132,32 +127,24 @@ struct BugpointPass : public Pass { RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections, bool assigns, bool updates) { RTLIL::Design *design_copy = new RTLIL::Design; - for (auto module : design->modules()) - design_copy->add(module->clone()); + for (auto &it : design->modules_) + design_copy->add(it.second->clone()); int index = 0; if (modules) { - Module *removed_module = nullptr; - for (auto module : design_copy->modules()) + for (auto &it : design_copy->modules_) { - if (module->get_blackbox_attribute()) + if (it.second->get_blackbox_attribute()) continue; - if (module->get_bool_attribute(ID::bugpoint_keep)) - continue; - if (index++ == seed) { - log_header(design, "Trying to remove module %s.\n", log_id(module)); - removed_module = module; - break; + log("Trying to remove module %s.\n", it.first.c_str()); + design_copy->remove(it.second); + return design_copy; } } - if (removed_module) { - design_copy->remove(removed_module); - return design_copy; - } } if (ports) { @@ -168,21 +155,18 @@ struct BugpointPass : public Pass { for (auto wire : mod->wires()) { - if (!wire->port_id) - continue; - - if (!stage2 && wire->get_bool_attribute(ID($bugpoint))) + if (!stage2 && wire->get_bool_attribute("$bugpoint")) continue; - if (wire->get_bool_attribute(ID::bugpoint_keep)) - continue; - - if (index++ == seed) + if (wire->port_input || wire->port_output) { - log_header(design, "Trying to remove module port %s.\n", log_id(wire)); - wire->port_input = wire->port_output = false; - mod->fixup_ports(); - return design_copy; + if (index++ == seed) + { + log("Trying to remove module port %s.\n", log_signal(wire)); + wire->port_input = wire->port_output = false; + mod->fixup_ports(); + return design_copy; + } } } } @@ -194,24 +178,15 @@ struct BugpointPass : public Pass { if (mod->get_blackbox_attribute()) continue; - - Cell *removed_cell = nullptr; - for (auto cell : mod->cells()) + for (auto &it : mod->cells_) { - if (cell->get_bool_attribute(ID::bugpoint_keep)) - continue; - if (index++ == seed) { - log_header(design, "Trying to remove cell %s.%s.\n", log_id(mod), log_id(cell)); - removed_cell = cell; - break; + log("Trying to remove cell %s.%s.\n", mod->name.c_str(), it.first.c_str()); + mod->remove(it.second); + return design_copy; } } - if (removed_cell) { - mod->remove(removed_cell); - return design_copy; - } } } if (connections) @@ -234,7 +209,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove cell port %s.%s.%s.\n", log_id(mod), log_id(cell), log_id(it.first)); + log("Trying to remove cell port %s.%s.%s.\n", mod->name.c_str(), cell->name.c_str(), it.first.c_str()); RTLIL::SigSpec port_x(State::Sx, port.size()); cell->unsetPort(it.first); cell->setPort(it.first, port_x); @@ -243,9 +218,9 @@ struct BugpointPass : public Pass { if (!stage2 && (cell->input(it.first) || cell->output(it.first)) && index++ == seed) { - log_header(design, "Trying to expose cell port %s.%s.%s as module port.\n", log_id(mod), log_id(cell), log_id(it.first)); + log("Trying to expose cell port %s.%s.%s as module port.\n", mod->name.c_str(), cell->name.c_str(), it.first.c_str()); RTLIL::Wire *wire = mod->addWire(NEW_ID, port.size()); - wire->set_bool_attribute(ID($bugpoint)); + wire->set_bool_attribute("$bugpoint"); wire->port_input = cell->input(it.first); wire->port_output = cell->output(it.first); cell->unsetPort(it.first); @@ -275,7 +250,7 @@ struct BugpointPass : public Pass { { if (index++ == seed) { - log_header(design, "Trying to remove assign %s %s in %s.%s.\n", log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first)); + log("Trying to remove assign %s %s in %s.%s.\n", log_signal((*it).first), log_signal((*it).second), mod->name.c_str(), pr.first.c_str()); cs->actions.erase(it); return design_copy; } @@ -301,7 +276,7 @@ struct BugpointPass : public Pass { { if (index++ == seed) { - log_header(design, "Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first)); + log("Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal((*it).first), log_signal((*it).second), mod->name.c_str(), pr.first.c_str()); sy->actions.erase(it); return design_copy; } @@ -310,18 +285,15 @@ struct BugpointPass : public Pass { } } } - return nullptr; + return NULL; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string yosys_cmd = "yosys", script, grep; bool fast = false, clean = false; bool modules = false, ports = false, cells = false, connections = false, assigns = false, updates = false, has_part = false; - log_header(design, "Executing BUGPOINT pass (minimize testcases).\n"); - log_push(); - size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -461,12 +433,10 @@ struct BugpointPass : public Pass { { Pass::call(design, "design -reset"); crashing_design = clean_design(crashing_design, clean, /*do_delete=*/true); - for (auto module : crashing_design->modules()) - design->add(module->clone()); + for (auto &it : crashing_design->modules_) + design->add(it.second->clone()); delete crashing_design; } - - log_pop(); } } BugpointPass; diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index a8b5362b32c..820ecac7b34 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct CheckPass : public Pass { CheckPass() : Pass("check", "check for obvious problems in the design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -61,7 +61,7 @@ struct CheckPass : public Pass { log(" Produce a runtime error if any problems are found in the current design.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { int counter = 0; bool noinit = false; @@ -98,6 +98,49 @@ struct CheckPass : public Pass { log_header(design, "Executing CHECK pass (checking for obvious problems).\n"); + pool fftypes; + fftypes.insert("$sr"); + fftypes.insert("$ff"); + fftypes.insert("$dff"); + fftypes.insert("$dffe"); + fftypes.insert("$dffsr"); + fftypes.insert("$adff"); + fftypes.insert("$dlatch"); + fftypes.insert("$dlatchsr"); + fftypes.insert("$_DFFE_NN_"); + fftypes.insert("$_DFFE_NP_"); + fftypes.insert("$_DFFE_PN_"); + fftypes.insert("$_DFFE_PP_"); + fftypes.insert("$_DFFSR_NNN_"); + fftypes.insert("$_DFFSR_NNP_"); + fftypes.insert("$_DFFSR_NPN_"); + fftypes.insert("$_DFFSR_NPP_"); + fftypes.insert("$_DFFSR_PNN_"); + fftypes.insert("$_DFFSR_PNP_"); + fftypes.insert("$_DFFSR_PPN_"); + fftypes.insert("$_DFFSR_PPP_"); + fftypes.insert("$_DFF_NN0_"); + fftypes.insert("$_DFF_NN1_"); + fftypes.insert("$_DFF_NP0_"); + fftypes.insert("$_DFF_NP1_"); + fftypes.insert("$_DFF_N_"); + fftypes.insert("$_DFF_PN0_"); + fftypes.insert("$_DFF_PN1_"); + fftypes.insert("$_DFF_PP0_"); + fftypes.insert("$_DFF_PP1_"); + fftypes.insert("$_DFF_P_"); + fftypes.insert("$_DLATCHSR_NNN_"); + fftypes.insert("$_DLATCHSR_NNP_"); + fftypes.insert("$_DLATCHSR_NPN_"); + fftypes.insert("$_DLATCHSR_NPP_"); + fftypes.insert("$_DLATCHSR_PNN_"); + fftypes.insert("$_DLATCHSR_PNP_"); + fftypes.insert("$_DLATCHSR_PPN_"); + fftypes.insert("$_DLATCHSR_PPP_"); + fftypes.insert("$_DLATCH_N_"); + fftypes.insert("$_DLATCH_P_"); + fftypes.insert("$_FF_"); + for (auto module : design->selected_whole_modules_warn()) { if (module->has_processes_warn()) @@ -159,8 +202,8 @@ struct CheckPass : public Pass { if (wire->port_input && !wire->port_output) for (auto bit : sigmap(wire)) if (bit.wire) wire_drivers_count[bit]++; - if (wire->attributes.count(ID::init)) { - Const initval = wire->attributes.at(ID::init); + if (wire->attributes.count("\\init")) { + Const initval = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) if (initval[i] == State::S0 || initval[i] == State::S1) init_bits.insert(sigmap(SigBit(wire, i))); @@ -199,10 +242,10 @@ struct CheckPass : public Pass { { for (auto cell : module->cells()) { - if (RTLIL::builtin_ff_cell_types().count(cell->type) == 0) + if (fftypes.count(cell->type) == 0) continue; - for (auto bit : sigmap(cell->getPort(ID::Q))) + for (auto bit : sigmap(cell->getPort("\\Q"))) init_bits.erase(bit); } diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc index a1b3fbef792..7e32da65f85 100644 --- a/passes/cmds/chformal.cc +++ b/passes/cmds/chformal.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct ChformalPass : public Pass { ChformalPass() : Pass("chformal", "change formal constraints of the design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -62,7 +62,7 @@ struct ChformalPass : public Pass { log(" change the roles of cells as indicated. these options can be combined\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool assert2assume = false; bool assume2assert = false; @@ -77,23 +77,23 @@ struct ChformalPass : public Pass { for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-assert") { - constr_types.insert(ID($assert)); + constr_types.insert("$assert"); continue; } if (args[argidx] == "-assume") { - constr_types.insert(ID($assume)); + constr_types.insert("$assume"); continue; } if (args[argidx] == "-live") { - constr_types.insert(ID($live)); + constr_types.insert("$live"); continue; } if (args[argidx] == "-fair") { - constr_types.insert(ID($fair)); + constr_types.insert("$fair"); continue; } if (args[argidx] == "-cover") { - constr_types.insert(ID($cover)); + constr_types.insert("$cover"); continue; } if (mode == 0 && args[argidx] == "-remove") { @@ -139,11 +139,11 @@ struct ChformalPass : public Pass { extra_args(args, argidx, design); if (constr_types.empty()) { - constr_types.insert(ID($assert)); - constr_types.insert(ID($assume)); - constr_types.insert(ID($live)); - constr_types.insert(ID($fair)); - constr_types.insert(ID($cover)); + constr_types.insert("$assert"); + constr_types.insert("$assume"); + constr_types.insert("$live"); + constr_types.insert("$fair"); + constr_types.insert("$cover"); } if (mode == 0) @@ -171,11 +171,11 @@ struct ChformalPass : public Pass { for (auto wire : module->wires()) { - if (wire->attributes.count(ID::init) == 0) + if (wire->attributes.count("\\init") == 0) continue; SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) { if (initval[i] == State::S0) @@ -187,17 +187,17 @@ struct ChformalPass : public Pass { for (auto cell : module->selected_cells()) { - if (cell->type == ID($ff)) { - SigSpec D = sigmap(cell->getPort(ID::D)); - SigSpec Q = sigmap(cell->getPort(ID::Q)); + if (cell->type == "$ff") { + SigSpec D = sigmap(cell->getPort("\\D")); + SigSpec Q = sigmap(cell->getPort("\\Q")); for (int i = 0; i < GetSize(D); i++) ffmap[Q[i]] = make_pair(D[i], make_pair(State::Sm, false)); } - if (cell->type == ID($dff)) { - SigSpec D = sigmap(cell->getPort(ID::D)); - SigSpec Q = sigmap(cell->getPort(ID::Q)); - SigSpec C = sigmap(cell->getPort(ID::CLK)); - bool clockpol = cell->getParam(ID::CLK_POLARITY).as_bool(); + if (cell->type == "$dff") { + SigSpec D = sigmap(cell->getPort("\\D")); + SigSpec Q = sigmap(cell->getPort("\\Q")); + SigSpec C = sigmap(cell->getPort("\\CLK")); + bool clockpol = cell->getParam("\\CLK_POLARITY").as_bool(); for (int i = 0; i < GetSize(D); i++) ffmap[Q[i]] = make_pair(D[i], make_pair(C, clockpol)); } @@ -206,15 +206,15 @@ struct ChformalPass : public Pass { for (auto cell : constr_cells) while (true) { - SigSpec A = sigmap(cell->getPort(ID::A)); - SigSpec EN = sigmap(cell->getPort(ID::EN)); + SigSpec A = sigmap(cell->getPort("\\A")); + SigSpec EN = sigmap(cell->getPort("\\EN")); if (ffmap.count(A) == 0 || ffmap.count(EN) == 0) break; if (!init_zero.count(EN)) { - if (cell->type == ID($cover)) break; - if (cell->type.in(ID($assert), ID($assume)) && !init_one.count(A)) break; + if (cell->type == "$cover") break; + if (cell->type.in("$assert", "$assume") && !init_one.count(A)) break; } const auto &A_map = ffmap.at(A); @@ -223,8 +223,8 @@ struct ChformalPass : public Pass { if (A_map.second != EN_map.second) break; - cell->setPort(ID::A, A_map.first); - cell->setPort(ID::EN, EN_map.first); + cell->setPort("\\A", A_map.first); + cell->setPort("\\EN", EN_map.first); } } else @@ -233,18 +233,18 @@ struct ChformalPass : public Pass { for (auto cell : constr_cells) for (int i = 0; i < mode_arg; i++) { - SigSpec orig_a = cell->getPort(ID::A); - SigSpec orig_en = cell->getPort(ID::EN); + SigSpec orig_a = cell->getPort("\\A"); + SigSpec orig_en = cell->getPort("\\EN"); Wire *new_a = module->addWire(NEW_ID); Wire *new_en = module->addWire(NEW_ID); - new_en->attributes[ID::init] = State::S0; + new_en->attributes["\\init"] = State::S0; module->addFf(NEW_ID, orig_a, new_a); module->addFf(NEW_ID, orig_en, new_en); - cell->setPort(ID::A, new_a); - cell->setPort(ID::EN, new_en); + cell->setPort("\\A", new_a); + cell->setPort("\\EN", new_en); } } else @@ -254,26 +254,26 @@ struct ChformalPass : public Pass { for (int i = 0; i < mode_arg; i++) { Wire *w = module->addWire(NEW_ID); - w->attributes[ID::init] = State::S0; + w->attributes["\\init"] = State::S0; module->addFf(NEW_ID, en, w); en = w; } for (auto cell : constr_cells) - cell->setPort(ID::EN, module->LogicAnd(NEW_ID, en, cell->getPort(ID::EN))); + cell->setPort("\\EN", module->LogicAnd(NEW_ID, en, cell->getPort("\\EN"))); } else if (mode == 'c') { for (auto cell : constr_cells) - if (assert2assume && cell->type == ID($assert)) - cell->type = ID($assume); - else if (assume2assert && cell->type == ID($assume)) - cell->type = ID($assert); - else if (live2fair && cell->type == ID($live)) - cell->type = ID($fair); - else if (fair2live && cell->type == ID($fair)) - cell->type = ID($live); + if (assert2assume && cell->type == "$assert") + cell->type = "$assume"; + else if (assume2assert && cell->type == "$assume") + cell->type = "$assert"; + else if (live2fair && cell->type == "$live") + cell->type = "$fair"; + else if (fair2live && cell->type == "$fair") + cell->type = "$live"; } } } diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc index b894f334cff..979aeadd450 100644 --- a/passes/cmds/chtype.cc +++ b/passes/cmds/chtype.cc @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN struct ChtypePass : public Pass { ChtypePass() : Pass("chtype", "change type of cells in the design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -40,7 +40,7 @@ struct ChtypePass : public Pass { log("\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { IdString set_type; dict map_types; diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc index 0cc6cbe52a0..f93bada2790 100644 --- a/passes/cmds/connect.cc +++ b/passes/cmds/connect.cc @@ -32,9 +32,9 @@ static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap & RTLIL::Wire *dummy_wire = module->addWire(NEW_ID, sig.size()); - for (auto cell : module->cells()) - for (auto &port : cell->connections_) - if (ct.cell_output(cell->type, port.first)) + for (auto &it : module->cells_) + for (auto &port : it.second->connections_) + if (ct.cell_output(it.second->type, port.first)) sigmap(port.second).replace(sig, dummy_wire, &port.second); for (auto &conn : module->connections_) @@ -43,7 +43,7 @@ static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap & struct ConnectPass : public Pass { ConnectPass() : Pass("connect", "create or remove connections") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -75,15 +75,17 @@ struct ConnectPass : public Pass { log("This command does not operate on module with processes.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - RTLIL::Module *module = nullptr; - for (auto mod : design->selected_modules()) { - if (module != nullptr) - log_cmd_error("Multiple modules selected: %s, %s\n", log_id(module->name), log_id(mod->name)); - module = mod; + RTLIL::Module *module = NULL; + for (auto &it : design->modules_) { + if (!design->selected(it.second)) + continue; + if (module != NULL) + log_cmd_error("Multiple modules selected: %s, %s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(it.first)); + module = it.second; } - if (module == nullptr) + if (module == NULL) log_cmd_error("No modules selected.\n"); if (!module->processes.empty()) log_cmd_error("Found processes in selected module.\n"); @@ -128,7 +130,7 @@ struct ConnectPass : public Pass { std::vector lhs = it.first.to_sigbit_vector(); std::vector rhs = it.first.to_sigbit_vector(); for (size_t i = 0; i < lhs.size(); i++) - if (rhs[i].wire != nullptr) + if (rhs[i].wire != NULL) sigmap.add(lhs[i], rhs[i]); } @@ -170,14 +172,14 @@ struct ConnectPass : public Pass { if (flag_nounset) log_cmd_error("Can't use -port together with -nounset.\n"); - if (module->cell(RTLIL::escape_id(port_cell)) == nullptr) + if (module->cells_.count(RTLIL::escape_id(port_cell)) == 0) log_cmd_error("Can't find cell %s.\n", port_cell.c_str()); RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, port_expr)) log_cmd_error("Failed to parse port expression `%s'.\n", port_expr.c_str()); - module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig)); + module->cells_.at(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig)); } else log_cmd_error("Expected -set, -unset, or -port.\n"); diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc index 9235dda2b47..5a15cbbaf20 100644 --- a/passes/cmds/connwrappers.cc +++ b/passes/cmds/connwrappers.cc @@ -65,13 +65,15 @@ struct ConnwrappersWorker decls[key] = decl; } - void work(RTLIL::Module *module) + void work(RTLIL::Design *design, RTLIL::Module *module) { std::map> extend_map; SigMap sigmap(module); - for (auto cell : module->cells()) + for (auto &it : module->cells_) { + RTLIL::Cell *cell = it.second; + if (!decl_celltypes.count(cell->type)) continue; @@ -103,8 +105,13 @@ struct ConnwrappersWorker } } - for (auto cell : module->selected_cells()) + for (auto &it : module->cells_) { + RTLIL::Cell *cell = it.second; + + if (!design->selected(module, cell)) + continue; + for (auto &conn : cell->connections_) { std::vector sigbits = sigmap(conn.second).to_sigbit_vector(); @@ -134,8 +141,8 @@ struct ConnwrappersWorker } if (old_sig.size()) - log("Connected extended bits of %s.%s:%s: %s -> %s\n", log_id(module->name), log_id(cell->name), - log_id(conn.first), log_signal(old_sig), log_signal(conn.second)); + log("Connected extended bits of %s.%s:%s: %s -> %s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), + RTLIL::id2cstr(conn.first), log_signal(old_sig), log_signal(conn.second)); } } } @@ -143,7 +150,7 @@ struct ConnwrappersWorker struct ConnwrappersPass : public Pass { ConnwrappersPass() : Pass("connwrappers", "match width of input-output port pairs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -165,7 +172,7 @@ struct ConnwrappersPass : public Pass { log("The options -signed, -unsigned, and -port can be specified multiple times.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { ConnwrappersWorker worker; @@ -193,8 +200,9 @@ struct ConnwrappersPass : public Pass { log_header(design, "Executing CONNWRAPPERS pass (connect extended ports of wrapper cells).\n"); - for (auto module : design->selected_modules()) - worker.work(module); + for (auto &mod_it : design->modules_) + if (design->selected(mod_it.second)) + worker.work(design, mod_it.second); } } ConnwrappersPass; diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc index c351065f35e..acd2dba5295 100644 --- a/passes/cmds/copy.cc +++ b/passes/cmds/copy.cc @@ -26,7 +26,7 @@ PRIVATE_NAMESPACE_BEGIN struct CopyPass : public Pass { CopyPass() : Pass("copy", "copy modules in the design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -36,7 +36,7 @@ struct CopyPass : public Pass { log("by this command.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { if (args.size() != 3) log_cmd_error("Invalid number of arguments!\n"); @@ -44,10 +44,10 @@ struct CopyPass : public Pass { std::string src_name = RTLIL::escape_id(args[1]); std::string trg_name = RTLIL::escape_id(args[2]); - if (design->module(src_name) == nullptr) + if (design->modules_.count(src_name) == 0) log_cmd_error("Can't find source module %s.\n", src_name.c_str()); - if (design->module(trg_name) != nullptr) + if (design->modules_.count(trg_name) != 0) log_cmd_error("Target module name %s already exists.\n", trg_name.c_str()); RTLIL::Module *new_mod = design->module(src_name)->clone(); diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index 0867e3b4f25..628ac4c5e56 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -35,7 +35,7 @@ PRIVATE_NAMESPACE_BEGIN struct CoverPass : public Pass { CoverPass() : Pass("cover", "print code coverage counters") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -83,7 +83,7 @@ struct CoverPass : public Pass { log("Coverage counters are only available in Yosys for Linux.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::vector out_files; std::vector patterns; @@ -101,8 +101,8 @@ struct CoverPass : public Pass { const std::string &filename = args[++argidx]; FILE *f = nullptr; if (args[argidx-1] == "-d") { - #if defined(_WIN32) || defined(__wasm) - log_cmd_error("The 'cover -d' option is not supported on this platform.\n"); + #ifdef _WIN32 + log_cmd_error("The 'cover -d' option is not supported on win32.\n"); #else char filename_buffer[4096]; snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", filename.c_str(), getpid()); diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index 684fa37b047..5822c09f888 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN struct DeletePass : public Pass { DeletePass() : Pass("delete", "delete objects in the design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -40,7 +40,7 @@ struct DeletePass : public Pass { log("selected wires, thus 'deleting' module ports.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_input = false; bool flag_output = false; @@ -65,24 +65,27 @@ struct DeletePass : public Pass { } extra_args(args, argidx, design); - std::vector delete_mods; - for (auto module : design->modules()) + std::vector delete_mods; + + for (auto &mod_it : design->modules_) { - if (design->selected_whole_module(module->name) && !flag_input && !flag_output) { - delete_mods.push_back(module); + if (design->selected_whole_module(mod_it.first) && !flag_input && !flag_output) { + delete_mods.push_back(mod_it.first); continue; } - if (!design->selected_module(module->name)) + if (!design->selected_module(mod_it.first)) continue; + RTLIL::Module *module = mod_it.second; + if (flag_input || flag_output) { - for (auto wire : module->wires()) - if (design->selected(module, wire)) { + for (auto &it : module->wires_) + if (design->selected(module, it.second)) { if (flag_input) - wire->port_input = false; + it.second->port_input = false; if (flag_output) - wire->port_output = false; + it.second->port_output = false; } module->fixup_ports(); continue; @@ -93,19 +96,20 @@ struct DeletePass : public Pass { pool delete_procs; pool delete_mems; - for (auto wire : module->selected_wires()) - delete_wires.insert(wire); + for (auto &it : module->wires_) + if (design->selected(module, it.second)) + delete_wires.insert(it.second); for (auto &it : module->memories) if (design->selected(module, it.second)) delete_mems.insert(it.first); - for (auto cell : module->cells()) { - if (design->selected(module, cell)) - delete_cells.insert(cell); - if (cell->type.in(ID($memrd), ID($memwr)) && - delete_mems.count(cell->parameters.at(ID::MEMID).decode_string()) != 0) - delete_cells.insert(cell); + for (auto &it : module->cells_) { + if (design->selected(module, it.second)) + delete_cells.insert(it.second); + if (it.second->type.in("$memrd", "$memwr") && + delete_mems.count(it.second->parameters.at("\\MEMID").decode_string()) != 0) + delete_cells.insert(it.second); } for (auto &it : module->processes) @@ -130,8 +134,9 @@ struct DeletePass : public Pass { module->fixup_ports(); } - for (auto mod : delete_mods) { - design->remove(mod); + for (auto &it : delete_mods) { + delete design->modules_.at(it); + design->modules_.erase(it); } } } DeletePass; diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index 2d7ba1fef06..172addcc130 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -18,7 +18,6 @@ */ #include "kernel/yosys.h" -#include "frontends/verilog/preproc.h" #include "frontends/ast/ast.h" YOSYS_NAMESPACE_BEGIN @@ -28,7 +27,7 @@ std::vector pushed_designs; struct DesignPass : public Pass { DesignPass() : Pass("design", "save, restore and reset current design") { } - ~DesignPass() override { + ~DesignPass() YS_OVERRIDE { for (auto &it : saved_designs) delete it.second; saved_designs.clear(); @@ -36,7 +35,7 @@ struct DesignPass : public Pass { delete it; pushed_designs.clear(); } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -60,11 +59,6 @@ struct DesignPass : public Pass { log("Push the current design to the stack and then clear the current design.\n"); log("\n"); log("\n"); - log(" design -push-copy\n"); - log("\n"); - log("Push the current design to the stack without clearing the current design.\n"); - log("\n"); - log("\n"); log(" design -pop\n"); log("\n"); log("Reset the current design and pop the last design from the stack.\n"); @@ -99,23 +93,17 @@ struct DesignPass : public Pass { log("The Verilog front-end remembers defined macros and top-level declarations\n"); log("between calls to 'read_verilog'. This command resets this memory.\n"); log("\n"); - log(" design -delete \n"); - log("\n"); - log("Delete the design previously saved under the given name.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool got_mode = false; bool reset_mode = false; bool reset_vlog_mode = false; bool push_mode = false; - bool push_copy_mode = false; bool pop_mode = false; bool import_mode = false; RTLIL::Design *copy_from_design = NULL, *copy_to_design = NULL; - std::string save_name, load_name, as_name, delete_name; + std::string save_name, load_name, as_name; std::vector copy_src_modules; size_t argidx; @@ -137,11 +125,6 @@ struct DesignPass : public Pass { push_mode = true; continue; } - if (!got_mode && args[argidx] == "-push-copy") { - got_mode = true; - push_copy_mode = true; - continue; - } if (!got_mode && args[argidx] == "-pop") { got_mode = true; pop_mode = true; @@ -195,13 +178,6 @@ struct DesignPass : public Pass { as_name = args[++argidx]; continue; } - if (!got_mode && args[argidx] == "-delete" && argidx+1 < args.size()) { - got_mode = true; - delete_name = args[++argidx]; - if (saved_designs.count(delete_name) == 0) - log_cmd_error("No saved design '%s' found!\n", delete_name.c_str()); - continue; - } break; } @@ -218,30 +194,24 @@ struct DesignPass : public Pass { argidx = args.size(); } - for (auto mod : copy_from_design->modules()) { - if (sel.selected_whole_module(mod->name)) { - copy_src_modules.push_back(mod); + for (auto &it : copy_from_design->modules_) { + if (sel.selected_whole_module(it.first)) { + copy_src_modules.push_back(it.second); continue; } - if (sel.selected_module(mod->name)) - log_cmd_error("Module %s is only partly selected.\n", log_id(mod->name)); + if (sel.selected_module(it.first)) + log_cmd_error("Module %s is only partly selected.\n", RTLIL::id2cstr(it.first)); } if (import_mode) { - std::vector candidates; for (auto module : copy_src_modules) { - if (module->get_bool_attribute(ID::top)) { - candidates.clear(); - candidates.push_back(module); + if (module->get_bool_attribute("\\top")) { + copy_src_modules.clear(); + copy_src_modules.push_back(module); break; } - if (!module->get_blackbox_attribute()) - candidates.push_back(module); } - - if (GetSize(candidates) == 1) - copy_src_modules = std::move(candidates); } } @@ -260,8 +230,8 @@ struct DesignPass : public Pass { pool queue; dict done; - if (copy_to_design->module(prefix) != nullptr) - copy_to_design->remove(copy_to_design->module(prefix)); + if (copy_to_design->modules_.count(prefix)) + delete copy_to_design->modules_.at(prefix); if (GetSize(copy_src_modules) != 1) log_cmd_error("No top module found in source design.\n"); @@ -270,13 +240,12 @@ struct DesignPass : public Pass { { log("Importing %s as %s.\n", log_id(mod), log_id(prefix)); - RTLIL::Module *t = mod->clone(); - t->name = prefix; - t->design = copy_to_design; - t->attributes.erase(ID::top); - copy_to_design->add(t); + copy_to_design->modules_[prefix] = mod->clone(); + copy_to_design->modules_[prefix]->name = prefix; + copy_to_design->modules_[prefix]->design = copy_to_design; + copy_to_design->modules_[prefix]->attributes.erase("\\top"); - queue.insert(t); + queue.insert(copy_to_design->modules_[prefix]); done[mod->name] = prefix; } @@ -299,16 +268,15 @@ struct DesignPass : public Pass { log("Importing %s as %s.\n", log_id(fmod), log_id(trg_name)); - if (copy_to_design->module(trg_name) != nullptr) - copy_to_design->remove(copy_to_design->module(trg_name)); + if (copy_to_design->modules_.count(trg_name)) + delete copy_to_design->modules_.at(trg_name); - RTLIL::Module *t = fmod->clone(); - t->name = trg_name; - t->design = copy_to_design; - t->attributes.erase(ID::top); - copy_to_design->add(t); + copy_to_design->modules_[trg_name] = fmod->clone(); + copy_to_design->modules_[trg_name]->name = trg_name; + copy_to_design->modules_[trg_name]->design = copy_to_design; + copy_to_design->modules_[trg_name]->attributes.erase("\\top"); - queue.insert(t); + queue.insert(copy_to_design->modules_[trg_name]); done[cell->type] = trg_name; } @@ -326,22 +294,21 @@ struct DesignPass : public Pass { { std::string trg_name = as_name.empty() ? mod->name.str() : RTLIL::escape_id(as_name); - if (copy_to_design->module(trg_name) != nullptr) - copy_to_design->remove(copy_to_design->module(trg_name)); + if (copy_to_design->modules_.count(trg_name)) + delete copy_to_design->modules_.at(trg_name); - RTLIL::Module *t = mod->clone(); - t->name = trg_name; - t->design = copy_to_design; - copy_to_design->add(t); + copy_to_design->modules_[trg_name] = mod->clone(); + copy_to_design->modules_[trg_name]->name = trg_name; + copy_to_design->modules_[trg_name]->design = copy_to_design; } } - if (!save_name.empty() || push_mode || push_copy_mode) + if (!save_name.empty() || push_mode) { RTLIL::Design *design_copy = new RTLIL::Design; - for (auto mod : design->modules()) - design_copy->add(mod->clone()); + for (auto &it : design->modules_) + design_copy->add(it.second->clone()); design_copy->selection_stack = design->selection_stack; design_copy->selection_vars = design->selection_vars; @@ -350,7 +317,7 @@ struct DesignPass : public Pass { if (saved_designs.count(save_name)) delete saved_designs.at(save_name); - if (push_mode || push_copy_mode) + if (push_mode) pushed_designs.push_back(design_copy); else saved_designs[save_name] = design_copy; @@ -358,8 +325,9 @@ struct DesignPass : public Pass { if (reset_mode || !load_name.empty() || push_mode || pop_mode) { - for (auto mod : design->modules().to_vector()) - design->remove(mod); + for (auto &it : design->modules_) + delete it.second; + design->modules_.clear(); design->selection_stack.clear(); design->selection_vars.clear(); @@ -378,15 +346,15 @@ struct DesignPass : public Pass { delete node; design->verilog_globals.clear(); - design->verilog_defines->clear(); + design->verilog_defines.clear(); } if (!load_name.empty() || pop_mode) { RTLIL::Design *saved_design = pop_mode ? pushed_designs.back() : saved_designs.at(load_name); - for (auto mod : saved_design->modules()) - design->add(mod->clone()); + for (auto &it : saved_design->modules_) + design->add(it.second->clone()); design->selection_stack = saved_design->selection_stack; design->selection_vars = saved_design->selection_vars; @@ -397,14 +365,6 @@ struct DesignPass : public Pass { pushed_designs.pop_back(); } } - - if (!delete_name.empty()) - { - auto it = saved_designs.find(delete_name); - log_assert(it != saved_designs.end()); - delete it->second; - saved_designs.erase(it); - } } } DesignPass; diff --git a/passes/cmds/edgetypes.cc b/passes/cmds/edgetypes.cc index 37c4204002e..58ed6457dea 100644 --- a/passes/cmds/edgetypes.cc +++ b/passes/cmds/edgetypes.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct EdgetypePass : public Pass { EdgetypePass() : Pass("edgetypes", "list all types of edges in selection") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -35,7 +35,7 @@ struct EdgetypePass : public Pass { log("is a 4-tuple of source and sink cell type and port name.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc deleted file mode 100644 index 951fa53fc44..00000000000 --- a/passes/cmds/exec.cc +++ /dev/null @@ -1,205 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 - 2020 Claire Wolf - * - * 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/register.h" -#include "kernel/log.h" -#include - -#if defined(_WIN32) -# include -# define WIFEXITED(x) 1 -# define WIFSIGNALED(x) 0 -# define WIFSTOPPED(x) 0 -# define WEXITSTATUS(x) ((x) & 0xff) -# define WTERMSIG(x) SIGTERM -# define WSTOPSIG(x) 0 -#else -# include -#endif - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct ExecPass : public Pass { - ExecPass() : Pass("exec", "execute commands in the operating system shell") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" exec [options] -- [command]\n"); - log("\n"); - log("Execute a command in the operating system shell. All supplied arguments are\n"); - log("concatenated and passed as a command to popen(3). Whitespace is not guaranteed\n"); - log("to be preserved, even if quoted. stdin and stderr are not connected, while stdout is\n"); - log("logged unless the \"-q\" option is specified.\n"); - log("\n"); - log("\n"); - log(" -q\n"); - log(" Suppress stdout and stderr from subprocess\n"); - log("\n"); - log(" -expect-return \n"); - log(" Generate an error if popen() does not return specified value.\n"); - log(" May only be specified once; the final specified value is controlling\n"); - log(" if specified multiple times.\n"); - log("\n"); - log(" -expect-stdout \n"); - log(" Generate an error if the specified regex does not match any line\n"); - log(" in subprocess's stdout. May be specified multiple times.\n"); - log("\n"); - log(" -not-expect-stdout \n"); - log(" Generate an error if the specified regex matches any line\n"); - log(" in subprocess's stdout. May be specified multiple times.\n"); - log("\n"); - log("\n"); - log(" Example: exec -q -expect-return 0 -- echo \"bananapie\" | grep \"nana\"\n"); - log("\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - std::string cmd = ""; - char buf[1024] = {}; - std::string linebuf = ""; - bool flag_cmd = false; - bool flag_quiet = false; - bool flag_expect_return = false; - int expect_return_value = 0; - bool flag_expect_stdout = false; - struct expect_stdout_elem { - bool matched; - bool polarity; //true: this regex must match at least one line - //false: this regex must not match any line - std::string str; - YS_REGEX_TYPE re; - - expect_stdout_elem() : matched(false), polarity(true), str(), re(){}; - }; - std::vector expect_stdout; - - if(args.size() == 0) - log_cmd_error("No command provided.\n"); - - for(size_t argidx = 1; argidx < args.size(); ++argidx) { - if (flag_cmd) { - cmd += args[argidx] + (argidx != (args.size() - 1)? " " : ""); - } else { - if (args[argidx] == "--") - flag_cmd = true; - else if (args[argidx] == "-q") - flag_quiet = true; - else if (args[argidx] == "-expect-return") { - flag_expect_return = true; - ++argidx; - if (argidx >= args.size()) - log_cmd_error("No expected return value specified.\n"); - - expect_return_value = atoi(args[argidx].c_str()); - } else if (args[argidx] == "-expect-stdout") { - flag_expect_stdout = true; - ++argidx; - if (argidx >= args.size()) - log_cmd_error("No expected regular expression specified.\n"); - - try{ - expect_stdout_elem x; - x.str = args[argidx]; - x.re = YS_REGEX_COMPILE(args[argidx]); - expect_stdout.push_back(x); - } catch (const YS_REGEX_NS::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", args[argidx].c_str()); - } - } else if (args[argidx] == "-not-expect-stdout") { - flag_expect_stdout = true; - ++argidx; - if (argidx >= args.size()) - log_cmd_error("No expected regular expression specified.\n"); - - try{ - expect_stdout_elem x; - x.str = args[argidx]; - x.re = YS_REGEX_COMPILE(args[argidx]); - x.polarity = false; - expect_stdout.push_back(x); - } catch (const YS_REGEX_NS::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", args[argidx].c_str()); - } - - } else - log_cmd_error("Unknown option \"%s\" or \"--\" doesn\'t precede command.", args[argidx].c_str()); - } - } - - log_header(design, "Executing command \"%s\".\n", cmd.c_str()); - log_push(); - - fflush(stdout); - bool keep_reading = true; - int status = 0; - int retval = 0; - -#ifndef EMSCRIPTEN - FILE *f = popen(cmd.c_str(), "r"); - if (f == nullptr) - log_cmd_error("errno %d after popen() returned NULL.\n", errno); - while (keep_reading) { - keep_reading = (fgets(buf, sizeof(buf), f) != nullptr); - linebuf += buf; - memset(buf, 0, sizeof(buf)); - - auto pos = linebuf.find('\n'); - while (pos != std::string::npos) { - std::string line = linebuf.substr(0, pos); - linebuf.erase(0, pos + 1); - if (!flag_quiet) - log("%s\n", line.c_str()); - - if (flag_expect_stdout) - for(auto &x : expect_stdout) - if (YS_REGEX_NS::regex_search(line, x.re)) - x.matched = true; - - pos = linebuf.find('\n'); - } - } - status = pclose(f); -#endif - - if(WIFEXITED(status)) { - retval = WEXITSTATUS(status); - } - else if(WIFSIGNALED(status)) { - retval = WTERMSIG(status); - } - else if(WIFSTOPPED(status)) { - retval = WSTOPSIG(status); - } - - if (flag_expect_return && retval != expect_return_value) - log_cmd_error("Return value %d did not match expected return value %d.\n", retval, expect_return_value); - - if (flag_expect_stdout) - for (auto &x : expect_stdout) - if (x.polarity ^ x.matched) - log_cmd_error("Command stdout did%s have a line matching given regex \"%s\".\n", (x.polarity? " not" : ""), x.str.c_str()); - - log_pop(); - } -} ExecPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/cmds/logcmd.cc b/passes/cmds/logcmd.cc index 12c43ecec59..522e1089d41 100644 --- a/passes/cmds/logcmd.cc +++ b/passes/cmds/logcmd.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct LogPass : public Pass { LogPass() : Pass("log", "print text and log files") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -52,7 +52,7 @@ struct LogPass : public Pass { log(" do not append a newline\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design*) override + void execute(std::vector args, RTLIL::Design*) YS_OVERRIDE { size_t argidx; bool to_stdout = false; diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc deleted file mode 100644 index 6a9ed603665..00000000000 --- a/passes/cmds/logger.cc +++ /dev/null @@ -1,185 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 Miodrag Milanovic - * - * 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/register.h" -#include "kernel/log.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct LoggerPass : public Pass { - LoggerPass() : Pass("logger", "set logger properties") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" logger [options]\n"); - log("\n"); - log("This command sets global logger properties, also available using command line\n"); - log("options.\n"); - log("\n"); - log(" -[no]time\n"); - log(" enable/disable display of timestamp in log output.\n"); - log("\n"); - log(" -[no]stderr\n"); - log(" enable/disable logging errors to stderr.\n"); - log("\n"); - log(" -warn regex\n"); - log(" print a warning for all log messages matching the regex.\n"); - log("\n"); - log(" -nowarn regex\n"); - log(" if a warning message matches the regex, it is printed as regular\n"); - log(" message instead.\n"); - log("\n"); - log(" -werror regex\n"); - log(" if a warning message matches the regex, it is printed as error\n"); - log(" message instead and the tool terminates with a nonzero return code.\n"); - log("\n"); - log(" -[no]debug\n"); - log(" globally enable/disable debug log messages.\n"); - log("\n"); - log(" -experimental \n"); - log(" do not print warnings for the specified experimental feature\n"); - log("\n"); - log(" -expect \n"); - log(" expect log, warning or error to appear. matched errors will terminate\n"); - log(" with exit code 0.\n"); - log("\n"); - log(" -expect-no-warnings\n"); - log(" gives error in case there is at least one warning that is not expected.\n"); - log("\n"); - } - - void execute(std::vector args, RTLIL::Design * design) override - { - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - - if (args[argidx] == "-time") { - log_time = true; - log("Enabled timestamp in logs.\n"); - continue; - } - if (args[argidx] == "-notime") { - log_time = false; - log("Disabled timestamp in logs.\n"); - continue; - } - if (args[argidx] == "-stderr") { - log_error_stderr = true; - log("Enabled loggint errors to stderr.\n"); - continue; - } - if (args[argidx] == "-nostderr") { - log_error_stderr = false; - log("Disabled loggint errors to stderr.\n"); - continue; - } - if (args[argidx] == "-warn" && argidx+1 < args.size()) { - std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); - try { - log("Added regex '%s' for warnings to warn list.\n", pattern.c_str()); - log_warn_regexes.push_back(YS_REGEX_COMPILE(pattern)); - } - catch (const YS_REGEX_NS::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); - } - continue; - } - if (args[argidx] == "-nowarn" && argidx+1 < args.size()) { - std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); - try { - log("Added regex '%s' for warnings to nowarn list.\n", pattern.c_str()); - log_nowarn_regexes.push_back(YS_REGEX_COMPILE(pattern)); - } - catch (const YS_REGEX_NS::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); - } - continue; - } - if (args[argidx] == "-werror" && argidx+1 < args.size()) { - std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); - try { - log("Added regex '%s' for warnings to werror list.\n", pattern.c_str()); - log_werror_regexes.push_back(YS_REGEX_COMPILE(pattern)); - } - catch (const YS_REGEX_NS::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); - } - continue; - } - if (args[argidx] == "-debug") { - log_force_debug = 1; - log("Enabled debug log messages.\n"); - continue; - } - if (args[argidx] == "-nodebug") { - log_force_debug = 0; - log("Disabled debug log messages.\n"); - continue; - } - if (args[argidx] == "-experimental" && argidx+1 < args.size()) { - std::string value = args[++argidx]; - log("Added '%s' experimental ignore list.\n", value.c_str()); - log_experimentals_ignored.insert(value); - continue; - } - if (args[argidx] == "-expect" && argidx+3 < args.size()) { - std::string type = args[++argidx]; - if (type!="error" && type!="warning" && type!="log") - log_cmd_error("Expect command require type to be 'log', 'warning' or 'error' !\n"); - if (type=="error" && log_expect_error.size()>0) - log_cmd_error("Only single error message can be expected !\n"); - std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); - int count = atoi(args[++argidx].c_str()); - if (count<=0) - log_cmd_error("Number of expected messages must be higher then 0 !\n"); - if (type=="error" && count!=1) - log_cmd_error("Expected error message occurrences must be 1 !\n"); - log("Added regex '%s' for warnings to expected %s list.\n", pattern.c_str(), type.c_str()); - try { - if (type == "error") - log_expect_error[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count); - else if (type == "warning") - log_expect_warning[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count); - else if (type == "log") - log_expect_log[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count); - else log_abort(); - } - catch (const YS_REGEX_NS::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); - } - continue; - } - if (args[argidx] == "-expect-no-warnings") { - log_expect_no_warnings = true; - continue; - } - break; - } - extra_args(args, argidx, design, false); - } -} LoggerPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc index 39ec432c263..05701710b2a 100644 --- a/passes/cmds/ltp.cc +++ b/passes/cmds/ltp.cc @@ -141,7 +141,7 @@ struct LtpWorker struct LtpPass : public Pass { LtpPass() : Pass("ltp", "print longest topological path") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -154,7 +154,7 @@ struct LtpPass : public Pass { log(" automatically exclude FF cell types\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool noff = false; diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc index 3ed19497d5e..4c16b56c400 100644 --- a/passes/cmds/plugin.cc +++ b/passes/cmds/plugin.cc @@ -99,7 +99,7 @@ void load_plugin(std::string, std::vector) struct PluginPass : public Pass { PluginPass() : Pass("plugin", "load and list loaded plugins") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -117,7 +117,7 @@ struct PluginPass : public Pass { log(" List loaded plugins\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string plugin_filename; std::vector plugin_aliases; diff --git a/passes/cmds/portlist.cc b/passes/cmds/portlist.cc index 97f4bfd9992..38c4a859711 100644 --- a/passes/cmds/portlist.cc +++ b/passes/cmds/portlist.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct PortlistPass : public Pass { PortlistPass() : Pass("portlist", "list (top-level) ports") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -39,7 +39,7 @@ struct PortlistPass : public Pass { log(" print verilog blackbox module definitions instead of port lists\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool m_mode = false; diff --git a/passes/cmds/printattrs.cc b/passes/cmds/printattrs.cc deleted file mode 100644 index 7973ac2625a..00000000000 --- a/passes/cmds/printattrs.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 Alberto Gonzalez - * - * 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" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct PrintAttrsPass : public Pass { - PrintAttrsPass() : Pass("printattrs", "print attributes of selected objects") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" printattrs [selection]\n"); - log("\n"); - log("Print all attributes of the selected objects.\n"); - log("\n"); - log("\n"); - } - - static std::string get_indent_str(const unsigned int indent) { - return stringf("%*s", indent, ""); - } - - static void log_const(const RTLIL::IdString &s, const RTLIL::Const &x, const unsigned int indent) { - if (x.flags == RTLIL::CONST_FLAG_STRING) - log("%s(* %s=\"%s\" *)\n", get_indent_str(indent).c_str(), log_id(s), x.decode_string().c_str()); - else if (x.flags == RTLIL::CONST_FLAG_NONE) - log("%s(* %s=%s *)\n", get_indent_str(indent).c_str(), log_id(s), x.as_string().c_str()); - else - log_assert(x.flags == RTLIL::CONST_FLAG_STRING || x.flags == RTLIL::CONST_FLAG_NONE); //intended to fail - } - - void execute(std::vector args, RTLIL::Design *design) override - { - size_t argidx = 1; - extra_args(args, argidx, design); - - unsigned int indent = 0; - for (auto mod : design->selected_modules()) - { - if (design->selected_whole_module(mod)) { - log("%s%s\n", get_indent_str(indent).c_str(), log_id(mod->name)); - indent += 2; - for (auto &it : mod->attributes) - log_const(it.first, it.second, indent); - } - - for (auto cell : mod->selected_cells()) { - log("%s%s\n", get_indent_str(indent).c_str(), log_id(cell->name)); - indent += 2; - for (auto &it : cell->attributes) - log_const(it.first, it.second, indent); - indent -= 2; - } - - for (auto wire : mod->selected_wires()) { - log("%s%s\n", get_indent_str(indent).c_str(), log_id(wire->name)); - indent += 2; - for (auto &it : wire->attributes) - log_const(it.first, it.second, indent); - indent -= 2; - } - - if (design->selected_whole_module(mod)) - indent -= 2; - } - - log("\n"); - } -} PrintAttrsPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc index cf0f6d0dea6..adbe89e315f 100644 --- a/passes/cmds/qwp.cc +++ b/passes/cmds/qwp.cc @@ -737,7 +737,7 @@ struct QwpWorker for (auto &node : nodes) if (node.cell != nullptr) - node.cell->attributes[ID::qwp_position] = stringf("%f %f", node.pos, node.alt_pos); + node.cell->attributes["\\qwp_position"] = stringf("%f %f", node.pos, node.alt_pos); vector edge_lengths; vector weighted_edge_lengths; @@ -778,7 +778,7 @@ struct QwpWorker struct QwpPass : public Pass { QwpPass() : Pass("qwp", "quadratic wirelength placer") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -808,7 +808,7 @@ struct QwpPass : public Pass { log("dense matrix operations. It is only a toy-placer for small circuits.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { QwpConfig config; xorshift32_state = 123456789; diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index 6326b4b15d2..9b1830b7b8a 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -32,27 +32,27 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: if (module->count_id(to_name)) log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name.c_str(), module->name.c_str()); - RTLIL::Wire *wire_to_rename = module->wire(from_name); - RTLIL::Cell *cell_to_rename = module->cell(from_name); + for (auto &it : module->wires_) + if (it.first == from_name) { + Wire *w = it.second; + log("Renaming wire %s to %s in module %s.\n", log_id(w), log_id(to_name), log_id(module)); + module->rename(w, to_name); + if (w->port_id || flag_output) { + if (flag_output) + w->port_output = true; + module->fixup_ports(); + } + return; + } - if (wire_to_rename != nullptr) { - log("Renaming wire %s to %s in module %s.\n", log_id(wire_to_rename), log_id(to_name), log_id(module)); - module->rename(wire_to_rename, to_name); - if (wire_to_rename->port_id || flag_output) { + for (auto &it : module->cells_) + if (it.first == from_name) { if (flag_output) - wire_to_rename->port_output = true; - module->fixup_ports(); + log_cmd_error("Called with -output but the specified object is a cell.\n"); + log("Renaming cell %s to %s in module %s.\n", log_id(it.second), log_id(to_name), log_id(module)); + module->rename(it.second, to_name); + return; } - return; - } - - if (cell_to_rename != nullptr) { - if (flag_output) - log_cmd_error("Called with -output but the specified object is a cell.\n"); - log("Renaming cell %s to %s in module %s.\n", log_id(cell_to_rename), log_id(to_name), log_id(module)); - module->rename(cell_to_rename, to_name); - return; - } log_cmd_error("Object `%s' not found!\n", from_name.c_str()); } @@ -66,26 +66,26 @@ static std::string derive_name_from_src(const std::string &src, int counter) return stringf("\\%s$%d", src_base.c_str(), counter); } -static IdString derive_name_from_cell_output_wire(const RTLIL::Cell *cell) +static IdString derive_name_from_wire(const RTLIL::Cell &cell) { // Find output const SigSpec *output = nullptr; int num_outputs = 0; - for (auto &connection : cell->connections()) { - if (cell->output(connection.first)) { + for (auto &connection : cell.connections()) { + if (cell.output(connection.first)) { output = &connection.second; num_outputs++; } } if (num_outputs != 1) // Skip cells thad drive multiple outputs - return cell->name; + return cell.name; std::string name = ""; for (auto &chunk : output->chunks()) { // Skip cells that drive privately named wires if (!chunk.wire || chunk.wire->name.str()[0] == '$') - return cell->name; + return cell.name; if (name != "") name += "$"; @@ -99,12 +99,12 @@ static IdString derive_name_from_cell_output_wire(const RTLIL::Cell *cell) } } - return name + cell->type.str(); + return name + cell.type.str(); } struct RenamePass : public Pass { RenamePass() : Pass("rename", "rename object in the design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -152,7 +152,7 @@ struct RenamePass : public Pass { log("Rename top module.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string pattern_prefix = "_", pattern_suffix = "_"; bool flag_src = false; @@ -210,25 +210,30 @@ struct RenamePass : public Pass { { extra_args(args, argidx, design); - for (auto module : design->selected_modules()) + for (auto &mod : design->modules_) { int counter = 0; - dict new_wire_names; - dict new_cell_names; - - for (auto wire : module->selected_wires()) - if (wire->name[0] == '$') - new_wire_names.emplace(wire, derive_name_from_src(wire->get_src_attribute(), counter++)); - - for (auto cell : module->selected_cells()) - if (cell->name[0] == '$') - new_cell_names.emplace(cell, derive_name_from_src(cell->get_src_attribute(), counter++)); - for (auto &it : new_wire_names) - module->rename(it.first, it.second); - - for (auto &it : new_cell_names) - module->rename(it.first, it.second); + RTLIL::Module *module = mod.second; + if (!design->selected(module)) + continue; + + dict new_wires; + for (auto &it : module->wires_) { + if (it.first[0] == '$' && design->selected(module, it.second)) + it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++); + new_wires[it.second->name] = it.second; + } + module->wires_.swap(new_wires); + module->fixup_ports(); + + dict new_cells; + for (auto &it : module->cells_) { + if (it.first[0] == '$' && design->selected(module, it.second)) + it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++); + new_cells[it.second->name] = it.second; + } + module->cells_.swap(new_cells); } } else @@ -236,13 +241,19 @@ struct RenamePass : public Pass { { extra_args(args, argidx, design); - for (auto module : design->selected_modules()) { - dict new_cell_names; - for (auto cell : module->selected_cells()) - if (cell->name[0] == '$') - new_cell_names[cell] = derive_name_from_cell_output_wire(cell); - for (auto &it : new_cell_names) - module->rename(it.first, it.second); + for (auto &mod : design->modules_) + { + RTLIL::Module *module = mod.second; + if (!design->selected(module)) + continue; + + dict new_cells; + for (auto &it : module->cells_) { + if (it.first[0] == '$' && design->selected(module, it.second)) + it.second->name = derive_name_from_wire(*it.second); + new_cells[it.second->name] = it.second; + } + module->cells_.swap(new_cells); } } else @@ -250,33 +261,32 @@ struct RenamePass : public Pass { { extra_args(args, argidx, design); - for (auto module : design->selected_modules()) + for (auto &mod : design->modules_) { int counter = 0; - dict new_wire_names; - dict new_cell_names; - - for (auto wire : module->selected_wires()) - if (wire->name[0] == '$') { - RTLIL::IdString buf; - do buf = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str()); - while (module->wire(buf) != nullptr); - new_wire_names[wire] = buf; - } - - for (auto cell : module->selected_cells()) - if (cell->name[0] == '$') { - RTLIL::IdString buf; - do buf = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str()); - while (module->cell(buf) != nullptr); - new_cell_names[cell] = buf; - } - for (auto &it : new_wire_names) - module->rename(it.first, it.second); - - for (auto &it : new_cell_names) - module->rename(it.first, it.second); + RTLIL::Module *module = mod.second; + if (!design->selected(module)) + continue; + + dict new_wires; + for (auto &it : module->wires_) { + if (it.first[0] == '$' && design->selected(module, it.second)) + do it.second->name = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str()); + while (module->count_id(it.second->name) > 0); + new_wires[it.second->name] = it.second; + } + module->wires_.swap(new_wires); + module->fixup_ports(); + + dict new_cells; + for (auto &it : module->cells_) { + if (it.first[0] == '$' && design->selected(module, it.second)) + do it.second->name = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str()); + while (module->count_id(it.second->name) > 0); + new_cells[it.second->name] = it.second; + } + module->cells_.swap(new_cells); } } else @@ -284,24 +294,30 @@ struct RenamePass : public Pass { { extra_args(args, argidx, design); - for (auto module : design->selected_modules()) + for (auto &mod : design->modules_) { - dict new_wire_names; - dict new_cell_names; - - for (auto wire : module->selected_wires()) - if (wire->name[0] == '\\' && wire->port_id == 0) - new_wire_names[wire] = NEW_ID; - - for (auto cell : module->selected_cells()) - if (cell->name[0] == '\\') - new_cell_names[cell] = NEW_ID; - - for (auto &it : new_wire_names) - module->rename(it.first, it.second); - - for (auto &it : new_cell_names) - module->rename(it.first, it.second); + RTLIL::Module *module = mod.second; + if (!design->selected(module)) + continue; + + dict new_wires; + for (auto &it : module->wires_) { + if (design->selected(module, it.second)) + if (it.first[0] == '\\' && it.second->port_id == 0) + it.second->name = NEW_ID; + new_wires[it.second->name] = it.second; + } + module->wires_.swap(new_wires); + module->fixup_ports(); + + dict new_cells; + for (auto &it : module->cells_) { + if (design->selected(module, it.second)) + if (it.first[0] == '\\') + it.second->name = NEW_ID; + new_cells[it.second->name] = it.second; + } + module->cells_.swap(new_cells); } } else @@ -313,7 +329,7 @@ struct RenamePass : public Pass { IdString new_name = RTLIL::escape_id(args[argidx]); RTLIL::Module *module = design->top_module(); - if (module == nullptr) + if (module == NULL) log_cmd_error("No top module found!\n"); log("Renaming module %s to %s.\n", log_id(module), log_id(new_name)); @@ -329,27 +345,27 @@ struct RenamePass : public Pass { if (!design->selected_active_module.empty()) { - if (design->module(design->selected_active_module) != nullptr) - rename_in_module(design->module(design->selected_active_module), from_name, to_name, flag_output); + if (design->modules_.count(design->selected_active_module) > 0) + rename_in_module(design->modules_.at(design->selected_active_module), from_name, to_name, flag_output); } else { if (flag_output) log_cmd_error("Mode -output requires that there is an active module selected.\n"); - - RTLIL::Module *module_to_rename = nullptr; - for (auto module : design->modules()) - if (module->name == from_name || RTLIL::unescape_id(module->name) == from_name) { - module_to_rename = module; - break; + for (auto &mod : design->modules_) { + if (mod.first == from_name || RTLIL::unescape_id(mod.first) == from_name) { + to_name = RTLIL::escape_id(to_name); + log("Renaming module %s to %s.\n", mod.first.c_str(), to_name.c_str()); + RTLIL::Module *module = mod.second; + design->modules_.erase(module->name); + module->name = to_name; + design->modules_[module->name] = module; + goto rename_ok; } + } - if (module_to_rename != nullptr) { - to_name = RTLIL::escape_id(to_name); - log("Renaming module %s to %s.\n", module_to_rename->name.c_str(), to_name.c_str()); - design->rename(module_to_rename, to_name); - } else - log_cmd_error("Object `%s' not found!\n", from_name.c_str()); + log_cmd_error("Object `%s' not found!\n", from_name.c_str()); + rename_ok:; } } } diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc index a70dd308602..7123ba9fb68 100644 --- a/passes/cmds/scatter.cc +++ b/passes/cmds/scatter.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct ScatterPass : public Pass { ScatterPass() : Pass("scatter", "add additional intermediate nets") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -41,24 +41,30 @@ struct ScatterPass : public Pass { log("Use the opt_clean command to get rid of the additional nets.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { CellTypes ct(design); extra_args(args, 1, design); - for (auto module : design->selected_modules()) + for (auto &mod_it : design->modules_) { - for (auto cell : module->cells()) { - dict new_connections; - for (auto conn : cell->connections()) - new_connections.emplace(conn.first, RTLIL::SigSig(conn.second, module->addWire(NEW_ID, GetSize(conn.second)))); - for (auto &it : new_connections) { - if (ct.cell_output(cell->type, it.first)) - module->connect(RTLIL::SigSig(it.second.first, it.second.second)); - else - module->connect(RTLIL::SigSig(it.second.second, it.second.first)); - cell->setPort(it.first, it.second.second); + if (!design->selected(mod_it.second)) + continue; + + for (auto &c : mod_it.second->cells_) + for (auto &p : c.second->connections_) + { + RTLIL::Wire *wire = mod_it.second->addWire(NEW_ID, p.second.size()); + + if (ct.cell_output(c.second->type, p.first)) { + RTLIL::SigSig sigsig(p.second, wire); + mod_it.second->connect(sigsig); + } else { + RTLIL::SigSig sigsig(wire, p.second); + mod_it.second->connect(sigsig); } + + p.second = wire; } } } diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc index 8e7f3f9909c..99f4fbae879 100644 --- a/passes/cmds/scc.cc +++ b/passes/cmds/scc.cc @@ -218,7 +218,7 @@ struct SccWorker struct SccPass : public Pass { SccPass() : Pass("scc", "detect strongly connected components (logic loops)") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -255,7 +255,7 @@ struct SccPass : public Pass { log(" that are part of a found logic loop\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::map setAttr; bool allCellTypes = false; @@ -301,40 +301,41 @@ struct SccPass : public Pass { RTLIL::Selection newSelection(false); int scc_counter = 0; - for (auto mod : design->selected_modules()) - { - SccWorker worker(design, mod, nofeedbackMode, allCellTypes, maxDepth); - - if (!setAttr.empty()) + for (auto &mod_it : design->modules_) + if (design->selected(mod_it.second)) { - for (const auto &cells : worker.sccList) + SccWorker worker(design, mod_it.second, nofeedbackMode, allCellTypes, maxDepth); + + if (!setAttr.empty()) { - for (auto attr : setAttr) + for (const auto &cells : worker.sccList) { - IdString attr_name(RTLIL::escape_id(attr.first)); - string attr_valstr = attr.second; - string index = stringf("%d", scc_counter); + for (auto attr : setAttr) + { + IdString attr_name(RTLIL::escape_id(attr.first)); + string attr_valstr = attr.second; + string index = stringf("%d", scc_counter); - for (size_t pos = 0; (pos = attr_valstr.find("{}", pos)) != string::npos; pos += index.size()) - attr_valstr.replace(pos, 2, index); + for (size_t pos = 0; (pos = attr_valstr.find("{}", pos)) != string::npos; pos += index.size()) + attr_valstr.replace(pos, 2, index); - Const attr_value(attr_valstr); + Const attr_value(attr_valstr); - for (auto cell : cells) - cell->attributes[attr_name] = attr_value; - } + for (auto cell : cells) + cell->attributes[attr_name] = attr_value; + } - scc_counter++; + scc_counter++; + } + } + else + { + scc_counter += GetSize(worker.sccList); } - } - else - { - scc_counter += GetSize(worker.sccList); - } - if (selectMode) - worker.select(newSelection); - } + if (selectMode) + worker.select(newSelection); + } if (expect >= 0) { if (scc_counter == expect) diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc deleted file mode 100644 index 9369f531299..00000000000 --- a/passes/cmds/scratchpad.cc +++ /dev/null @@ -1,141 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Nina Engelhardt - * - * 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/register.h" -#include "kernel/rtlil.h" -#include "kernel/log.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct ScratchpadPass : public Pass { - ScratchpadPass() : Pass("scratchpad", "get/set values in the scratchpad") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" scratchpad [options]\n"); - log("\n"); - log("This pass allows to read and modify values from the scratchpad of the current\n"); - log("design. Options:\n"); - log("\n"); - log(" -get \n"); - log(" print the value saved in the scratchpad under the given identifier.\n"); - log("\n"); - log(" -set \n"); - log(" save the given value in the scratchpad under the given identifier.\n"); - log("\n"); - log(" -unset \n"); - log(" remove the entry for the given identifier from the scratchpad.\n"); - log("\n"); - log(" -copy \n"); - log(" copy the value of the first identifier to the second identifier.\n"); - log("\n"); - log(" -assert \n"); - log(" assert that the entry for the given identifier is set to the given value.\n"); - log("\n"); - log(" -assert-set \n"); - log(" assert that the entry for the given identifier exists.\n"); - log("\n"); - log(" -assert-unset \n"); - log(" assert that the entry for the given identifier does not exist.\n"); - log("\n"); - log("The identifier may not contain whitespace. By convention, it is usually prefixed\n"); - log("by the name of the pass that uses it, e.g. 'opt.did_something'. If the value\n"); - log("contains whitespace, it must be enclosed in double quotes.\n"); - log("\n"); - } - - void execute(std::vector args, RTLIL::Design *design) override - { - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-get" && argidx+1 < args.size()) { - string identifier = args[++argidx]; - if (design->scratchpad.count(identifier)) { - log("%s\n", design->scratchpad_get_string(identifier).c_str()); - } else if (RTLIL::constpad.count(identifier)) { - log("%s\n", RTLIL::constpad.at(identifier).c_str()); - } else { - log("\"%s\" not set\n", identifier.c_str()); - } - continue; - } - if (args[argidx] == "-set" && argidx+2 < args.size()) { - string identifier = args[++argidx]; - if (RTLIL::constpad.count(identifier)) - log_error("scratchpad entry \"%s\" is a global constant\n", identifier.c_str()); - string value = args[++argidx]; - if (value.front() == '\"' && value.back() == '\"') value = value.substr(1, value.size() - 2); - design->scratchpad_set_string(identifier, value); - continue; - } - if (args[argidx] == "-unset" && argidx+1 < args.size()) { - string identifier = args[++argidx]; - design->scratchpad_unset(identifier); - continue; - } - if (args[argidx] == "-copy" && argidx+2 < args.size()) { - string identifier_from = args[++argidx]; - string identifier_to = args[++argidx]; - string value; - if (design->scratchpad.count(identifier_from)) - value = design->scratchpad_get_string(identifier_from); - else if (RTLIL::constpad.count(identifier_from)) - value = RTLIL::constpad.at(identifier_from); - else - log_error("\"%s\" not set\n", identifier_from.c_str()); - if (RTLIL::constpad.count(identifier_to)) - log_error("scratchpad entry \"%s\" is a global constant\n", identifier_to.c_str()); - design->scratchpad_set_string(identifier_to, value); - continue; - } - if (args[argidx] == "-assert" && argidx+2 < args.size()) { - string identifier = args[++argidx]; - string expected = args[++argidx]; - if (expected.front() == '\"' && expected.back() == '\"') expected = expected.substr(1, expected.size() - 2); - if (design->scratchpad.count(identifier) == 0) - log_error("scratchpad entry '%s' is not defined\n", identifier.c_str()); - string value = design->scratchpad_get_string(identifier); - if (value != expected) { - log_error("scratchpad entry '%s' is set to '%s' instead of the asserted '%s'\n", - identifier.c_str(), value.c_str(), expected.c_str()); - } - continue; - } - if (args[argidx] == "-assert-set" && argidx+1 < args.size()) { - string identifier = args[++argidx]; - if (design->scratchpad.count(identifier) == 0) - log_error("scratchpad entry '%s' is not defined\n", identifier.c_str()); - continue; - } - if (args[argidx] == "-assert-unset" && argidx+1 < args.size()) { - string identifier = args[++argidx]; - if (design->scratchpad.count(identifier) > 0) - log_error("scratchpad entry '%s' is defined\n", identifier.c_str()); - continue; - } - break; - } - extra_args(args, argidx, design, false); - } -} ScratchpadPass; -PRIVATE_NAMESPACE_END diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index b4f3994a224..0f1f05ccb89 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -30,31 +30,26 @@ using RTLIL::id2cstr; static std::vector work_stack; -static bool match_ids(RTLIL::IdString id, const std::string &pattern) +static bool match_ids(RTLIL::IdString id, std::string pattern) { if (id == pattern) return true; - - const char *id_c = id.c_str(); - const char *pat_c = pattern.c_str(); - size_t id_size = strlen(id_c); - size_t pat_size = pattern.size(); - - if (*id_c == '\\' && id_size == 1 + pat_size && memcmp(id_c + 1, pat_c, pat_size) == 0) + if (id.size() > 0 && id[0] == '\\' && id.compare(1, std::string::npos, pattern.c_str()) == 0) return true; - if (patmatch(pat_c, id_c)) + if (patmatch(pattern.c_str(), id.c_str())) return true; - if (*id_c == '\\' && patmatch(pat_c, id_c + 1)) + if (id.size() > 0 && id[0] == '\\' && patmatch(pattern.c_str(), id.substr(1).c_str())) return true; - if (*id_c == '$' && *pat_c == '$') { - const char *q = strrchr(id_c, '$'); + if (id.size() > 0 && id[0] == '$' && pattern.size() > 0 && pattern[0] == '$') { + const char *p = id.c_str(); + const char *q = strrchr(p, '$'); if (pattern == q) return true; } return false; } -static bool match_attr_val(const RTLIL::Const &value, const std::string &pattern, char match_op) +static bool match_attr_val(const RTLIL::Const &value, std::string pattern, char match_op) { if (match_op == 0) return true; @@ -63,7 +58,7 @@ static bool match_attr_val(const RTLIL::Const &value, const std::string &pattern { RTLIL::SigSpec sig_value; - if (!RTLIL::SigSpec::parse(sig_value, nullptr, pattern)) + if (!RTLIL::SigSpec::parse(sig_value, NULL, pattern)) return false; RTLIL::Const pattern_value = sig_value.as_const(); @@ -106,7 +101,7 @@ static bool match_attr_val(const RTLIL::Const &value, const std::string &pattern log_abort(); } -static bool match_attr(const dict &attributes, const std::string &name_pat, const std::string &value_pat, char match_op) +static bool match_attr(const dict &attributes, std::string name_pat, std::string value_pat, char match_op) { if (name_pat.find('*') != std::string::npos || name_pat.find('?') != std::string::npos || name_pat.find('[') != std::string::npos) { for (auto &it : attributes) { @@ -124,7 +119,7 @@ static bool match_attr(const dict &attributes, co return false; } -static bool match_attr(const dict &attributes, const std::string &match_expr) +static bool match_attr(const dict &attributes, std::string match_expr) { size_t pos = match_expr.find_first_of(""); @@ -157,26 +152,27 @@ static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs) RTLIL::Selection new_sel(false); - for (auto mod : design->modules()) + for (auto &mod_it : design->modules_) { - if (lhs.selected_whole_module(mod->name)) + if (lhs.selected_whole_module(mod_it.first)) continue; - if (!lhs.selected_module(mod->name)) { - new_sel.selected_modules.insert(mod->name); + if (!lhs.selected_module(mod_it.first)) { + new_sel.selected_modules.insert(mod_it.first); continue; } - for (auto wire : mod->wires()) - if (!lhs.selected_member(mod->name, wire->name)) - new_sel.selected_members[mod->name].insert(wire->name); + RTLIL::Module *mod = mod_it.second; + for (auto &it : mod->wires_) + if (!lhs.selected_member(mod_it.first, it.first)) + new_sel.selected_members[mod->name].insert(it.first); for (auto &it : mod->memories) - if (!lhs.selected_member(mod->name, it.first)) + if (!lhs.selected_member(mod_it.first, it.first)) + new_sel.selected_members[mod->name].insert(it.first); + for (auto &it : mod->cells_) + if (!lhs.selected_member(mod_it.first, it.first)) new_sel.selected_members[mod->name].insert(it.first); - for (auto cell : mod->cells()) - if (!lhs.selected_member(mod->name, cell->name)) - new_sel.selected_members[mod->name].insert(cell->name); for (auto &it : mod->processes) - if (!lhs.selected_member(mod->name, it.first)) + if (!lhs.selected_member(mod_it.first, it.first)) new_sel.selected_members[mod->name].insert(it.first); } @@ -227,15 +223,15 @@ static void select_op_random(RTLIL::Design *design, RTLIL::Selection &lhs, int c static void select_op_submod(RTLIL::Design *design, RTLIL::Selection &lhs) { - for (auto mod : design->modules()) + for (auto &mod_it : design->modules_) { - if (lhs.selected_whole_module(mod->name)) + if (lhs.selected_whole_module(mod_it.first)) { - for (auto cell : mod->cells()) + for (auto &cell_it : mod_it.second->cells_) { - if (design->module(cell->type) == nullptr) + if (design->modules_.count(cell_it.second->type) == 0) continue; - lhs.selected_modules.insert(cell->type); + lhs.selected_modules.insert(cell_it.second->type); } } } @@ -244,21 +240,21 @@ static void select_op_submod(RTLIL::Design *design, RTLIL::Selection &lhs) static void select_op_cells_to_modules(RTLIL::Design *design, RTLIL::Selection &lhs) { RTLIL::Selection new_sel(false); - for (auto mod : design->modules()) - if (lhs.selected_module(mod->name)) - for (auto cell : mod->cells()) - if (lhs.selected_member(mod->name, cell->name) && (design->module(cell->type) != nullptr)) - new_sel.selected_modules.insert(cell->type); + for (auto &mod_it : design->modules_) + if (lhs.selected_module(mod_it.first)) + for (auto &cell_it : mod_it.second->cells_) + if (lhs.selected_member(mod_it.first, cell_it.first) && design->modules_.count(cell_it.second->type)) + new_sel.selected_modules.insert(cell_it.second->type); lhs = new_sel; } static void select_op_module_to_cells(RTLIL::Design *design, RTLIL::Selection &lhs) { RTLIL::Selection new_sel(false); - for (auto mod : design->modules()) - for (auto cell : mod->cells()) - if ((design->module(cell->type) != nullptr) && lhs.selected_whole_module(cell->type)) - new_sel.selected_members[mod->name].insert(cell->name); + for (auto &mod_it : design->modules_) + for (auto &cell_it : mod_it.second->cells_) + if (design->modules_.count(cell_it.second->type) && lhs.selected_whole_module(cell_it.second->type)) + new_sel.selected_members[mod_it.first].insert(cell_it.first); lhs = new_sel; } @@ -272,23 +268,23 @@ static void select_op_fullmod(RTLIL::Design *design, RTLIL::Selection &lhs) static void select_op_alias(RTLIL::Design *design, RTLIL::Selection &lhs) { - for (auto mod : design->modules()) + for (auto &mod_it : design->modules_) { - if (lhs.selected_whole_module(mod->name)) + if (lhs.selected_whole_module(mod_it.first)) continue; - if (!lhs.selected_module(mod->name)) + if (!lhs.selected_module(mod_it.first)) continue; - SigMap sigmap(mod); + SigMap sigmap(mod_it.second); SigPool selected_bits; - for (auto wire : mod->wires()) - if (lhs.selected_member(mod->name, wire->name)) - selected_bits.add(sigmap(wire)); + for (auto &it : mod_it.second->wires_) + if (lhs.selected_member(mod_it.first, it.first)) + selected_bits.add(sigmap(it.second)); - for (auto wire : mod->wires()) - if (!lhs.selected_member(mod->name, wire->name) && selected_bits.check_any(sigmap(wire))) - lhs.selected_members[mod->name].insert(wire->name); + for (auto &it : mod_it.second->wires_) + if (!lhs.selected_member(mod_it.first, it.first) && selected_bits.check_any(sigmap(it.second))) + lhs.selected_members[mod_it.first].insert(it.first); } } @@ -327,8 +323,8 @@ static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const R if (!rhs.full_selection && rhs.selected_modules.size() == 0 && rhs.selected_members.size() == 0) return; lhs.full_selection = false; - for (auto mod : design->modules()) - lhs.selected_modules.insert(mod->name); + for (auto &it : design->modules_) + lhs.selected_modules.insert(it.first); } for (auto &it : rhs.selected_modules) { @@ -338,19 +334,19 @@ static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const R for (auto &it : rhs.selected_members) { - if (design->module(it.first) == nullptr) + if (design->modules_.count(it.first) == 0) continue; - RTLIL::Module *mod = design->module(it.first); + RTLIL::Module *mod = design->modules_[it.first]; if (lhs.selected_modules.count(mod->name) > 0) { - for (auto wire : mod->wires()) - lhs.selected_members[mod->name].insert(wire->name); + for (auto &it : mod->wires_) + lhs.selected_members[mod->name].insert(it.first); for (auto &it : mod->memories) lhs.selected_members[mod->name].insert(it.first); - for (auto cell : mod->cells()) - lhs.selected_members[mod->name].insert(cell->name); + for (auto &it : mod->cells_) + lhs.selected_members[mod->name].insert(it.first); for (auto &it : mod->processes) lhs.selected_members[mod->name].insert(it.first); lhs.selected_modules.erase(mod->name); @@ -371,8 +367,8 @@ static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, co if (lhs.full_selection) { lhs.full_selection = false; - for (auto mod : design->modules()) - lhs.selected_modules.insert(mod->name); + for (auto &it : design->modules_) + lhs.selected_modules.insert(it.first); } std::vector del_list; @@ -415,7 +411,7 @@ namespace { }; } -static int parse_comma_list(std::set &tokens, const std::string &str, size_t pos, std::string stopchar) +static int parse_comma_list(std::set &tokens, std::string str, size_t pos, std::string stopchar) { stopchar += ','; while (1) { @@ -435,17 +431,18 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v { int sel_objects = 0; bool is_input, is_output; - for (auto mod : design->modules()) + for (auto &mod_it : design->modules_) { - if (lhs.selected_whole_module(mod->name) || !lhs.selected_module(mod->name)) + if (lhs.selected_whole_module(mod_it.first) || !lhs.selected_module(mod_it.first)) continue; + RTLIL::Module *mod = mod_it.second; std::set selected_wires; auto selected_members = lhs.selected_members[mod->name]; - for (auto wire : mod->wires()) - if (lhs.selected_member(mod->name, wire->name) && limits.count(wire->name) == 0) - selected_wires.insert(wire); + for (auto &it : mod->wires_) + if (lhs.selected_member(mod_it.first, it.first) && limits.count(it.first) == 0) + selected_wires.insert(it.second); for (auto &conn : mod->connections()) { @@ -453,7 +450,7 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v std::vector conn_rhs = conn.second.to_sigbit_vector(); for (size_t i = 0; i < conn_lhs.size(); i++) { - if (conn_lhs[i].wire == nullptr || conn_rhs[i].wire == nullptr) + if (conn_lhs[i].wire == NULL || conn_rhs[i].wire == NULL) continue; if (mode != 'i' && selected_wires.count(conn_rhs[i].wire) && selected_members.count(conn_lhs[i].wire->name) == 0) lhs.selected_members[mod->name].insert(conn_lhs[i].wire->name), sel_objects++, max_objects--; @@ -462,15 +459,15 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v } } - for (auto cell : mod->cells()) - for (auto &conn : cell->connections()) + for (auto &cell : mod->cells_) + for (auto &conn : cell.second->connections()) { char last_mode = '-'; - if (eval_only && !yosys_celltypes.cell_evaluable(cell->type)) + if (eval_only && !yosys_celltypes.cell_evaluable(cell.second->type)) goto exclude_match; for (auto &rule : rules) { last_mode = rule.mode; - if (rule.cell_types.size() > 0 && rule.cell_types.count(cell->type) == 0) + if (rule.cell_types.size() > 0 && rule.cell_types.count(cell.second->type) == 0) continue; if (rule.port_names.size() > 0 && rule.port_names.count(conn.first) == 0) continue; @@ -482,14 +479,14 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v if (last_mode == '+') goto exclude_match; include_match: - is_input = mode == 'x' || ct.cell_input(cell->type, conn.first); - is_output = mode == 'x' || ct.cell_output(cell->type, conn.first); + is_input = mode == 'x' || ct.cell_input(cell.second->type, conn.first); + is_output = mode == 'x' || ct.cell_output(cell.second->type, conn.first); for (auto &chunk : conn.second.chunks()) - if (chunk.wire != nullptr) { - if (max_objects != 0 && selected_wires.count(chunk.wire) > 0 && selected_members.count(cell->name) == 0) + if (chunk.wire != NULL) { + if (max_objects != 0 && selected_wires.count(chunk.wire) > 0 && selected_members.count(cell.first) == 0) if (mode == 'x' || (mode == 'i' && is_output) || (mode == 'o' && is_input)) - lhs.selected_members[mod->name].insert(cell->name), sel_objects++, max_objects--; - if (max_objects != 0 && selected_members.count(cell->name) > 0 && limits.count(cell->name) == 0 && selected_members.count(chunk.wire->name) == 0) + lhs.selected_members[mod->name].insert(cell.first), sel_objects++, max_objects--; + if (max_objects != 0 && selected_members.count(cell.first) > 0 && limits.count(cell.first) == 0 && selected_members.count(chunk.wire->name) == 0) if (mode == 'x' || (mode == 'i' && is_input) || (mode == 'o' && is_output)) lhs.selected_members[mod->name].insert(chunk.wire->name), sel_objects++, max_objects--; } @@ -500,7 +497,7 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v return sel_objects; } -static void select_op_expand(RTLIL::Design *design, const std::string &arg, char mode, bool eval_only) +static void select_op_expand(RTLIL::Design *design, std::string arg, char mode, bool eval_only) { int pos = (mode == 'x' ? 2 : 3) + (eval_only ? 1 : 0); int levels = 1, rem_objects = -1; @@ -630,15 +627,9 @@ static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &se } } -static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_empty_warning = false) +static void select_stmt(RTLIL::Design *design, std::string arg) { std::string arg_mod, arg_memb; - std::unordered_map arg_mod_found; - std::unordered_map arg_memb_found; - - auto isprefixed = [](const string &s) { - return GetSize(s) >= 2 && ((s[0] >= 'a' && s[0] <= 'z') || (s[0] >= 'A' && s[0] <= 'Z')) && s[1] == ':'; - }; if (arg.size() == 0) return; @@ -766,103 +757,84 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp return; } - bool select_blackboxes = false; - if (arg.substr(0, 1) == "=") { - arg = arg.substr(1); - select_blackboxes = true; - } - if (!design->selected_active_module.empty()) { arg_mod = design->selected_active_module; arg_memb = arg; - if (!isprefixed(arg_memb)) - arg_memb_found[arg_memb] = false; } else - if (isprefixed(arg) && arg[0] >= 'a' && arg[0] <= 'z') { + if (GetSize(arg) >= 2 && arg[0] >= 'a' && arg[0] <= 'z' && arg[1] == ':') { arg_mod = "*", arg_memb = arg; } else { size_t pos = arg.find('/'); if (pos == std::string::npos) { - arg_mod = arg; - if (!isprefixed(arg_mod)) - arg_mod_found[arg_mod] = false; + if (arg.find(':') == std::string::npos || arg.compare(0, 1, "A") == 0) + arg_mod = arg; + else + arg_mod = "*", arg_memb = arg; } else { arg_mod = arg.substr(0, pos); - if (!isprefixed(arg_mod)) - arg_mod_found[arg_mod] = false; arg_memb = arg.substr(pos+1); - if (!isprefixed(arg_memb)) - arg_memb_found[arg_memb] = false; } } work_stack.push_back(RTLIL::Selection()); RTLIL::Selection &sel = work_stack.back(); - if (arg == "*" && arg_mod == "*" && select_blackboxes) { + if (arg == "*" && arg_mod == "*") { select_filter_active_mod(design, work_stack.back()); return; } sel.full_selection = false; - for (auto mod : design->modules()) + for (auto &mod_it : design->modules_) { - if (!select_blackboxes && mod->get_blackbox_attribute()) - continue; - if (arg_mod.compare(0, 2, "A:") == 0) { - if (!match_attr(mod->attributes, arg_mod.substr(2))) - continue; - } else - if (arg_mod.compare(0, 2, "N:") == 0) { - if (!match_ids(mod->name, arg_mod.substr(2))) + if (!match_attr(mod_it.second->attributes, arg_mod.substr(2))) continue; } else - if (!match_ids(mod->name, arg_mod)) + if (!match_ids(mod_it.first, arg_mod)) continue; - else - arg_mod_found[arg_mod] = true; if (arg_memb == "") { - sel.selected_modules.insert(mod->name); + sel.selected_modules.insert(mod_it.first); continue; } + RTLIL::Module *mod = mod_it.second; if (arg_memb.compare(0, 2, "w:") == 0) { - for (auto wire : mod->wires()) - if (match_ids(wire->name, arg_memb.substr(2))) - sel.selected_members[mod->name].insert(wire->name); + for (auto &it : mod->wires_) + if (match_ids(it.first, arg_memb.substr(2))) + sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "i:") == 0) { - for (auto wire : mod->wires()) - if (wire->port_input && match_ids(wire->name, arg_memb.substr(2))) - sel.selected_members[mod->name].insert(wire->name); + for (auto &it : mod->wires_) + if (it.second->port_input && match_ids(it.first, arg_memb.substr(2))) + sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "o:") == 0) { - for (auto wire : mod->wires()) - if (wire->port_output && match_ids(wire->name, arg_memb.substr(2))) - sel.selected_members[mod->name].insert(wire->name); + for (auto &it : mod->wires_) + if (it.second->port_output && match_ids(it.first, arg_memb.substr(2))) + sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "x:") == 0) { - for (auto wire : mod->wires()) - if ((wire->port_input || wire->port_output) && match_ids(wire->name, arg_memb.substr(2))) - sel.selected_members[mod->name].insert(wire->name); + for (auto &it : mod->wires_) + if ((it.second->port_input || it.second->port_output) && match_ids(it.first, arg_memb.substr(2))) + sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "s:") == 0) { size_t delim = arg_memb.substr(2).find(':'); if (delim == std::string::npos) { int width = atoi(arg_memb.substr(2).c_str()); - for (auto wire : mod->wires()) - if (wire->width == width) - sel.selected_members[mod->name].insert(wire->name); + for (auto &it : mod->wires_) + if (it.second->width == width) + sel.selected_members[mod->name].insert(it.first); } else { std::string min_str = arg_memb.substr(2, delim); std::string max_str = arg_memb.substr(2+delim+1); int min_width = min_str.empty() ? 0 : atoi(min_str.c_str()); int max_width = max_str.empty() ? -1 : atoi(max_str.c_str()); - for (auto wire : mod->wires()) - if (min_width <= wire->width && (wire->width <= max_width || max_width == -1)) - sel.selected_members[mod->name].insert(wire->name); + for (auto &it : mod->wires_) + if (min_width <= it.second->width && (it.second->width <= max_width || max_width == -1)) + sel.selected_members[mod->name].insert(it.first); } } else if (arg_memb.compare(0, 2, "m:") == 0) { @@ -870,15 +842,15 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp if (match_ids(it.first, arg_memb.substr(2))) sel.selected_members[mod->name].insert(it.first); } else - if (arg_memb.compare(0, 2, "c:") == 0) { - for (auto cell : mod->cells()) - if (match_ids(cell->name, arg_memb.substr(2))) - sel.selected_members[mod->name].insert(cell->name); + if (arg_memb.compare(0, 2, "c:") ==0) { + for (auto &it : mod->cells_) + if (match_ids(it.first, arg_memb.substr(2))) + sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "t:") == 0) { - for (auto cell : mod->cells()) - if (match_ids(cell->type, arg_memb.substr(2))) - sel.selected_members[mod->name].insert(cell->name); + for (auto &it : mod->cells_) + if (match_ids(it.second->type, arg_memb.substr(2))) + sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "p:") == 0) { for (auto &it : mod->processes) @@ -886,82 +858,62 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "a:") == 0) { - for (auto wire : mod->wires()) - if (match_attr(wire->attributes, arg_memb.substr(2))) - sel.selected_members[mod->name].insert(wire->name); + for (auto &it : mod->wires_) + if (match_attr(it.second->attributes, arg_memb.substr(2))) + sel.selected_members[mod->name].insert(it.first); for (auto &it : mod->memories) if (match_attr(it.second->attributes, arg_memb.substr(2))) sel.selected_members[mod->name].insert(it.first); - for (auto cell : mod->cells()) - if (match_attr(cell->attributes, arg_memb.substr(2))) - sel.selected_members[mod->name].insert(cell->name); + for (auto &it : mod->cells_) + if (match_attr(it.second->attributes, arg_memb.substr(2))) + sel.selected_members[mod->name].insert(it.first); for (auto &it : mod->processes) if (match_attr(it.second->attributes, arg_memb.substr(2))) sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "r:") == 0) { - for (auto cell : mod->cells()) - if (match_attr(cell->parameters, arg_memb.substr(2))) - sel.selected_members[mod->name].insert(cell->name); + for (auto &it : mod->cells_) + if (match_attr(it.second->parameters, arg_memb.substr(2))) + sel.selected_members[mod->name].insert(it.first); } else { - std::string orig_arg_memb = arg_memb; if (arg_memb.compare(0, 2, "n:") == 0) arg_memb = arg_memb.substr(2); - for (auto wire : mod->wires()) - if (match_ids(wire->name, arg_memb)) { - sel.selected_members[mod->name].insert(wire->name); - arg_memb_found[orig_arg_memb] = true; - } + for (auto &it : mod->wires_) + if (match_ids(it.first, arg_memb)) + sel.selected_members[mod->name].insert(it.first); for (auto &it : mod->memories) - if (match_ids(it.first, arg_memb)) { + if (match_ids(it.first, arg_memb)) + sel.selected_members[mod->name].insert(it.first); + for (auto &it : mod->cells_) + if (match_ids(it.first, arg_memb)) sel.selected_members[mod->name].insert(it.first); - arg_memb_found[orig_arg_memb] = true; - } - for (auto cell : mod->cells()) - if (match_ids(cell->name, arg_memb)) { - sel.selected_members[mod->name].insert(cell->name); - arg_memb_found[orig_arg_memb] = true; - } for (auto &it : mod->processes) - if (match_ids(it.first, arg_memb)) { + if (match_ids(it.first, arg_memb)) sel.selected_members[mod->name].insert(it.first); - arg_memb_found[orig_arg_memb] = true; - } } } select_filter_active_mod(design, work_stack.back()); - - for (auto &it : arg_mod_found) { - if (it.second == false && !disable_empty_warning) { - log_warning("Selection \"%s\" did not match any module.\n", it.first.c_str()); - } - } - for (auto &it : arg_memb_found) { - if (it.second == false && !disable_empty_warning) { - log_warning("Selection \"%s\" did not match any object.\n", it.first.c_str()); - } - } } static std::string describe_selection_for_assert(RTLIL::Design *design, RTLIL::Selection *sel) { std::string desc = "Selection contains:\n"; - for (auto mod : design->modules()) + for (auto mod_it : design->modules_) { - if (sel->selected_module(mod->name)) { - for (auto wire : mod->wires()) - if (sel->selected_member(mod->name, wire->name)) - desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(wire->name)); - for (auto &it : mod->memories) - if (sel->selected_member(mod->name, it.first)) - desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(it.first)); - for (auto cell : mod->cells()) - if (sel->selected_member(mod->name, cell->name)) - desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(cell->name)); - for (auto &it : mod->processes) - if (sel->selected_member(mod->name, it.first)) - desc += stringf("%s/%s\n", id2cstr(mod->name), id2cstr(it.first)); + if (sel->selected_module(mod_it.first)) { + for (auto &it : mod_it.second->wires_) + if (sel->selected_member(mod_it.first, it.first)) + desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)); + for (auto &it : mod_it.second->memories) + if (sel->selected_member(mod_it.first, it.first)) + desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)); + for (auto &it : mod_it.second->cells_) + if (sel->selected_member(mod_it.first, it.first)) + desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)); + for (auto &it : mod_it.second->processes) + if (sel->selected_member(mod_it.first, it.first)) + desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)); } } return desc; @@ -971,12 +923,12 @@ PRIVATE_NAMESPACE_END YOSYS_NAMESPACE_BEGIN // used in kernel/register.cc and maybe other locations, extern decl. in register.h -void handle_extra_select_args(Pass *pass, const vector &args, size_t argidx, size_t args_size, RTLIL::Design *design) +void handle_extra_select_args(Pass *pass, vector args, size_t argidx, size_t args_size, RTLIL::Design *design) { work_stack.clear(); for (; argidx < args_size; argidx++) { if (args[argidx].compare(0, 1, "-") == 0) { - if (pass != nullptr) + if (pass != NULL) pass->cmd_error(args, argidx, "Unexpected option in selection arguments."); else log_cmd_error("Unexpected option in selection arguments."); @@ -1021,12 +973,11 @@ PRIVATE_NAMESPACE_BEGIN struct SelectPass : public Pass { SelectPass() : Pass("select", "modify and view the list of selected objects") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" select [ -add | -del | -set ] {-read | }\n"); - log(" select [ -unset ]\n"); log(" select [ ] {-read | }\n"); log(" select [ -list | -write | -count | -clear ]\n"); log(" select -module \n"); @@ -1049,10 +1000,6 @@ struct SelectPass : public Pass { log(" under the given name (see @ below). to save the current selection,\n"); log(" use \"select -set %%\"\n"); log("\n"); - log(" -unset \n"); - log(" do not modify the current selection. instead remove a previously saved\n"); - log(" selection under the given name (see @ below)."); - log("\n"); log(" -assert-none\n"); log(" do not modify the current selection. instead assert that the given\n"); log(" selection is empty. i.e. produce an error if any object matching the\n"); @@ -1123,9 +1070,6 @@ struct SelectPass : public Pass { log(" \n"); log(" select the specified object(s) from the current module\n"); log("\n"); - log("By default, patterns will not match black/white-box modules or their"); - log("contents. To include such objects, prefix the pattern with '='.\n"); - log("\n"); log("A can be a module name, wildcard expression (*, ?, [..])\n"); log("matching module names, or one of the following:\n"); log("\n"); @@ -1133,10 +1077,6 @@ struct SelectPass : public Pass { log(" all modules with an attribute matching the given pattern\n"); log(" in addition to = also <, <=, >=, and > are supported\n"); log("\n"); - log(" N:\n"); - log(" all modules with a name matching the given pattern\n"); - log(" (i.e. 'N:' is optional as it is the default matching rule)\n"); - log("\n"); log("An can be an object name, wildcard expression, or one of\n"); log("the following:\n"); log("\n"); @@ -1250,7 +1190,7 @@ struct SelectPass : public Pass { log(" select */t:SWITCH %%x:+[GATE] */t:SWITCH %%d\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool add_mode = false; bool del_mode = false; @@ -1265,7 +1205,7 @@ struct SelectPass : public Pass { int assert_max = -1; int assert_min = -1; std::string write_file, read_file; - std::string set_name, unset_name, sel_str; + std::string set_name, sel_str; work_stack.clear(); @@ -1327,7 +1267,7 @@ struct SelectPass : public Pass { } if (arg == "-module" && argidx+1 < args.size()) { RTLIL::IdString mod_name = RTLIL::escape_id(args[++argidx]); - if (design->module(mod_name) == nullptr) + if (design->modules_.count(mod_name) == 0) log_cmd_error("No such module: %s\n", id2cstr(mod_name)); design->selected_active_module = mod_name.str(); got_module = true; @@ -1337,14 +1277,9 @@ struct SelectPass : public Pass { set_name = RTLIL::escape_id(args[++argidx]); continue; } - if (arg == "-unset" && argidx+1 < args.size()) { - unset_name = RTLIL::escape_id(args[++argidx]); - continue; - } if (arg.size() > 0 && arg[0] == '-') log_cmd_error("Unknown option %s.\n", arg.c_str()); - bool disable_empty_warning = count_mode || assert_none || assert_any || (assert_count != -1) || (assert_max != -1) || (assert_min != -1); - select_stmt(design, arg, disable_empty_warning); + select_stmt(design, arg); sel_str += " " + arg; } @@ -1389,11 +1324,8 @@ struct SelectPass : public Pass { if ((list_mode || !write_file.empty() || count_mode) && (add_mode || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0)) log_cmd_error("Options -list, -write and -count can not be combined with -add, -del, -assert-none, -assert-any, assert-count, -assert-max, or -assert-min.\n"); - if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || !unset_name.empty() || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0)) - log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -unset, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min.\n"); - - if (!unset_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || !set_name.empty() || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0)) - log_cmd_error("Option -unset can not be combined with -list, -write, -count, -add, -del, -set, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min.\n"); + if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0)) + log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min.\n"); if (work_stack.size() == 0 && got_module) { RTLIL::Selection sel; @@ -1421,41 +1353,41 @@ struct SelectPass : public Pass { if (list_mode || count_mode || !write_file.empty()) { - #define LOG_OBJECT(...) { if (list_mode) log(__VA_ARGS__); if (f != nullptr) fprintf(f, __VA_ARGS__); total_count++; } + #define LOG_OBJECT(...) { if (list_mode) log(__VA_ARGS__); if (f != NULL) fprintf(f, __VA_ARGS__); total_count++; } int total_count = 0; - FILE *f = nullptr; + FILE *f = NULL; if (!write_file.empty()) { f = fopen(write_file.c_str(), "w"); yosys_output_files.insert(write_file); - if (f == nullptr) + if (f == NULL) log_error("Can't open '%s' for writing: %s\n", write_file.c_str(), strerror(errno)); } RTLIL::Selection *sel = &design->selection_stack.back(); if (work_stack.size() > 0) sel = &work_stack.back(); sel->optimize(design); - for (auto mod : design->modules()) + for (auto mod_it : design->modules_) { - if (sel->selected_whole_module(mod->name) && list_mode) - log("%s\n", id2cstr(mod->name)); - if (sel->selected_module(mod->name)) { - for (auto wire : mod->wires()) - if (sel->selected_member(mod->name, wire->name)) - LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(wire->name)) - for (auto &it : mod->memories) - if (sel->selected_member(mod->name, it.first)) - LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(it.first)) - for (auto cell : mod->cells()) - if (sel->selected_member(mod->name, cell->name)) - LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(cell->name)) - for (auto &it : mod->processes) - if (sel->selected_member(mod->name, it.first)) - LOG_OBJECT("%s/%s\n", id2cstr(mod->name), id2cstr(it.first)) + if (sel->selected_whole_module(mod_it.first) && list_mode) + log("%s\n", id2cstr(mod_it.first)); + if (sel->selected_module(mod_it.first)) { + for (auto &it : mod_it.second->wires_) + if (sel->selected_member(mod_it.first, it.first)) + LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)) + for (auto &it : mod_it.second->memories) + if (sel->selected_member(mod_it.first, it.first)) + LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)) + for (auto &it : mod_it.second->cells_) + if (sel->selected_member(mod_it.first, it.first)) + LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)) + for (auto &it : mod_it.second->processes) + if (sel->selected_member(mod_it.first, it.first)) + LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)) } } if (count_mode) log("%d objects.\n", total_count); - if (f != nullptr) + if (f != NULL) fclose(f); #undef LOG_OBJECT return; @@ -1516,19 +1448,19 @@ struct SelectPass : public Pass { log_cmd_error("No selection to check.\n"); RTLIL::Selection *sel = &work_stack.back(); sel->optimize(design); - for (auto mod : design->modules()) - if (sel->selected_module(mod->name)) { - for (auto wire : mod->wires()) - if (sel->selected_member(mod->name, wire->name)) + for (auto mod_it : design->modules_) + if (sel->selected_module(mod_it.first)) { + for (auto &it : mod_it.second->wires_) + if (sel->selected_member(mod_it.first, it.first)) total_count++; - for (auto &it : mod->memories) - if (sel->selected_member(mod->name, it.first)) + for (auto &it : mod_it.second->memories) + if (sel->selected_member(mod_it.first, it.first)) total_count++; - for (auto cell : mod->cells()) - if (sel->selected_member(mod->name, cell->name)) + for (auto &it : mod_it.second->cells_) + if (sel->selected_member(mod_it.first, it.first)) total_count++; - for (auto &it : mod->processes) - if (sel->selected_member(mod->name, it.first)) + for (auto &it : mod_it.second->processes) + if (sel->selected_member(mod_it.first, it.first)) total_count++; } if (assert_count >= 0 && assert_count != total_count) @@ -1561,13 +1493,6 @@ struct SelectPass : public Pass { return; } - if (!unset_name.empty()) - { - if (!design->selection_vars.erase(unset_name)) - log_error("Selection '%s' does not exist!\n", unset_name.c_str()); - return; - } - if (work_stack.size() == 0) { RTLIL::Selection &sel = design->selection_stack.back(); if (sel.full_selection) @@ -1587,7 +1512,7 @@ struct SelectPass : public Pass { struct CdPass : public Pass { CdPass() : Pass("cd", "a shortcut for 'select -module '") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1613,7 +1538,7 @@ struct CdPass : public Pass { log("This is just a shortcut for 'select -clear'.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { if (args.size() != 1 && args.size() != 2) log_cmd_error("Invalid number of arguments.\n"); @@ -1656,13 +1581,15 @@ struct CdPass : public Pass { std::string modname = RTLIL::escape_id(args[1]); - if (design->module(modname) == nullptr && !design->selected_active_module.empty()) { - RTLIL::Module *module = design->module(design->selected_active_module); - if (module != nullptr && module->cell(modname) != nullptr) - modname = module->cell(modname)->type.str(); + if (design->modules_.count(modname) == 0 && !design->selected_active_module.empty()) { + RTLIL::Module *module = NULL; + if (design->modules_.count(design->selected_active_module) > 0) + module = design->modules_.at(design->selected_active_module); + if (module != NULL && module->cells_.count(modname) > 0) + modname = module->cells_.at(modname)->type.str(); } - if (design->module(modname) != nullptr) { + if (design->modules_.count(modname) > 0) { design->selected_active_module = modname; design->selection_stack.back() = RTLIL::Selection(); select_filter_active_mod(design, design->selection_stack.back()); @@ -1675,7 +1602,7 @@ struct CdPass : public Pass { } CdPass; template -static void log_matches(const char *title, Module *module, const T &list) +static void log_matches(const char *title, Module *module, T list) { std::vector matches; @@ -1693,7 +1620,7 @@ static void log_matches(const char *title, Module *module, const T &list) struct LsPass : public Pass { LsPass() : Pass("ls", "list modules or objects in modules") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1704,7 +1631,7 @@ struct LsPass : public Pass { log("When an active module is selected, this prints a list of objects in the module.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx = 1; extra_args(args, argidx, design); diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 3a94209d407..1ccfc2e86dc 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -38,7 +38,7 @@ struct setunset_t value = RTLIL::Const(set_value.substr(1, GetSize(set_value)-2)); } else { RTLIL::SigSpec sig_value; - if (!RTLIL::SigSpec::parse(sig_value, nullptr, set_value)) + if (!RTLIL::SigSpec::parse(sig_value, NULL, set_value)) log_cmd_error("Can't decode value '%s'!\n", set_value.c_str()); value = sig_value.as_const(); } @@ -56,7 +56,7 @@ static void do_setunset(dict &attrs, const std::v struct SetattrPass : public Pass { SetattrPass() : Pass("setattr", "set/unset attributes on objects") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -69,7 +69,7 @@ struct SetattrPass : public Pass { log("instead of objects within modules.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::vector setunset_list; bool flag_mod = false; @@ -96,8 +96,10 @@ struct SetattrPass : public Pass { } extra_args(args, argidx, design); - for (auto module : design->modules()) + for (auto &mod : design->modules_) { + RTLIL::Module *module = mod.second; + if (flag_mod) { if (design->selected_whole_module(module->name)) do_setunset(module->attributes, setunset_list); @@ -107,17 +109,17 @@ struct SetattrPass : public Pass { if (!design->selected(module)) continue; - for (auto wire : module->wires()) - if (design->selected(module, wire)) - do_setunset(wire->attributes, setunset_list); + for (auto &it : module->wires_) + if (design->selected(module, it.second)) + do_setunset(it.second->attributes, setunset_list); for (auto &it : module->memories) if (design->selected(module, it.second)) do_setunset(it.second->attributes, setunset_list); - for (auto cell : module->cells()) - if (design->selected(module, cell)) - do_setunset(cell->attributes, setunset_list); + for (auto &it : module->cells_) + if (design->selected(module, it.second)) + do_setunset(it.second->attributes, setunset_list); for (auto &it : module->processes) if (design->selected(module, it.second)) @@ -128,7 +130,7 @@ struct SetattrPass : public Pass { struct WbflipPass : public Pass { WbflipPass() : Pass("wbflip", "flip the whitebox attribute") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -138,7 +140,7 @@ struct WbflipPass : public Pass { log("vice-versa. Blackbox cells are not effected by this command.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -157,17 +159,17 @@ struct WbflipPass : public Pass { if (!design->selected(module)) continue; - if (module->get_bool_attribute(ID::blackbox)) + if (module->get_bool_attribute("\\blackbox")) continue; - module->set_bool_attribute(ID::whitebox, !module->get_bool_attribute(ID::whitebox)); + module->set_bool_attribute("\\whitebox", !module->get_bool_attribute("\\whitebox")); } } } WbflipPass; struct SetparamPass : public Pass { SetparamPass() : Pass("setparam", "set/unset parameters on objects") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -179,7 +181,7 @@ struct SetparamPass : public Pass { log("The -type option can be used to change the cell type of the selected cells.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { vector setunset_list; string new_cell_type; @@ -206,20 +208,26 @@ struct SetparamPass : public Pass { } extra_args(args, argidx, design); - for (auto module : design->selected_modules()) + for (auto &mod : design->modules_) { - for (auto cell : module->selected_cells()) { - if (!new_cell_type.empty()) - cell->type = new_cell_type; - do_setunset(cell->parameters, setunset_list); - } + RTLIL::Module *module = mod.second; + + if (!design->selected(module)) + continue; + + for (auto &it : module->cells_) + if (design->selected(module, it.second)) { + if (!new_cell_type.empty()) + it.second->type = new_cell_type; + do_setunset(it.second->parameters, setunset_list); + } } } } SetparamPass; struct ChparamPass : public Pass { ChparamPass() : Pass("chparam", "re-evaluate modules with new parameters") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -234,7 +242,7 @@ struct ChparamPass : public Pass { log("List the available parameters of the selected modules.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::vector setunset_list; dict new_parameters; diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc index cf8d766196c..3eedc86b871 100644 --- a/passes/cmds/setundef.cc +++ b/passes/cmds/setundef.cc @@ -107,7 +107,7 @@ struct SetundefWorker struct SetundefPass : public Pass { SetundefPass() : Pass("setundef", "replace undef values with defined constants") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -147,9 +147,9 @@ struct SetundefPass : public Pass { log(" replace undef in cell parameters\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - int got_value = 0; + bool got_value = false; bool undriven_mode = false; bool expose_mode = false; bool init_mode = false; @@ -170,31 +170,31 @@ struct SetundefPass : public Pass { continue; } if (args[argidx] == "-zero") { - got_value++; + got_value = true; worker.next_bit_mode = MODE_ZERO; worker.next_bit_state = 0; continue; } if (args[argidx] == "-one") { - got_value++; + got_value = true; worker.next_bit_mode = MODE_ONE; worker.next_bit_state = 0; continue; } if (args[argidx] == "-anyseq") { - got_value++; + got_value = true; worker.next_bit_mode = MODE_ANYSEQ; worker.next_bit_state = 0; continue; } if (args[argidx] == "-anyconst") { - got_value++; + got_value = true; worker.next_bit_mode = MODE_ANYCONST; worker.next_bit_state = 0; continue; } if (args[argidx] == "-undef") { - got_value++; + got_value = true; worker.next_bit_mode = MODE_UNDEF; worker.next_bit_state = 0; continue; @@ -207,8 +207,8 @@ struct SetundefPass : public Pass { params_mode = true; continue; } - if (args[argidx] == "-random" && argidx+1 < args.size()) { - got_value++; + if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) { + got_value = true; worker.next_bit_mode = MODE_RANDOM; worker.next_bit_state = atoi(args[++argidx].c_str()) + 1; for (int i = 0; i < 10; i++) @@ -221,7 +221,7 @@ struct SetundefPass : public Pass { if (!got_value && expose_mode) { log("Using default as -undef with -expose.\n"); - got_value++; + got_value = true; worker.next_bit_mode = MODE_UNDEF; worker.next_bit_state = 0; } @@ -229,9 +229,7 @@ struct SetundefPass : public Pass { if (expose_mode && !undriven_mode) log_cmd_error("Option -expose must be used with option -undriven.\n"); if (!got_value) - log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, -random , or -expose must be specified.\n"); - else if (got_value > 1) - log_cmd_error("Only one of the options -zero, -one, -anyseq, -anyconst, or -random can be specified.\n"); + log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, or -random must be specified.\n"); if (init_mode && (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)) log_cmd_error("The options -init and -anyseq / -anyconst are exclusive.\n"); @@ -361,12 +359,37 @@ struct SetundefPass : public Pass { pool ffbits; pool initwires; + pool fftypes; + fftypes.insert("$dff"); + fftypes.insert("$dffe"); + fftypes.insert("$dffsr"); + fftypes.insert("$adff"); + + std::vector list_np = {'N', 'P'}, list_01 = {'0', '1'}; + + for (auto c1 : list_np) + fftypes.insert(stringf("$_DFF_%c_", c1)); + + for (auto c1 : list_np) + for (auto c2 : list_np) + fftypes.insert(stringf("$_DFFE_%c%c_", c1, c2)); + + for (auto c1 : list_np) + for (auto c2 : list_np) + for (auto c3 : list_01) + fftypes.insert(stringf("$_DFF_%c%c%c_", c1, c2, c3)); + + for (auto c1 : list_np) + for (auto c2 : list_np) + for (auto c3 : list_np) + fftypes.insert(stringf("$_DFFSR_%c%c%c_", c1, c2, c3)); + for (auto cell : module->cells()) { - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!fftypes.count(cell->type)) continue; - for (auto bit : sigmap(cell->getPort(ID::Q))) + for (auto bit : sigmap(cell->getPort("\\Q"))) ffbits.insert(bit); } @@ -388,7 +411,7 @@ struct SetundefPass : public Pass { for (auto wire : initwires) { - Const &initval = wire->attributes[ID::init]; + Const &initval = wire->attributes["\\init"]; initval.bits.resize(GetSize(wire), State::Sx); for (int i = 0; i < GetSize(wire); i++) { @@ -400,7 +423,7 @@ struct SetundefPass : public Pass { } if (initval.is_fully_undef()) - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); } initwires.clear(); @@ -416,14 +439,14 @@ struct SetundefPass : public Pass { if (wire->name[0] == (wire_types ? '\\' : '$')) continue; - if (!wire->attributes.count(ID::init)) + if (!wire->attributes.count("\\init")) continue; - Const &initval = wire->attributes[ID::init]; + Const &initval = wire->attributes["\\init"]; initval.bits.resize(GetSize(wire), State::Sx); if (initval.is_fully_undef()) { - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); continue; } diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index cbed08a3f62..a3e969ef176 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -41,6 +41,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +using RTLIL::id2cstr; + #undef CLUSTER_CELLS_AND_PORTBOXES struct ShowWorker @@ -99,7 +101,7 @@ struct ShowWorker { sig.sort_and_unify(); for (auto &c : sig.chunks()) { - if (c.wire != nullptr) + if (c.wire != NULL) for (auto &s : color_selections) if (s.second.selected_members.count(module->name) > 0 && s.second.selected_members.at(module->name).count(c.wire->name) > 0) return stringf("color=\"%s\"", s.first.c_str()); @@ -216,7 +218,7 @@ struct ShowWorker if (sig.is_chunk()) { const RTLIL::SigChunk &c = sig.as_chunk(); - if (c.wire != nullptr && design->selected_member(module->name, c.wire->name)) { + if (c.wire != NULL && design->selected_member(module->name, c.wire->name)) { if (!range_check || c.wire->width == c.width) return stringf("n%d", id2num(c.wire->name)); } else { @@ -228,7 +230,7 @@ struct ShowWorker return std::string(); } - std::string gen_portbox(std::string port, RTLIL::SigSpec sig, bool driver, std::string *node = nullptr) + std::string gen_portbox(std::string port, RTLIL::SigSpec sig, bool driver, std::string *node = NULL) { std::string code; std::string net = gen_signode_simple(sig); @@ -285,7 +287,7 @@ struct ShowWorker else code += stringf("x%d:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", idx, port.c_str(), nextColor(sig).c_str(), widthLabel(sig.size()).c_str()); } - if (node != nullptr) + if (node != NULL) *node = stringf("x%d", idx); } else @@ -298,7 +300,7 @@ struct ShowWorker net_conn_map[net].bits = sig.size(); net_conn_map[net].color = nextColor(sig, net_conn_map[net].color); } - if (node != nullptr) + if (node != NULL) *node = net; } return code; @@ -364,20 +366,22 @@ struct ShowWorker std::set all_sources, all_sinks; std::map wires_on_demand; - for (auto wire : module->selected_wires()) { + for (auto &it : module->wires_) { + if (!design->selected_member(module->name, it.first)) + continue; const char *shape = "diamond"; - if (wire->port_input || wire->port_output) + if (it.second->port_input || it.second->port_output) shape = "octagon"; - if (wire->name[0] == '\\') { + if (it.first[0] == '\\') { fprintf(f, "n%d [ shape=%s, label=\"%s\", %s, fontcolor=\"black\" ];\n", - id2num(wire->name), shape, findLabel(wire->name.str()), - nextColor(RTLIL::SigSpec(wire), "color=\"black\"").c_str()); - if (wire->port_input) - all_sources.insert(stringf("n%d", id2num(wire->name))); - else if (wire->port_output) - all_sinks.insert(stringf("n%d", id2num(wire->name))); + id2num(it.first), shape, findLabel(it.first.str()), + nextColor(RTLIL::SigSpec(it.second), "color=\"black\"").c_str()); + if (it.second->port_input) + all_sources.insert(stringf("n%d", id2num(it.first))); + else if (it.second->port_output) + all_sinks.insert(stringf("n%d", id2num(it.first))); } else { - wires_on_demand[stringf("n%d", id2num(wire->name))] = wire->name.str(); + wires_on_demand[stringf("n%d", id2num(it.first))] = it.first.str(); } } @@ -394,12 +398,15 @@ struct ShowWorker fprintf(f, "}\n"); } - for (auto cell : module->selected_cells()) + for (auto &it : module->cells_) { + if (!design->selected_member(module->name, it.first)) + continue; + std::vector in_ports, out_ports; - for (auto &conn : cell->connections()) { - if (!ct.cell_output(cell->type, conn.first)) + for (auto &conn : it.second->connections()) { + if (!ct.cell_output(it.second->type, conn.first)) in_ports.push_back(conn.first); else out_ports.push_back(conn.first); @@ -412,12 +419,12 @@ struct ShowWorker for (auto &p : in_ports) label_string += stringf(" %s%s|", id2num(p), escape(p.str()), - genSignedLabels && cell->hasParam(p.str() + "_SIGNED") && - cell->getParam(p.str() + "_SIGNED").as_bool() ? "*" : ""); + genSignedLabels && it.second->hasParam(p.str() + "_SIGNED") && + it.second->getParam(p.str() + "_SIGNED").as_bool() ? "*" : ""); if (label_string[label_string.size()-1] == '|') label_string = label_string.substr(0, label_string.size()-1); - label_string += stringf("}|%s\\n%s|{", findLabel(cell->name.str()), escape(cell->type.str())); + label_string += stringf("}|%s\\n%s|{", findLabel(it.first.str()), escape(it.second->type.str())); for (auto &p : out_ports) label_string += stringf(" %s|", id2num(p), escape(p.str())); @@ -427,19 +434,19 @@ struct ShowWorker label_string += "}}"; std::string code; - for (auto &conn : cell->connections()) { - code += gen_portbox(stringf("c%d:p%d", id2num(cell->name), id2num(conn.first)), - conn.second, ct.cell_output(cell->type, conn.first)); + for (auto &conn : it.second->connections()) { + code += gen_portbox(stringf("c%d:p%d", id2num(it.first), id2num(conn.first)), + conn.second, ct.cell_output(it.second->type, conn.first)); } #ifdef CLUSTER_CELLS_AND_PORTBOXES if (!code.empty()) fprintf(f, "subgraph cluster_c%d {\nc%d [ shape=record, label=\"%s\"%s ];\n%s}\n", - id2num(cell->name), id2num(cell->name), label_string.c_str(), findColor(cell->name), code.c_str()); + id2num(it.first), id2num(it.first), label_string.c_str(), findColor(it.first), code.c_str()); else #endif fprintf(f, "c%d [ shape=record, label=\"%s\"%s ];\n%s", - id2num(cell->name), label_string.c_str(), findColor(cell->name.str()), code.c_str()); + id2num(it.first), label_string.c_str(), findColor(it.first.str()), code.c_str()); } for (auto &it : module->processes) @@ -475,8 +482,8 @@ struct ShowWorker } std::string proc_src = RTLIL::unescape_id(proc->name); - if (proc->attributes.count(ID::src) > 0) - proc_src = proc->attributes.at(ID::src).decode_string(); + if (proc->attributes.count("\\src") > 0) + proc_src = proc->attributes.at("\\src").decode_string(); fprintf(f, "p%d [shape=box, style=rounded, label=\"PROC %s\\n%s\"];\n", pidx, findLabel(proc->name.str()), proc_src.c_str()); } @@ -484,12 +491,12 @@ struct ShowWorker { bool found_lhs_wire = false; for (auto &c : conn.first.chunks()) { - if (c.wire == nullptr || design->selected_member(module->name, c.wire->name)) + if (c.wire == NULL || design->selected_member(module->name, c.wire->name)) found_lhs_wire = true; } bool found_rhs_wire = false; for (auto &c : conn.second.chunks()) { - if (c.wire == nullptr || design->selected_member(module->name, c.wire->name)) + if (c.wire == NULL || design->selected_member(module->name, c.wire->name)) found_rhs_wire = true; } if (!found_lhs_wire || !found_rhs_wire) @@ -565,21 +572,23 @@ struct ShowWorker design->optimize(); page_counter = 0; - for (auto mod : design->selected_modules()) + for (auto &mod_it : design->modules_) { - module = mod; + module = mod_it.second; + if (!design->selected_module(module->name)) + continue; if (design->selected_whole_module(module->name)) { if (module->get_blackbox_attribute()) { - // log("Skipping blackbox module %s.\n", log_id(module->name)); + // log("Skipping blackbox module %s.\n", id2cstr(module->name)); continue; } else - if (module->cells().size() == 0 && module->connections().empty() && module->processes.empty()) { - log("Skipping empty module %s.\n", log_id(module->name)); + if (module->cells_.empty() && module->connections().empty() && module->processes.empty()) { + log("Skipping empty module %s.\n", id2cstr(module->name)); continue; } else - log("Dumping module %s to page %d.\n", log_id(module->name), ++page_counter); + log("Dumping module %s to page %d.\n", id2cstr(module->name), ++page_counter); } else - log("Dumping selected parts of module %s to page %d.\n", log_id(module->name), ++page_counter); + log("Dumping selected parts of module %s to page %d.\n", id2cstr(module->name), ++page_counter); handle_module(); } } @@ -587,7 +596,7 @@ struct ShowWorker struct ShowPass : public Pass { ShowPass() : Pass("show", "generate schematics using graphviz") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -659,10 +668,6 @@ struct ShowPass : public Pass { log(" -notitle\n"); log(" do not add the module name as graph title to the dot file\n"); log("\n"); - log(" -nobg\n"); - log(" don't run viewer in the background, IE wait for the viewer tool to\n"); - log(" exit before returning\n"); - log("\n"); log("When no is specified, 'dot' is used. When no and is\n"); log("specified, 'xdot' is used to display the schematic (POSIX systems only).\n"); log("\n"); @@ -674,7 +679,7 @@ struct ShowPass : public Pass { log("the 'show' command is executed.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Generating Graphviz representation of design.\n"); log_push(); @@ -682,7 +687,7 @@ struct ShowPass : public Pass { std::vector> color_selections; std::vector> label_selections; -#if defined(_WIN32) || defined(YOSYS_DISABLE_SPAWN) +#if defined(EMSCRIPTEN) || defined(_WIN32) std::string format = "dot"; std::string prefix = "show"; #else @@ -701,7 +706,6 @@ struct ShowPass : public Pass { bool flag_abbreviate = true; bool flag_notitle = false; bool custom_prefix = false; - std::string background = "&"; RTLIL::IdString colorattr; size_t argidx; @@ -783,22 +787,19 @@ struct ShowPass : public Pass { flag_notitle = true; continue; } - if (arg == "-nobg") { - background= ""; - continue; - } break; } extra_args(args, argidx, design); if (format != "ps" && format != "dot") { int modcount = 0; - for (auto module : design->selected_modules()) { - if (module->get_blackbox_attribute()) + for (auto &mod_it : design->modules_) { + if (mod_it.second->get_blackbox_attribute()) continue; - if (module->cells().size() == 0 && module->connections().empty()) + if (mod_it.second->cells_.empty() && mod_it.second->connections().empty()) continue; - modcount++; + if (design->selected_module(mod_it.first)) + modcount++; } if (modcount > 1) log_cmd_error("For formats different than 'ps' or 'dot' only one module must be selected.\n"); @@ -825,7 +826,7 @@ struct ShowPass : public Pass { FILE *f = fopen(dot_file.c_str(), "w"); if (custom_prefix) yosys_output_files.insert(dot_file); - if (f == nullptr) { + if (f == NULL) { for (auto lib : libs) delete lib; log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file.c_str()); @@ -849,44 +850,40 @@ struct ShowPass : public Pass { std::string cmd = stringf(DOT_CMD, format.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str(), out_file.c_str()); #undef DOT_CMD log("Exec: %s\n", cmd.c_str()); - #if !defined(YOSYS_DISABLE_SPAWN) - if (run_command(cmd) != 0) - log_cmd_error("Shell command failed!\n"); - #endif + if (run_command(cmd) != 0) + log_cmd_error("Shell command failed!\n"); } - #if defined(YOSYS_DISABLE_SPAWN) - log_assert(viewer_exe.empty() && !format.empty()); - #else if (!viewer_exe.empty()) { #ifdef _WIN32 // system()/cmd.exe does not understand single quotes nor // background tasks on Windows. So we have to pause yosys // until the viewer exits. - std::string cmd = stringf("%s \"%s\"", viewer_exe.c_str(), out_file.c_str()); + #define VIEW_CMD "%s \"%s\"" #else - std::string cmd = stringf("%s '%s' %s", viewer_exe.c_str(), out_file.c_str(), background.c_str()); + #define VIEW_CMD "%s '%s' &" #endif + std::string cmd = stringf(VIEW_CMD, viewer_exe.c_str(), out_file.c_str()); + #undef VIEW_CMD log("Exec: %s\n", cmd.c_str()); if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); } else if (format.empty()) { #ifdef __APPLE__ - std::string cmd = stringf("ps -fu %d | grep -q '[ ]%s' || xdot '%s' %s", getuid(), dot_file.c_str(), dot_file.c_str(), background.c_str()); + std::string cmd = stringf("ps -fu %d | grep -q '[ ]%s' || xdot '%s' &", getuid(), dot_file.c_str(), dot_file.c_str()); #else - std::string cmd = stringf("{ test -f '%s.pid' && fuser -s '%s.pid' 2> /dev/null; } || ( echo $$ >&3; exec xdot '%s'; ) 3> '%s.pid' %s", dot_file.c_str(), dot_file.c_str(), dot_file.c_str(), dot_file.c_str(), background.c_str()); + std::string cmd = stringf("{ test -f '%s.pid' && fuser -s '%s.pid'; } || ( echo $$ >&3; exec xdot '%s'; ) 3> '%s.pid' &", dot_file.c_str(), dot_file.c_str(), dot_file.c_str(), dot_file.c_str()); #endif log("Exec: %s\n", cmd.c_str()); if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); } - #endif if (flag_pause) { #ifdef YOSYS_ENABLE_READLINE - char *input = nullptr; - while ((input = readline("Press ENTER to continue (or type 'shell' to open a shell)> ")) != nullptr) { + char *input = NULL; + while ((input = readline("Press ENTER to continue (or type 'shell' to open a shell)> ")) != NULL) { if (input[strspn(input, " \t\r\n")] == 0) break; char *p = input + strspn(input, " \t\r\n"); diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc index 20627d601e7..bafafca4ed3 100644 --- a/passes/cmds/splice.cc +++ b/passes/cmds/splice.cc @@ -75,13 +75,13 @@ struct SpliceWorker RTLIL::SigSpec new_sig = sig; if (sig_a.size() != sig.size()) { - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($slice)); - cell->parameters[ID::OFFSET] = offset; - cell->parameters[ID::A_WIDTH] = sig_a.size(); - cell->parameters[ID::Y_WIDTH] = sig.size(); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::Y, module->addWire(NEW_ID, sig.size())); - new_sig = cell->getPort(ID::Y); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$slice"); + cell->parameters["\\OFFSET"] = offset; + cell->parameters["\\A_WIDTH"] = sig_a.size(); + cell->parameters["\\Y_WIDTH"] = sig.size(); + cell->setPort("\\A", sig_a); + cell->setPort("\\Y", module->addWire(NEW_ID, sig.size())); + new_sig = cell->getPort("\\Y"); } sliced_signals_cache[sig] = new_sig; @@ -102,7 +102,7 @@ struct SpliceWorker for (auto &bit : sig.to_sigbit_vector()) { - if (bit.wire == nullptr) + if (bit.wire == NULL) { if (last_bit == 0) chunks.back().append(bit); @@ -132,13 +132,13 @@ struct SpliceWorker RTLIL::SigSpec new_sig = get_sliced_signal(chunks.front()); for (size_t i = 1; i < chunks.size(); i++) { RTLIL::SigSpec sig2 = get_sliced_signal(chunks[i]); - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($concat)); - cell->parameters[ID::A_WIDTH] = new_sig.size(); - cell->parameters[ID::B_WIDTH] = sig2.size(); - cell->setPort(ID::A, new_sig); - cell->setPort(ID::B, sig2); - cell->setPort(ID::Y, module->addWire(NEW_ID, new_sig.size() + sig2.size())); - new_sig = cell->getPort(ID::Y); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$concat"); + cell->parameters["\\A_WIDTH"] = new_sig.size(); + cell->parameters["\\B_WIDTH"] = sig2.size(); + cell->setPort("\\A", new_sig); + cell->setPort("\\B", sig2); + cell->setPort("\\Y", module->addWire(NEW_ID, new_sig.size() + sig2.size())); + new_sig = cell->getPort("\\Y"); } spliced_signals_cache[sig] = new_sig; @@ -149,23 +149,23 @@ struct SpliceWorker void run() { - log("Splicing signals in module %s:\n", log_id(module->name)); + log("Splicing signals in module %s:\n", RTLIL::id2cstr(module->name)); driven_bits.push_back(RTLIL::State::Sm); driven_bits.push_back(RTLIL::State::Sm); - for (auto wire : module->wires()) - if (wire->port_input) { - RTLIL::SigSpec sig = sigmap(wire); + for (auto &it : module->wires_) + if (it.second->port_input) { + RTLIL::SigSpec sig = sigmap(it.second); driven_chunks.insert(sig); for (auto &bit : sig.to_sigbit_vector()) driven_bits.push_back(bit); driven_bits.push_back(RTLIL::State::Sm); } - for (auto cell : module->cells()) - for (auto &conn : cell->connections()) - if (!ct.cell_known(cell->type) || ct.cell_output(cell->type, conn.first)) { + for (auto &it : module->cells_) + for (auto &conn : it.second->connections()) + if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first)) { RTLIL::SigSpec sig = sigmap(conn.second); driven_chunks.insert(sig); for (auto &bit : sig.to_sigbit_vector()) @@ -180,8 +180,9 @@ struct SpliceWorker SigPool selected_bits; if (!sel_by_cell) - for (auto wire : module->selected_wires()) - selected_bits.add(sigmap(wire)); + for (auto &it : module->wires_) + if (design->selected(module, it.second)) + selected_bits.add(sigmap(it.second)); std::vector mod_cells = module->cells(); @@ -246,7 +247,7 @@ struct SpliceWorker struct SplicePass : public Pass { SplicePass() : Pass("splice", "create explicit splicing cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -287,7 +288,7 @@ struct SplicePass : public Pass { log("by selected wires are rewired.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool sel_by_cell = false; bool sel_by_wire = false; @@ -342,14 +343,17 @@ struct SplicePass : public Pass { log_header(design, "Executing SPLICE pass (creating cells for signal splicing).\n"); - for (auto module : design->selected_modules()) + for (auto &mod_it : design->modules_) { - if (module->processes.size()) { - log("Skipping module %s as it contains processes.\n", module->name.c_str()); + if (!design->selected(mod_it.second)) + continue; + + if (mod_it.second->processes.size()) { + log("Skipping module %s as it contains processes.\n", mod_it.second->name.c_str()); continue; } - SpliceWorker worker(design, module); + SpliceWorker worker(design, mod_it.second); worker.sel_by_cell = sel_by_cell; worker.sel_by_wire = sel_by_wire; worker.sel_any_bit = sel_any_bit; diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index fff8a0d3efa..f5a1f17b3bd 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -59,26 +59,18 @@ struct SplitnetsWorker new_wire->port_id = wire->port_id ? wire->port_id + offset : 0; new_wire->port_input = wire->port_input; new_wire->port_output = wire->port_output; - new_wire->start_offset = wire->start_offset + offset; - auto it = wire->attributes.find(ID::src); - if (it != wire->attributes.end()) - new_wire->attributes.emplace(ID::src, it->second); + if (wire->attributes.count("\\src")) + new_wire->attributes["\\src"] = wire->attributes.at("\\src"); - it = wire->attributes.find(ID::hdlname); - if (it != wire->attributes.end()) - new_wire->attributes.emplace(ID::hdlname, it->second); + if (wire->attributes.count("\\keep")) + new_wire->attributes["\\keep"] = wire->attributes.at("\\keep"); - it = wire->attributes.find(ID::keep); - if (it != wire->attributes.end()) - new_wire->attributes.emplace(ID::keep, it->second); - - it = wire->attributes.find(ID::init); - if (it != wire->attributes.end()) { - Const old_init = it->second, new_init; + if (wire->attributes.count("\\init")) { + Const old_init = wire->attributes.at("\\init"), new_init; for (int i = offset; i < offset+width; i++) new_init.bits.push_back(i < GetSize(old_init) ? old_init.bits.at(i) : State::Sx); - new_wire->attributes.emplace(ID::init, new_init); + new_wire->attributes["\\init"] = new_init; } std::vector sigvec = RTLIL::SigSpec(new_wire).to_sigbit_vector(); @@ -95,7 +87,7 @@ struct SplitnetsWorker struct SplitnetsPass : public Pass { SplitnetsPass() : Pass("splitnets", "split up multi-bit nets") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -117,7 +109,7 @@ struct SplitnetsPass : public Pass { log(" and split nets so that no driver drives only part of a net.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_ports = false; bool flag_driver = false; @@ -149,9 +141,6 @@ struct SplitnetsPass : public Pass { for (auto module : design->selected_modules()) { - if (module->has_processes_warn()) - continue; - SplitnetsWorker worker; if (flag_ports) @@ -174,12 +163,12 @@ struct SplitnetsPass : public Pass { std::map> split_wires_at; - for (auto c : module->cells()) - for (auto &p : c->connections()) + for (auto &c : module->cells_) + for (auto &p : c.second->connections()) { - if (!ct.cell_known(c->type)) + if (!ct.cell_known(c.second->type)) continue; - if (!ct.cell_output(c->type, p.first)) + if (!ct.cell_output(c.second->type, p.first)) continue; RTLIL::SigSpec sig = p.second; @@ -206,8 +195,9 @@ struct SplitnetsPass : public Pass { } else { - for (auto wire : module->wires()) { - if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, wire)) + for (auto &w : module->wires_) { + RTLIL::Wire *wire = w.second; + if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, w.second)) worker.splitmap[wire] = std::vector(); } diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index ed51fdc2472..c8e4f398128 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -79,15 +79,18 @@ struct statdata_t STAT_NUMERIC_MEMBERS #undef X - for (auto wire : mod->selected_wires()) + for (auto &it : mod->wires_) { - if (wire->name[0] == '\\') { + if (!design->selected(mod, it.second)) + continue; + + if (it.first[0] == '\\') { num_pub_wires++; - num_pub_wire_bits += wire->width; + num_pub_wire_bits += it.second->width; } num_wires++; - num_wire_bits += wire->width; + num_wire_bits += it.second->width; } for (auto &it : mod->memories) { @@ -97,31 +100,31 @@ struct statdata_t num_memory_bits += it.second->width * it.second->size; } - for (auto cell : mod->selected_cells()) + for (auto &it : mod->cells_) { - RTLIL::IdString cell_type = cell->type; + if (!design->selected(mod, it.second)) + continue; + + RTLIL::IdString cell_type = it.second->type; if (width_mode) { - if (cell_type.in(ID($not), ID($pos), ID($neg), - ID($logic_not), ID($logic_and), ID($logic_or), - ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), - ID($lut), ID($and), ID($or), ID($xor), ID($xnor), - ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), - ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), - ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow), ID($alu))) { - int width_a = cell->hasPort(ID::A) ? GetSize(cell->getPort(ID::A)) : 0; - int width_b = cell->hasPort(ID::B) ? GetSize(cell->getPort(ID::B)) : 0; - int width_y = cell->hasPort(ID::Y) ? GetSize(cell->getPort(ID::Y)) : 0; + if (cell_type.in("$not", "$pos", "$neg", + "$logic_not", "$logic_and", "$logic_or", + "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", + "$lut", "$and", "$or", "$xor", "$xnor", + "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", + "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", + "$add", "$sub", "$mul", "$div", "$mod", "$pow", "$alu")) { + int width_a = it.second->hasPort("\\A") ? GetSize(it.second->getPort("\\A")) : 0; + int width_b = it.second->hasPort("\\B") ? GetSize(it.second->getPort("\\B")) : 0; + int width_y = it.second->hasPort("\\Y") ? GetSize(it.second->getPort("\\Y")) : 0; cell_type = stringf("%s_%d", cell_type.c_str(), max({width_a, width_b, width_y})); } - else if (cell_type.in(ID($mux), ID($pmux))) - cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y))); - else if (cell_type.in( - ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), - ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), - ID($dlatch), ID($adlatch), ID($dlatchsr))) - cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Q))); + else if (cell_type.in("$mux", "$pmux")) + cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(it.second->getPort("\\Y"))); + else if (cell_type.in("$sr", "$dff", "$dffsr", "$adff", "$dlatch", "$dlatchsr")) + cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(it.second->getPort("\\Q"))); } if (!cell_area.empty()) { @@ -154,7 +157,7 @@ struct statdata_t log(" Number of cells: %6d\n", num_cells); for (auto &it : num_cells_by_type) if (it.second) - log(" %-26s %6d\n", log_id(it.first), it.second); + log(" %-26s %6d\n", RTLIL::id2cstr(it.first), it.second); if (!unknown_cell_area.empty()) { log("\n"); @@ -169,12 +172,12 @@ struct statdata_t if (tech == "xilinx") { - int lut6_cnt = num_cells_by_type[ID(LUT6)]; - int lut5_cnt = num_cells_by_type[ID(LUT5)]; - int lut4_cnt = num_cells_by_type[ID(LUT4)]; - int lut3_cnt = num_cells_by_type[ID(LUT3)]; - int lut2_cnt = num_cells_by_type[ID(LUT2)]; - int lut1_cnt = num_cells_by_type[ID(LUT1)]; + int lut6_cnt = num_cells_by_type["\\LUT6"]; + int lut5_cnt = num_cells_by_type["\\LUT5"]; + int lut4_cnt = num_cells_by_type["\\LUT4"]; + int lut3_cnt = num_cells_by_type["\\LUT3"]; + int lut2_cnt = num_cells_by_type["\\LUT2"]; + int lut1_cnt = num_cells_by_type["\\LUT1"]; int lc_cnt = 0; lc_cnt += lut6_cnt; @@ -232,7 +235,7 @@ struct statdata_t if (gate_costs.count(ctype)) tran_cnt += cnum * gate_costs.at(ctype); - else if (ctype.in(ID($_DFF_P_), ID($_DFF_N_))) + else if (ctype.in("$_DFF_P_", "$_DFF_N_")) tran_cnt += cnum * 16; else tran_cnt_exact = false; @@ -252,7 +255,7 @@ statdata_t hierarchy_worker(std::map &mod_stat, RTL for (auto &it : num_cells_by_type) if (mod_stat.count(it.first) > 0) { - log(" %*s%-*s %6d\n", 2*level, "", 26-2*level, log_id(it.first), it.second); + log(" %*s%-*s %6d\n", 2*level, "", 26-2*level, RTLIL::id2cstr(it.first), it.second); mod_data = mod_data + hierarchy_worker(mod_stat, it.first, level+1) * it.second; mod_data.num_cells -= it.second; } else { @@ -278,14 +281,14 @@ void read_liberty_cellarea(dict &cell_area, string liberty_fil continue; LibertyAst *ar = cell->find("area"); - if (ar != nullptr && !ar->value.empty()) + if (ar != NULL && !ar->value.empty()) cell_area["\\" + cell->args[0]] = atof(ar->value.c_str()); } } struct StatPass : public Pass { StatPass() : Pass("stat", "print some statistics") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -311,12 +314,12 @@ struct StatPass : public Pass { log(" e.g. $add_8 for an 8 bit wide $add cell.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Printing statistics.\n"); bool width_mode = false; - RTLIL::Module *top_mod = nullptr; + RTLIL::Module *top_mod = NULL; std::map mod_stat; dict cell_area; string techname; @@ -339,9 +342,9 @@ struct StatPass : public Pass { continue; } if (args[argidx] == "-top" && argidx+1 < args.size()) { - if (design->module(RTLIL::escape_id(args[argidx+1])) == nullptr) + if (design->modules_.count(RTLIL::escape_id(args[argidx+1])) == 0) log_cmd_error("Can't find module %s.\n", args[argidx+1].c_str()); - top_mod = design->module(RTLIL::escape_id(args[++argidx])); + top_mod = design->modules_.at(RTLIL::escape_id(args[++argidx])); continue; } break; @@ -354,25 +357,25 @@ struct StatPass : public Pass { for (auto mod : design->selected_modules()) { if (!top_mod && design->full_selection()) - if (mod->get_bool_attribute(ID::top)) + if (mod->get_bool_attribute("\\top")) top_mod = mod; statdata_t data(design, mod, width_mode, cell_area, techname); mod_stat[mod->name] = data; log("\n"); - log("=== %s%s ===\n", log_id(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)"); + log("=== %s%s ===\n", RTLIL::id2cstr(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)"); log("\n"); data.log_data(mod->name, false); } - if (top_mod != nullptr && GetSize(mod_stat) > 1) + if (top_mod != NULL && GetSize(mod_stat) > 1) { log("\n"); log("=== design hierarchy ===\n"); log("\n"); - log(" %-28s %6d\n", log_id(top_mod->name), 1); + log(" %-28s %6d\n", RTLIL::id2cstr(top_mod->name), 1); statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0); log("\n"); diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc index 60689fc825a..1a44bdaecbd 100644 --- a/passes/cmds/tee.cc +++ b/passes/cmds/tee.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct TeePass : public Pass { TeePass() : Pass("tee", "redirect command output to file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -49,7 +49,7 @@ struct TeePass : public Pass { log(" Add/subtract INT from the -v setting for this command.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::vector backup_log_files, files_to_close; std::vector backup_log_streams; diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc index 30e76081e45..3c0eac8de51 100644 --- a/passes/cmds/torder.cc +++ b/passes/cmds/torder.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct TorderPass : public Pass { TorderPass() : Pass("torder", "print cells in topological order") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -43,7 +43,7 @@ struct TorderPass : public Pass { log(" are not used in topological sorting. this option deactivates that.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool noautostop = false; dict> stop_db; @@ -81,9 +81,9 @@ struct TorderPass : public Pass { continue; if (!noautostop && yosys_celltypes.cell_known(cell->type)) { - if (conn.first.in(ID::Q, ID::CTRL_OUT, ID::RD_DATA)) + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) continue; - if (cell->type == ID($memrd) && conn.first == ID::DATA) + if (cell->type == "$memrd" && conn.first == "\\DATA") continue; } diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc index 10742c3706c..cf3e46ace2d 100644 --- a/passes/cmds/trace.cc +++ b/passes/cmds/trace.cc @@ -25,34 +25,34 @@ PRIVATE_NAMESPACE_BEGIN struct TraceMonitor : public RTLIL::Monitor { - void notify_module_add(RTLIL::Module *module) override + void notify_module_add(RTLIL::Module *module) YS_OVERRIDE { log("#TRACE# Module add: %s\n", log_id(module)); } - void notify_module_del(RTLIL::Module *module) override + void notify_module_del(RTLIL::Module *module) YS_OVERRIDE { log("#TRACE# Module delete: %s\n", log_id(module)); } - void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override + void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE { log("#TRACE# Cell connect: %s.%s.%s = %s (was: %s)\n", log_id(cell->module), log_id(cell), log_id(port), log_signal(sig), log_signal(old_sig)); } - void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) override + void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) YS_OVERRIDE { log("#TRACE# Connection in module %s: %s = %s\n", log_id(module), log_signal(sigsig.first), log_signal(sigsig.second)); } - void notify_connect(RTLIL::Module *module, const std::vector &sigsig_vec) override + void notify_connect(RTLIL::Module *module, const std::vector &sigsig_vec) YS_OVERRIDE { log("#TRACE# New connections in module %s:\n", log_id(module)); for (auto &sigsig : sigsig_vec) log("## %s = %s\n", log_signal(sigsig.first), log_signal(sigsig.second)); } - void notify_blackout(RTLIL::Module *module) override + void notify_blackout(RTLIL::Module *module) YS_OVERRIDE { log("#TRACE# Blackout in module %s:\n", log_id(module)); } @@ -60,7 +60,7 @@ struct TraceMonitor : public RTLIL::Monitor struct TracePass : public Pass { TracePass() : Pass("trace", "redirect command output to file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -70,7 +70,7 @@ struct TracePass : public Pass { log("the design in real time.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -96,7 +96,7 @@ struct TracePass : public Pass { struct DebugPass : public Pass { DebugPass() : Pass("debug", "run command with debug log messages enabled") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -105,7 +105,7 @@ struct DebugPass : public Pass { log("Execute the specified command with debug log messages enabled\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc index 3d898a5efef..64a762d7caf 100644 --- a/passes/cmds/write_file.cc +++ b/passes/cmds/write_file.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct WriteFileFrontend : public Frontend { WriteFileFrontend() : Frontend("=write_file", "write a text to a file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -44,7 +44,7 @@ struct WriteFileFrontend : public Frontend { log(" EOT\n"); log("\n"); } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design*) override + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design*) YS_OVERRIDE { bool append_mode = false; std::string output_filename; diff --git a/passes/equiv/equiv_add.cc b/passes/equiv/equiv_add.cc index 2abbb59bbb0..71599f46e5c 100644 --- a/passes/equiv/equiv_add.cc +++ b/passes/equiv/equiv_add.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct EquivAddPass : public Pass { EquivAddPass() : Pass("equiv_add", "add a $equiv cell") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -39,7 +39,7 @@ struct EquivAddPass : public Pass { log("This command adds $equiv cells for the ports of the specified cells.\n"); log("\n"); } - void execute(std::vector args, Design *design) override + void execute(std::vector args, Design *design) YS_OVERRIDE { bool try_mode = false; @@ -152,7 +152,7 @@ struct EquivAddPass : public Pass { for (int i = 0; i < GetSize(gold_signal); i++) { Cell *equiv_cell = module->addEquiv(NEW_ID, gold_signal[i], gate_signal[i], equiv_signal[i]); - equiv_cell->set_bool_attribute(ID::keep); + equiv_cell->set_bool_attribute("\\keep"); to_equiv_bits[gold_signal[i]] = equiv_signal[i]; to_equiv_bits[gate_signal[i]] = equiv_signal[i]; added_equiv_cells.insert(equiv_cell); diff --git a/passes/equiv/equiv_induct.cc b/passes/equiv/equiv_induct.cc index 596c938fc08..bcc68d6d2ce 100644 --- a/passes/equiv/equiv_induct.cc +++ b/passes/equiv/equiv_induct.cc @@ -58,9 +58,9 @@ struct EquivInductWorker log_warning("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type)); cell_warn_cache.insert(cell); } - if (cell->type == ID($equiv)) { - SigBit bit_a = sigmap(cell->getPort(ID::A)).as_bit(); - SigBit bit_b = sigmap(cell->getPort(ID::B)).as_bit(); + if (cell->type == "$equiv") { + SigBit bit_a = sigmap(cell->getPort("\\A")).as_bit(); + SigBit bit_b = sigmap(cell->getPort("\\B")).as_bit(); if (bit_a != bit_b) { int ez_a = satgen.importSigBit(bit_a, step); int ez_b = satgen.importSigBit(bit_b, step); @@ -125,7 +125,7 @@ struct EquivInductWorker if (!ez->solve(new_step_not_consistent)) { log(" Proof for induction step holds. Entire workset of %d cells proven!\n", GetSize(workset)); for (auto cell : workset) - cell->setPort(ID::B, cell->getPort(ID::A)); + cell->setPort("\\B", cell->getPort("\\A")); success_counter += GetSize(workset); return; } @@ -137,10 +137,10 @@ struct EquivInductWorker for (auto cell : workset) { - SigBit bit_a = sigmap(cell->getPort(ID::A)).as_bit(); - SigBit bit_b = sigmap(cell->getPort(ID::B)).as_bit(); + SigBit bit_a = sigmap(cell->getPort("\\A")).as_bit(); + SigBit bit_b = sigmap(cell->getPort("\\B")).as_bit(); - log(" Trying to prove $equiv for %s:", log_signal(sigmap(cell->getPort(ID::Y)))); + log(" Trying to prove $equiv for %s:", log_signal(sigmap(cell->getPort("\\Y")))); int ez_a = satgen.importSigBit(bit_a, max_seq+1); int ez_b = satgen.importSigBit(bit_b, max_seq+1); @@ -151,7 +151,7 @@ struct EquivInductWorker if (!ez->solve(cond)) { log(" success!\n"); - cell->setPort(ID::B, cell->getPort(ID::A)); + cell->setPort("\\B", cell->getPort("\\A")); success_counter++; } else { log(" failed.\n"); @@ -162,7 +162,7 @@ struct EquivInductWorker struct EquivInductPass : public Pass { EquivInductPass() : Pass("equiv_induct", "proving $equiv cells using temporal induction") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -192,7 +192,7 @@ struct EquivInductPass : public Pass { log("after reset.\n"); log("\n"); } - void execute(std::vector args, Design *design) override + void execute(std::vector args, Design *design) YS_OVERRIDE { int success_counter = 0; bool model_undef = false; @@ -219,8 +219,8 @@ struct EquivInductPass : public Pass { pool unproven_equiv_cells; for (auto cell : module->selected_cells()) - if (cell->type == ID($equiv)) { - if (cell->getPort(ID::A) != cell->getPort(ID::B)) + if (cell->type == "$equiv") { + if (cell->getPort("\\A") != cell->getPort("\\B")) unproven_equiv_cells.insert(cell); } diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc index 51b4ad0f136..4855ce29e02 100644 --- a/passes/equiv/equiv_make.cc +++ b/passes/equiv/equiv_make.cc @@ -406,7 +406,7 @@ struct EquivMakeWorker void init_bit2driven() { for (auto cell : equiv_mod->cells()) { - if (!ct.cell_known(cell->type) && !cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_), ID($ff), ID($_FF_))) + if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_")) continue; for (auto &conn : cell->connections()) { @@ -466,7 +466,7 @@ struct EquivMakeWorker struct EquivMakePass : public Pass { EquivMakePass() : Pass("equiv_make", "prepare a circuit for equivalence checking") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -491,7 +491,7 @@ struct EquivMakePass : public Pass { log("checking problem. Use 'miter -equiv' if you want to create a miter circuit.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { EquivMakeWorker worker; worker.ct.setup(design); diff --git a/passes/equiv/equiv_mark.cc b/passes/equiv/equiv_mark.cc index a722b5ed634..135eaf145c3 100644 --- a/passes/equiv/equiv_mark.cc +++ b/passes/equiv/equiv_mark.cc @@ -48,7 +48,7 @@ struct EquivMarkWorker { for (auto cell : module->cells()) { - if (cell->type == ID($equiv)) + if (cell->type == "$equiv") equiv_cells.insert(cell->name); for (auto &port : cell->connections()) @@ -122,8 +122,8 @@ struct EquivMarkWorker { auto cell = module->cell(cell_name); - SigSpec sig_a = sigmap(cell->getPort(ID::A)); - SigSpec sig_b = sigmap(cell->getPort(ID::B)); + SigSpec sig_a = sigmap(cell->getPort("\\A")); + SigSpec sig_b = sigmap(cell->getPort("\\B")); if (sig_a == sig_b) { for (auto bit : sig_a) @@ -139,11 +139,11 @@ struct EquivMarkWorker for (auto cell : module->cells()) { - if (cell_regions.count(cell->name) || cell->type != ID($equiv)) + if (cell_regions.count(cell->name) || cell->type != "$equiv") continue; - SigSpec sig_a = sigmap(cell->getPort(ID::A)); - SigSpec sig_b = sigmap(cell->getPort(ID::B)); + SigSpec sig_a = sigmap(cell->getPort("\\A")); + SigSpec sig_b = sigmap(cell->getPort("\\B")); log_assert(sig_a != sig_b); @@ -176,10 +176,10 @@ struct EquivMarkWorker { if (cell_regions.count(cell->name)) { int r = final_region_map.at(cell_regions.at(cell->name)); - cell->attributes[ID::equiv_region] = Const(r); + cell->attributes["\\equiv_region"] = Const(r); region_cell_count[r]++; } else - cell->attributes.erase(ID::equiv_region); + cell->attributes.erase("\\equiv_region"); } for (auto wire : module->wires()) @@ -191,10 +191,10 @@ struct EquivMarkWorker if (GetSize(regions) == 1) { int r = final_region_map.at(*regions.begin()); - wire->attributes[ID::equiv_region] = Const(r); + wire->attributes["\\equiv_region"] = Const(r); region_wire_count[r]++; } else - wire->attributes.erase(ID::equiv_region); + wire->attributes.erase("\\equiv_region"); } for (int i = 0; i < next_final_region; i++) @@ -204,7 +204,7 @@ struct EquivMarkWorker struct EquivMarkPass : public Pass { EquivMarkPass() : Pass("equiv_mark", "mark equivalence checking regions") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -216,7 +216,7 @@ struct EquivMarkPass : public Pass { log("wires and cells.\n"); log("\n"); } - void execute(std::vector args, Design *design) override + void execute(std::vector args, Design *design) YS_OVERRIDE { log_header(design, "Executing EQUIV_MARK pass.\n"); diff --git a/passes/equiv/equiv_miter.cc b/passes/equiv/equiv_miter.cc index e028f806acf..e06f9515b32 100644 --- a/passes/equiv/equiv_miter.cc +++ b/passes/equiv/equiv_miter.cc @@ -47,7 +47,7 @@ struct EquivMiterWorker if (cone.count(c)) return; - if (c->type == ID($equiv) && !seed_cells.count(c)) { + if (c->type == "$equiv" && !seed_cells.count(c)) { leaves.insert(c); return; } @@ -57,7 +57,7 @@ struct EquivMiterWorker for (auto &conn : c->connections()) { if (!ct.cell_input(c->type, conn.first)) continue; - if (c->type == ID($equiv) && (conn.first == ID::A) != gold_mode) + if (c->type == "$equiv" && (conn.first == "\\A") != gold_mode) continue; for (auto bit : sigmap(conn.second)) if (bit_to_driver.count(bit)) @@ -81,7 +81,7 @@ struct EquivMiterWorker // find seed cells for (auto c : source_module->selected_cells()) - if (c->type == ID($equiv)) { + if (c->type == "$equiv") { log("Seed $equiv cell: %s\n", log_id(c)); seed_cells.insert(c); } @@ -213,18 +213,18 @@ struct EquivMiterWorker vector equiv_cells; for (auto c : miter_module->cells()) - if (c->type == ID($equiv) && c->getPort(ID::A) != c->getPort(ID::B)) + if (c->type == "$equiv" && c->getPort("\\A") != c->getPort("\\B")) equiv_cells.push_back(c); for (auto c : equiv_cells) { SigSpec cmp = mode_undef ? - miter_module->LogicOr(NEW_ID, miter_module->Eqx(NEW_ID, c->getPort(ID::A), State::Sx), - miter_module->Eqx(NEW_ID, c->getPort(ID::A), c->getPort(ID::B))) : - miter_module->Eq(NEW_ID, c->getPort(ID::A), c->getPort(ID::B)); + miter_module->LogicOr(NEW_ID, miter_module->Eqx(NEW_ID, c->getPort("\\A"), State::Sx), + miter_module->Eqx(NEW_ID, c->getPort("\\A"), c->getPort("\\B"))) : + miter_module->Eq(NEW_ID, c->getPort("\\A"), c->getPort("\\B")); if (mode_cmp) { - string cmp_name = stringf("\\cmp%s", log_signal(c->getPort(ID::Y))); + string cmp_name = string("\\cmp") + log_signal(c->getPort("\\Y")); for (int i = 1; i < GetSize(cmp_name); i++) if (cmp_name[i] == '\\') cmp_name[i] = '_'; @@ -242,7 +242,7 @@ struct EquivMiterWorker } if (mode_trigger) { - auto w = miter_module->addWire(ID(trigger)); + auto w = miter_module->addWire("\\trigger"); w->port_output = true; miter_module->addReduceOr(NEW_ID, trigger_signals, w); } @@ -261,7 +261,7 @@ struct EquivMiterWorker struct EquivMiterPass : public Pass { EquivMiterPass() : Pass("equiv_miter", "extract miter from equiv circuit") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -282,7 +282,7 @@ struct EquivMiterPass : public Pass { log(" Create compare logic that handles undefs correctly\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { EquivMiterWorker worker; worker.ct.setup(design); diff --git a/passes/equiv/equiv_opt.cc b/passes/equiv/equiv_opt.cc index 4d04004481e..c7e6d71a62e 100644 --- a/passes/equiv/equiv_opt.cc +++ b/passes/equiv/equiv_opt.cc @@ -26,7 +26,7 @@ struct EquivOptPass:public ScriptPass { EquivOptPass() : ScriptPass("equiv_opt", "prove equivalence for optimized circuit") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -44,10 +44,6 @@ struct EquivOptPass:public ScriptPass log(" expand the modules in this file before proving equivalence. this is\n"); log(" useful for handling architecture-specific primitives.\n"); log("\n"); - log(" -blacklist \n"); - log(" Do not match cells or signals that match the names in the file\n"); - log(" (passed to equiv_make).\n"); - log("\n"); log(" -assert\n"); log(" produce an error if the circuits are not equivalent.\n"); log("\n"); @@ -65,21 +61,20 @@ struct EquivOptPass:public ScriptPass log("\n"); } - std::string command, techmap_opts, make_opts; + std::string command, techmap_opts; bool assert, undef, multiclock, async2sync; - void clear_flags() override + void clear_flags() YS_OVERRIDE { command = ""; techmap_opts = ""; - make_opts = ""; assert = false; undef = false; multiclock = false; async2sync = false; } - void execute(std::vector < std::string > args, RTLIL::Design * design) override + void execute(std::vector < std::string > args, RTLIL::Design * design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -98,10 +93,6 @@ struct EquivOptPass:public ScriptPass techmap_opts += " -map " + args[++argidx]; continue; } - if (args[argidx] == "-blacklist" && argidx + 1 < args.size()) { - make_opts += " -blacklist " + args[++argidx]; - continue; - } if (args[argidx] == "-assert") { assert = true; continue; @@ -148,7 +139,7 @@ struct EquivOptPass:public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("run_pass")) { run("hierarchy -auto-top"); @@ -179,12 +170,7 @@ struct EquivOptPass:public ScriptPass run("clk2fflogic", "(only with -multiclock)"); if (async2sync || help_mode) run("async2sync", " (only with -async2sync)"); - string opts; - if (help_mode) - opts = " -blacklist ..."; - else - opts = make_opts; - run("equiv_make" + opts + " gold gate equiv"); + run("equiv_make gold gate equiv"); if (help_mode) run("equiv_induct [-undef] equiv"); else if (undef) diff --git a/passes/equiv/equiv_purge.cc b/passes/equiv/equiv_purge.cc index d15c8d1836b..18b3e7d3681 100644 --- a/passes/equiv/equiv_purge.cc +++ b/passes/equiv/equiv_purge.cc @@ -102,7 +102,7 @@ struct EquivPurgeWorker for (auto cell : module->cells()) { - if (cell->type != ID($equiv)) { + if (cell->type != "$equiv") { for (auto &port : cell->connections()) { if (cell->input(port.first)) for (auto bit : sigmap(port.second)) @@ -114,9 +114,9 @@ struct EquivPurgeWorker continue; } - SigSpec sig_a = sigmap(cell->getPort(ID::A)); - SigSpec sig_b = sigmap(cell->getPort(ID::B)); - SigSpec sig_y = sigmap(cell->getPort(ID::Y)); + SigSpec sig_a = sigmap(cell->getPort("\\A")); + SigSpec sig_b = sigmap(cell->getPort("\\B")); + SigSpec sig_y = sigmap(cell->getPort("\\Y")); if (sig_a == sig_b) continue; @@ -130,7 +130,7 @@ struct EquivPurgeWorker for (auto bit : sig_y) visited.insert(bit); - cell->setPort(ID::Y, make_output(sig_y, cell->name)); + cell->setPort("\\Y", make_output(sig_y, cell->name)); } SigSpec srcsig; @@ -167,8 +167,8 @@ struct EquivPurgeWorker rewrite_sigmap.add(chunk, make_input(chunk)); for (auto cell : module->cells()) - if (cell->type == ID($equiv)) - cell->setPort(ID::Y, rewrite_sigmap(sigmap(cell->getPort(ID::Y)))); + if (cell->type == "$equiv") + cell->setPort("\\Y", rewrite_sigmap(sigmap(cell->getPort("\\Y")))); module->fixup_ports(); } @@ -176,7 +176,7 @@ struct EquivPurgeWorker struct EquivPurgePass : public Pass { EquivPurgePass() : Pass("equiv_purge", "purge equivalence checking module") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -187,7 +187,7 @@ struct EquivPurgePass : public Pass { log("ports as needed.\n"); log("\n"); } - void execute(std::vector args, Design *design) override + void execute(std::vector args, Design *design) YS_OVERRIDE { log_header(design, "Executing EQUIV_PURGE pass.\n"); diff --git a/passes/equiv/equiv_remove.cc b/passes/equiv/equiv_remove.cc index 89442308b41..c5c28c7d94b 100644 --- a/passes/equiv/equiv_remove.cc +++ b/passes/equiv/equiv_remove.cc @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN struct EquivRemovePass : public Pass { EquivRemovePass() : Pass("equiv_remove", "remove $equiv cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -40,7 +40,7 @@ struct EquivRemovePass : public Pass { log(" keep gate circuit\n"); log("\n"); } - void execute(std::vector args, Design *design) override + void execute(std::vector args, Design *design) YS_OVERRIDE { bool mode_gold = false; bool mode_gate = false; @@ -68,9 +68,9 @@ struct EquivRemovePass : public Pass { for (auto module : design->selected_modules()) { for (auto cell : module->selected_cells()) - if (cell->type == ID($equiv) && (mode_gold || mode_gate || cell->getPort(ID::A) == cell->getPort(ID::B))) { - log("Removing $equiv cell %s.%s (%s).\n", log_id(module), log_id(cell), log_signal(cell->getPort(ID::Y))); - module->connect(cell->getPort(ID::Y), mode_gate ? cell->getPort(ID::B) : cell->getPort(ID::A)); + if (cell->type == "$equiv" && (mode_gold || mode_gate || cell->getPort("\\A") == cell->getPort("\\B"))) { + log("Removing $equiv cell %s.%s (%s).\n", log_id(module), log_id(cell), log_signal(cell->getPort("\\Y"))); + module->connect(cell->getPort("\\Y"), mode_gate ? cell->getPort("\\B") : cell->getPort("\\A")); module->remove(cell); remove_count++; } diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc index 408c5a7934f..c2fab26f2bc 100644 --- a/passes/equiv/equiv_simple.cc +++ b/passes/equiv/equiv_simple.cc @@ -60,8 +60,8 @@ struct EquivSimpleWorker for (auto &conn : cell->connections()) if (yosys_celltypes.cell_input(cell->type, conn.first)) for (auto bit : sigmap(conn.second)) { - if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_), ID($ff), ID($_FF_))) { - if (!conn.first.in(ID::CLK, ID::C)) + if (cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_")) { + if (!conn.first.in("\\CLK", "\\C")) next_seed.insert(bit); } else find_input_cone(next_seed, cells_cone, bits_cone, cells_stop, bits_stop, input_bits, bit); @@ -90,8 +90,8 @@ struct EquivSimpleWorker bool run_cell() { - SigBit bit_a = sigmap(equiv_cell->getPort(ID::A)).as_bit(); - SigBit bit_b = sigmap(equiv_cell->getPort(ID::B)).as_bit(); + SigBit bit_a = sigmap(equiv_cell->getPort("\\A")).as_bit(); + SigBit bit_b = sigmap(equiv_cell->getPort("\\B")).as_bit(); int ez_context = ez->frozen_literal(); if (satgen.model_undef) @@ -115,9 +115,9 @@ struct EquivSimpleWorker if (verbose) { log(" Trying to prove $equiv cell %s:\n", log_id(equiv_cell)); - log(" A = %s, B = %s, Y = %s\n", log_signal(bit_a), log_signal(bit_b), log_signal(equiv_cell->getPort(ID::Y))); + log(" A = %s, B = %s, Y = %s\n", log_signal(bit_a), log_signal(bit_b), log_signal(equiv_cell->getPort("\\Y"))); } else { - log(" Trying to prove $equiv for %s:", log_signal(equiv_cell->getPort(ID::Y))); + log(" Trying to prove $equiv for %s:", log_signal(equiv_cell->getPort("\\Y"))); } int step = max_seq; @@ -199,7 +199,7 @@ struct EquivSimpleWorker if (!ez->solve(ez_context)) { log(verbose ? " Proved equivalence! Marking $equiv cell as proven.\n" : " success!\n"); - equiv_cell->setPort(ID::B, equiv_cell->getPort(ID::A)); + equiv_cell->setPort("\\B", equiv_cell->getPort("\\A")); ez->assume(ez->NOT(ez_context)); return true; } @@ -256,7 +256,7 @@ struct EquivSimpleWorker if (GetSize(equiv_cells) > 1) { SigSpec sig; for (auto c : equiv_cells) - sig.append(sigmap(c->getPort(ID::Y))); + sig.append(sigmap(c->getPort("\\Y"))); log(" Grouping SAT models for %s:\n", log_signal(sig)); } @@ -273,7 +273,7 @@ struct EquivSimpleWorker struct EquivSimplePass : public Pass { EquivSimplePass() : Pass("equiv_simple", "try proving simple $equiv instances") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -298,7 +298,7 @@ struct EquivSimplePass : public Pass { log(" the max. number of time steps to be considered (default = 1)\n"); log("\n"); } - void execute(std::vector args, Design *design) override + void execute(std::vector args, Design *design) YS_OVERRIDE { bool verbose = false, short_cones = false, model_undef = false, nogroup = false; int success_counter = 0; @@ -344,8 +344,8 @@ struct EquivSimplePass : public Pass { int unproven_cells_counter = 0; for (auto cell : module->selected_cells()) - if (cell->type == ID($equiv) && cell->getPort(ID::A) != cell->getPort(ID::B)) { - auto bit = sigmap(cell->getPort(ID::Y).as_bit()); + if (cell->type == "$equiv" && cell->getPort("\\A") != cell->getPort("\\B")) { + auto bit = sigmap(cell->getPort("\\Y").as_bit()); auto bit_group = bit; if (!nogroup && bit_group.wire) bit_group.offset = 0; @@ -360,7 +360,7 @@ struct EquivSimplePass : public Pass { unproven_cells_counter, GetSize(unproven_equiv_cells), log_id(module)); for (auto cell : module->cells()) { - if (!ct.cell_known(cell->type) && !cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_), ID($ff), ID($_FF_))) + if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_")) continue; for (auto &conn : cell->connections()) if (yosys_celltypes.cell_output(cell->type, conn.first)) diff --git a/passes/equiv/equiv_status.cc b/passes/equiv/equiv_status.cc index 2db44ea908b..b4a93ccf5d3 100644 --- a/passes/equiv/equiv_status.cc +++ b/passes/equiv/equiv_status.cc @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN struct EquivStatusPass : public Pass { EquivStatusPass() : Pass("equiv_status", "print status of equivalent checking module") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -36,7 +36,7 @@ struct EquivStatusPass : public Pass { log(" produce an error if any unproven $equiv cell is found\n"); log("\n"); } - void execute(std::vector args, Design *design) override + void execute(std::vector args, Design *design) YS_OVERRIDE { bool assert_mode = false; int unproven_count = 0; @@ -59,8 +59,8 @@ struct EquivStatusPass : public Pass { int proven_equiv_cells = 0; for (auto cell : module->selected_cells()) - if (cell->type == ID($equiv)) { - if (cell->getPort(ID::A) != cell->getPort(ID::B)) + if (cell->type == "$equiv") { + if (cell->getPort("\\A") != cell->getPort("\\B")) unproven_equiv_cells.push_back(cell); else proven_equiv_cells++; @@ -77,7 +77,7 @@ struct EquivStatusPass : public Pass { log(" Equivalence successfully proven!\n"); } else { for (auto cell : unproven_equiv_cells) - log(" Unproven $equiv %s: %s %s\n", log_id(cell), log_signal(cell->getPort(ID::A)), log_signal(cell->getPort(ID::B))); + log(" Unproven $equiv %s: %s %s\n", log_id(cell), log_signal(cell->getPort("\\A")), log_signal(cell->getPort("\\B"))); } unproven_count += GetSize(unproven_equiv_cells); diff --git a/passes/equiv/equiv_struct.cc b/passes/equiv/equiv_struct.cc index 9784225db20..6672948b92d 100644 --- a/passes/equiv/equiv_struct.cc +++ b/passes/equiv/equiv_struct.cc @@ -110,9 +110,9 @@ struct EquivStructWorker module->connect(sig_b, sig_a); } - auto merged_attr = cell_b->get_strpool_attribute(ID::equiv_merged); + auto merged_attr = cell_b->get_strpool_attribute("\\equiv_merged"); merged_attr.insert(log_id(cell_b)); - cell_a->add_strpool_attribute(ID::equiv_merged, merged_attr); + cell_a->add_strpool_attribute("\\equiv_merged", merged_attr); module->remove(cell_b); } @@ -126,9 +126,9 @@ struct EquivStructWorker pool cells; for (auto cell : module->selected_cells()) - if (cell->type == ID($equiv)) { - SigBit sig_a = sigmap(cell->getPort(ID::A).as_bit()); - SigBit sig_b = sigmap(cell->getPort(ID::B).as_bit()); + if (cell->type == "$equiv") { + SigBit sig_a = sigmap(cell->getPort("\\A").as_bit()); + SigBit sig_b = sigmap(cell->getPort("\\B").as_bit()); equiv_bits.add(sig_b, sig_a); equiv_inputs.insert(sig_a); equiv_inputs.insert(sig_b); @@ -139,10 +139,10 @@ struct EquivStructWorker } for (auto cell : module->selected_cells()) - if (cell->type == ID($equiv)) { - SigBit sig_a = sigmap(cell->getPort(ID::A).as_bit()); - SigBit sig_b = sigmap(cell->getPort(ID::B).as_bit()); - SigBit sig_y = sigmap(cell->getPort(ID::Y).as_bit()); + if (cell->type == "$equiv") { + SigBit sig_a = sigmap(cell->getPort("\\A").as_bit()); + SigBit sig_b = sigmap(cell->getPort("\\B").as_bit()); + SigBit sig_y = sigmap(cell->getPort("\\Y").as_bit()); if (sig_a == sig_b && equiv_inputs.count(sig_y)) { log(" Purging redundant $equiv cell %s.\n", log_id(cell)); module->connect(sig_y, sig_a); @@ -283,7 +283,7 @@ struct EquivStructWorker struct EquivStructPass : public Pass { EquivStructPass() : Pass("equiv_struct", "structural equivalence checking") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -314,9 +314,9 @@ struct EquivStructPass : public Pass { log(" maximum number of iterations to run before aborting\n"); log("\n"); } - void execute(std::vector args, Design *design) override + void execute(std::vector args, Design *design) YS_OVERRIDE { - pool fwonly_cells({ ID($equiv) }); + pool fwonly_cells({ "$equiv" }); bool mode_icells = false; bool mode_fwd = false; int max_iter = -1; diff --git a/passes/fsm/fsm.cc b/passes/fsm/fsm.cc index 21d352407f7..c5cb338ab05 100644 --- a/passes/fsm/fsm.cc +++ b/passes/fsm/fsm.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct FsmPass : public Pass { FsmPass() : Pass("fsm", "extract and optimize finite state machines") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -68,7 +68,7 @@ struct FsmPass : public Pass { log(" passed through to fsm_recode pass\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_nomap = false; bool flag_norecode = false; diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc index 97c575ba76e..fb389666973 100644 --- a/passes/fsm/fsm_detect.cc +++ b/passes/fsm/fsm_detect.cc @@ -34,20 +34,13 @@ static SigSet sig2driver, sig2user; static std::set muxtree_cells; static SigPool sig_at_port; -static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig, pool &recursion_monitor, dict &mux_tree_cache) +static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig, pool &recursion_monitor) { - if (mux_tree_cache.find(sig) != mux_tree_cache.end()) - return mux_tree_cache.at(sig); - if (sig.is_fully_const() || old_sig == sig) { -ret_true: - mux_tree_cache[sig] = true; return true; } if (sig_at_port.check_any(assign_map(sig))) { -ret_false: - mux_tree_cache[sig] = false; return false; } @@ -55,37 +48,37 @@ static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig, poo sig2driver.find(sig, cellport_list); for (auto &cellport : cellport_list) { - if ((cellport.first->type != ID($mux) && cellport.first->type != ID($pmux)) || cellport.second != ID::Y) { - goto ret_false; + if ((cellport.first->type != "$mux" && cellport.first->type != "$pmux") || cellport.second != "\\Y") { + return false; } if (recursion_monitor.count(cellport.first)) { log_warning("logic loop in mux tree at signal %s in module %s.\n", log_signal(sig), RTLIL::id2cstr(module->name)); - goto ret_false; + return false; } recursion_monitor.insert(cellport.first); - RTLIL::SigSpec sig_a = assign_map(cellport.first->getPort(ID::A)); - RTLIL::SigSpec sig_b = assign_map(cellport.first->getPort(ID::B)); + RTLIL::SigSpec sig_a = assign_map(cellport.first->getPort("\\A")); + RTLIL::SigSpec sig_b = assign_map(cellport.first->getPort("\\B")); - if (!check_state_mux_tree(old_sig, sig_a, recursion_monitor, mux_tree_cache)) { + if (!check_state_mux_tree(old_sig, sig_a, recursion_monitor)) { recursion_monitor.erase(cellport.first); - goto ret_false; + return false; } for (int i = 0; i < sig_b.size(); i += sig_a.size()) - if (!check_state_mux_tree(old_sig, sig_b.extract(i, sig_a.size()), recursion_monitor, mux_tree_cache)) { + if (!check_state_mux_tree(old_sig, sig_b.extract(i, sig_a.size()), recursion_monitor)) { recursion_monitor.erase(cellport.first); - goto ret_false; + return false; } recursion_monitor.erase(cellport.first); muxtree_cells.insert(cellport.first); } - goto ret_true; + return true; } static bool check_state_users(RTLIL::SigSpec sig) @@ -99,18 +92,18 @@ static bool check_state_users(RTLIL::SigSpec sig) RTLIL::Cell *cell = cellport.first; if (muxtree_cells.count(cell) > 0) continue; - if (cell->type == ID($logic_not) && assign_map(cell->getPort(ID::A)) == sig) + if (cell->type == "$logic_not" && assign_map(cell->getPort("\\A")) == sig) continue; - if (cellport.second != ID::A && cellport.second != ID::B) + if (cellport.second != "\\A" && cellport.second != "\\B") return false; - if (!cell->hasPort(ID::A) || !cell->hasPort(ID::B) || !cell->hasPort(ID::Y)) + if (!cell->hasPort("\\A") || !cell->hasPort("\\B") || !cell->hasPort("\\Y")) return false; for (auto &port_it : cell->connections()) - if (port_it.first != ID::A && port_it.first != ID::B && port_it.first != ID::Y) + if (port_it.first != "\\A" && port_it.first != "\\B" && port_it.first != "\\Y") return false; - if (assign_map(cell->getPort(ID::A)) == sig && cell->getPort(ID::B).is_fully_const()) + if (assign_map(cell->getPort("\\A")) == sig && cell->getPort("\\B").is_fully_const()) continue; - if (assign_map(cell->getPort(ID::B)) == sig && cell->getPort(ID::A).is_fully_const()) + if (assign_map(cell->getPort("\\B")) == sig && cell->getPort("\\A").is_fully_const()) continue; return false; } @@ -120,9 +113,9 @@ static bool check_state_users(RTLIL::SigSpec sig) static void detect_fsm(RTLIL::Wire *wire) { - bool has_fsm_encoding_attr = wire->attributes.count(ID::fsm_encoding) > 0 && wire->attributes.at(ID::fsm_encoding).decode_string() != "none"; - bool has_fsm_encoding_none = wire->attributes.count(ID::fsm_encoding) > 0 && wire->attributes.at(ID::fsm_encoding).decode_string() == "none"; - bool has_init_attr = wire->attributes.count(ID::init) > 0; + bool has_fsm_encoding_attr = wire->attributes.count("\\fsm_encoding") > 0 && wire->attributes.at("\\fsm_encoding").decode_string() != "none"; + bool has_fsm_encoding_none = wire->attributes.count("\\fsm_encoding") > 0 && wire->attributes.at("\\fsm_encoding").decode_string() == "none"; + bool has_init_attr = wire->attributes.count("\\init") > 0; bool is_module_port = sig_at_port.check_any(assign_map(RTLIL::SigSpec(wire))); bool looks_like_state_reg = false, looks_like_good_state_reg = false; bool is_self_resetting = false; @@ -133,7 +126,7 @@ static void detect_fsm(RTLIL::Wire *wire) if (wire->width <= 1) { if (has_fsm_encoding_attr) { log_warning("Removing fsm_encoding attribute from 1-bit net: %s.%s\n", log_id(wire->module), log_id(wire)); - wire->attributes.erase(ID::fsm_encoding); + wire->attributes.erase("\\fsm_encoding"); } return; } @@ -143,19 +136,18 @@ static void detect_fsm(RTLIL::Wire *wire) for (auto &cellport : cellport_list) { - if ((cellport.first->type != ID($dff) && cellport.first->type != ID($adff)) || cellport.second != ID::Q) + if ((cellport.first->type != "$dff" && cellport.first->type != "$adff") || cellport.second != "\\Q") continue; muxtree_cells.clear(); pool recursion_monitor; - RTLIL::SigSpec sig_q = assign_map(cellport.first->getPort(ID::Q)); - RTLIL::SigSpec sig_d = assign_map(cellport.first->getPort(ID::D)); - dict mux_tree_cache; + RTLIL::SigSpec sig_q = assign_map(cellport.first->getPort("\\Q")); + RTLIL::SigSpec sig_d = assign_map(cellport.first->getPort("\\D")); if (sig_q != assign_map(wire)) continue; - looks_like_state_reg = check_state_mux_tree(sig_q, sig_d, recursion_monitor, mux_tree_cache); + looks_like_state_reg = check_state_mux_tree(sig_q, sig_d, recursion_monitor); looks_like_good_state_reg = check_state_users(sig_q); if (!looks_like_state_reg) @@ -173,10 +165,10 @@ static void detect_fsm(RTLIL::Wire *wire) RTLIL::Cell *cell = cellport.first; bool set_output = false, clr_output = false; - if (cell->type.in(ID($ne), ID($reduce_or), ID($reduce_bool))) + if (cell->type.in("$ne", "$reduce_or", "$reduce_bool")) set_output = true; - if (cell->type.in(ID($eq), ID($logic_not), ID($reduce_and))) + if (cell->type.in("$eq", "$logic_not", "$reduce_and")) clr_output = true; if (set_output || clr_output) { @@ -234,7 +226,7 @@ static void detect_fsm(RTLIL::Wire *wire) if (looks_like_state_reg && looks_like_good_state_reg && !has_init_attr && !is_module_port && !is_self_resetting) { log("Found FSM state register %s.%s.\n", log_id(wire->module), log_id(wire)); - wire->attributes[ID::fsm_encoding] = RTLIL::Const("auto"); + wire->attributes["\\fsm_encoding"] = RTLIL::Const("auto"); } else if (looks_like_state_reg) @@ -257,7 +249,7 @@ static void detect_fsm(RTLIL::Wire *wire) struct FsmDetectPass : public Pass { FsmDetectPass() : Pass("fsm_detect", "finding FSMs in design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -273,7 +265,7 @@ struct FsmDetectPass : public Pass { log("'fsm_encoding' attribute to \"none\".\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing FSM_DETECT pass (finding FSMs in design).\n"); extra_args(args, 1, design); @@ -284,34 +276,38 @@ struct FsmDetectPass : public Pass { ct.setup_stdcells(); ct.setup_stdcells_mem(); - for (auto mod : design->selected_modules()) + for (auto &mod_it : design->modules_) { - module = mod; + if (!design->selected(mod_it.second)) + continue; + + module = mod_it.second; assign_map.set(module); sig2driver.clear(); sig2user.clear(); sig_at_port.clear(); - for (auto cell : module->cells()) - for (auto &conn_it : cell->connections()) { - if (ct.cell_output(cell->type, conn_it.first) || !ct.cell_known(cell->type)) { + for (auto &cell_it : module->cells_) + for (auto &conn_it : cell_it.second->connections()) { + if (ct.cell_output(cell_it.second->type, conn_it.first) || !ct.cell_known(cell_it.second->type)) { RTLIL::SigSpec sig = conn_it.second; assign_map.apply(sig); - sig2driver.insert(sig, sig2driver_entry_t(cell, conn_it.first)); + sig2driver.insert(sig, sig2driver_entry_t(cell_it.second, conn_it.first)); } - if (!ct.cell_known(cell->type) || ct.cell_input(cell->type, conn_it.first)) { + if (!ct.cell_known(cell_it.second->type) || ct.cell_input(cell_it.second->type, conn_it.first)) { RTLIL::SigSpec sig = conn_it.second; assign_map.apply(sig); - sig2user.insert(sig, sig2driver_entry_t(cell, conn_it.first)); + sig2user.insert(sig, sig2driver_entry_t(cell_it.second, conn_it.first)); } } - for (auto wire : module->wires()) - if (wire->port_id != 0) - sig_at_port.add(assign_map(wire)); + for (auto &wire_it : module->wires_) + if (wire_it.second->port_id != 0) + sig_at_port.add(assign_map(RTLIL::SigSpec(wire_it.second))); - for (auto wire : module->selected_wires()) - detect_fsm(wire); + for (auto &wire_it : module->wires_) + if (design->selected(module, wire_it.second)) + detect_fsm(wire_it.second); } assign_map.clear(); diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc index d6b492af542..1610ec751f5 100644 --- a/passes/fsm/fsm_expand.cc +++ b/passes/fsm/fsm_expand.cc @@ -47,42 +47,42 @@ struct FsmExpand bool is_cell_merge_candidate(RTLIL::Cell *cell) { - if (full_mode || cell->type == ID($_MUX_)) + if (full_mode || cell->type == "$_MUX_") return true; - if (cell->type.in(ID($mux), ID($pmux))) - if (cell->getPort(ID::A).size() < 2) + if (cell->type.in("$mux", "$pmux")) + if (cell->getPort("\\A").size() < 2) return true; int in_bits = 0; RTLIL::SigSpec new_signals; - if (cell->hasPort(ID::A)) { - in_bits += GetSize(cell->getPort(ID::A)); - new_signals.append(assign_map(cell->getPort(ID::A))); + if (cell->hasPort("\\A")) { + in_bits += GetSize(cell->getPort("\\A")); + new_signals.append(assign_map(cell->getPort("\\A"))); } - if (cell->hasPort(ID::B)) { - in_bits += GetSize(cell->getPort(ID::B)); - new_signals.append(assign_map(cell->getPort(ID::B))); + if (cell->hasPort("\\B")) { + in_bits += GetSize(cell->getPort("\\B")); + new_signals.append(assign_map(cell->getPort("\\B"))); } - if (cell->hasPort(ID::S)) { - in_bits += GetSize(cell->getPort(ID::S)); - new_signals.append(assign_map(cell->getPort(ID::S))); + if (cell->hasPort("\\S")) { + in_bits += GetSize(cell->getPort("\\S")); + new_signals.append(assign_map(cell->getPort("\\S"))); } if (in_bits > 8) return false; - if (cell->hasPort(ID::Y)) - new_signals.append(assign_map(cell->getPort(ID::Y))); + if (cell->hasPort("\\Y")) + new_signals.append(assign_map(cell->getPort("\\Y"))); new_signals.sort_and_unify(); new_signals.remove_const(); - new_signals.remove(assign_map(fsm_cell->getPort(ID::CTRL_IN))); - new_signals.remove(assign_map(fsm_cell->getPort(ID::CTRL_OUT))); + new_signals.remove(assign_map(fsm_cell->getPort("\\CTRL_IN"))); + new_signals.remove(assign_map(fsm_cell->getPort("\\CTRL_OUT"))); if (new_signals.size() > 3) return false; @@ -94,10 +94,10 @@ struct FsmExpand { std::vector cell_list; - for (auto c : sig2driver.find(assign_map(fsm_cell->getPort(ID::CTRL_IN)))) + for (auto c : sig2driver.find(assign_map(fsm_cell->getPort("\\CTRL_IN")))) cell_list.push_back(c); - for (auto c : sig2user.find(assign_map(fsm_cell->getPort(ID::CTRL_OUT)))) + for (auto c : sig2user.find(assign_map(fsm_cell->getPort("\\CTRL_OUT")))) cell_list.push_back(c); current_set.clear(); @@ -106,7 +106,7 @@ struct FsmExpand if (merged_set.count(c) > 0 || current_set.count(c) > 0 || no_candidate_set.count(c) > 0) continue; for (auto &p : c->connections()) { - if (p.first != ID::A && p.first != ID::B && p.first != ID::S && p.first != ID::Y) + if (p.first != "\\A" && p.first != "\\B" && p.first != "\\S" && p.first != "\\Y") goto next_cell; } if (!is_cell_merge_candidate(c)) { @@ -123,14 +123,14 @@ struct FsmExpand if (already_optimized) return; - int trans_num = fsm_cell->parameters[ID::TRANS_NUM].as_int(); + int trans_num = fsm_cell->parameters["\\TRANS_NUM"].as_int(); if (trans_num > limit_transitions) { log(" grown transition table to %d entries -> optimize.\n", trans_num); FsmData::optimize_fsm(fsm_cell, module); already_optimized = true; - trans_num = fsm_cell->parameters[ID::TRANS_NUM].as_int(); + trans_num = fsm_cell->parameters["\\TRANS_NUM"].as_int(); log(" transition table size after optimizaton: %d\n", trans_num); limit_transitions = 16 * trans_num; } @@ -159,12 +159,12 @@ struct FsmExpand for (int i = 0; i < (1 << input_sig.size()); i++) { RTLIL::Const in_val(i, input_sig.size()); RTLIL::SigSpec A, B, S; - if (cell->hasPort(ID::A)) - A = assign_map(cell->getPort(ID::A)); - if (cell->hasPort(ID::B)) - B = assign_map(cell->getPort(ID::B)); - if (cell->hasPort(ID::S)) - S = assign_map(cell->getPort(ID::S)); + if (cell->hasPort("\\A")) + A = assign_map(cell->getPort("\\A")); + if (cell->hasPort("\\B")) + B = assign_map(cell->getPort("\\B")); + if (cell->hasPort("\\S")) + S = assign_map(cell->getPort("\\S")); A.replace(input_sig, RTLIL::SigSpec(in_val)); B.replace(input_sig, RTLIL::SigSpec(in_val)); S.replace(input_sig, RTLIL::SigSpec(in_val)); @@ -178,14 +178,14 @@ struct FsmExpand fsm_data.copy_from_cell(fsm_cell); fsm_data.num_inputs += input_sig.size(); - RTLIL::SigSpec new_ctrl_in = fsm_cell->getPort(ID::CTRL_IN); + RTLIL::SigSpec new_ctrl_in = fsm_cell->getPort("\\CTRL_IN"); new_ctrl_in.append(input_sig); - fsm_cell->setPort(ID::CTRL_IN, new_ctrl_in); + fsm_cell->setPort("\\CTRL_IN", new_ctrl_in); fsm_data.num_outputs += output_sig.size(); - RTLIL::SigSpec new_ctrl_out = fsm_cell->getPort(ID::CTRL_OUT); + RTLIL::SigSpec new_ctrl_out = fsm_cell->getPort("\\CTRL_OUT"); new_ctrl_out.append(output_sig); - fsm_cell->setPort(ID::CTRL_OUT, new_ctrl_out); + fsm_cell->setPort("\\CTRL_OUT", new_ctrl_out); if (GetSize(input_sig) > 10) log_warning("Cell %s.%s (%s) has %d input bits, merging into FSM %s.%s might be problematic.\n", @@ -246,7 +246,7 @@ struct FsmExpand log("Expanding FSM `%s' from module `%s':\n", fsm_cell->name.c_str(), module->name.c_str()); already_optimized = false; - limit_transitions = 16 * fsm_cell->parameters[ID::TRANS_NUM].as_int(); + limit_transitions = 16 * fsm_cell->parameters["\\TRANS_NUM"].as_int(); for (create_current_set(); current_set.size() > 0; create_current_set()) { for (auto c : current_set) @@ -265,7 +265,7 @@ struct FsmExpand struct FsmExpandPass : public Pass { FsmExpandPass() : Pass("fsm_expand", "expand FSM cells by merging logic into it") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -279,7 +279,7 @@ struct FsmExpandPass : public Pass { log("word-wide cells. Call with -full to consider all cells for merging.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool full_mode = false; @@ -295,13 +295,15 @@ struct FsmExpandPass : public Pass { } extra_args(args, argidx, design); - for (auto mod : design->selected_modules()) { + for (auto &mod_it : design->modules_) { + if (!design->selected(mod_it.second)) + continue; std::vector fsm_cells; - for (auto cell : mod->selected_cells()) - if (cell->type == ID($fsm)) - fsm_cells.push_back(cell); + for (auto &cell_it : mod_it.second->cells_) + if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second)) + fsm_cells.push_back(cell_it.second); for (auto c : fsm_cells) { - FsmExpand fsm_expand(c, design, mod, full_mode); + FsmExpand fsm_expand(c, design, mod_it.second, full_mode); fsm_expand.execute(); } } diff --git a/passes/fsm/fsm_export.cc b/passes/fsm/fsm_export.cc index be6702d7e13..8eb1872f0d0 100644 --- a/passes/fsm/fsm_export.cc +++ b/passes/fsm/fsm_export.cc @@ -57,7 +57,7 @@ void write_kiss2(struct RTLIL::Module *module, struct RTLIL::Cell *cell, std::st std::string kiss_name; size_t i; - attr_it = cell->attributes.find(ID::fsm_export); + attr_it = cell->attributes.find("\\fsm_export"); if (!filename.empty()) { kiss_name.assign(filename); } else if (attr_it != cell->attributes.end() && attr_it->second.decode_string() != "") { @@ -120,7 +120,7 @@ void write_kiss2(struct RTLIL::Module *module, struct RTLIL::Cell *cell, std::st */ struct FsmExportPass : public Pass { FsmExportPass() : Pass("fsm_export", "exporting FSMs to KISS2 files") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -143,7 +143,7 @@ struct FsmExportPass : public Pass { log(" use binary state encoding as state names instead of s0, s1, ...\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { dict::iterator attr_it; std::string arg; @@ -173,15 +173,16 @@ struct FsmExportPass : public Pass { } extra_args(args, argidx, design); - for (auto mod : design->selected_modules()) - for (auto cell : mod->selected_cells()) - if (cell->type == ID($fsm)) { - attr_it = cell->attributes.find(ID::fsm_export); - if (!flag_noauto || (attr_it != cell->attributes.end())) { - write_kiss2(mod, cell, filename, flag_origenc); - filename.clear(); + for (auto &mod_it : design->modules_) + if (design->selected(mod_it.second)) + for (auto &cell_it : mod_it.second->cells_) + if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second)) { + attr_it = cell_it.second->attributes.find("\\fsm_export"); + if (!flag_noauto || (attr_it != cell_it.second->attributes.end())) { + write_kiss2(mod_it.second, cell_it.second, filename, flag_origenc); + filename.clear(); + } } - } } } FsmExportPass; diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc index 082973153fa..a85c3bec066 100644 --- a/passes/fsm/fsm_extract.cc +++ b/passes/fsm/fsm_extract.cc @@ -70,15 +70,15 @@ static bool find_states(RTLIL::SigSpec sig, const RTLIL::SigSpec &dff_out, RTLIL for (auto &cellport : cellport_list) { RTLIL::Cell *cell = module->cells_.at(cellport.first); - if ((cell->type != ID($mux) && cell->type != ID($pmux)) || cellport.second != ID::Y) { + if ((cell->type != "$mux" && cell->type != "$pmux") || cellport.second != "\\Y") { log(" unexpected cell type %s (%s) found in state selection tree.\n", cell->type.c_str(), cell->name.c_str()); return false; } - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); - RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); - RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S)); - RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y)); + RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); + RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec sig_s = assign_map(cell->getPort("\\S")); + RTLIL::SigSpec sig_y = assign_map(cell->getPort("\\Y")); RTLIL::SigSpec sig_aa = sig; sig_aa.replace(sig_y, sig_a); @@ -272,17 +272,17 @@ static void extract_fsm(RTLIL::Wire *wire) sig2driver.find(dff_out, cellport_list); for (auto &cellport : cellport_list) { RTLIL::Cell *cell = module->cells_.at(cellport.first); - if ((cell->type != ID($dff) && cell->type != ID($adff)) || cellport.second != ID::Q) + if ((cell->type != "$dff" && cell->type != "$adff") || cellport.second != "\\Q") continue; log(" found %s cell for state register: %s\n", cell->type.c_str(), cell->name.c_str()); - RTLIL::SigSpec sig_q = assign_map(cell->getPort(ID::Q)); - RTLIL::SigSpec sig_d = assign_map(cell->getPort(ID::D)); - clk = cell->getPort(ID::CLK); - clk_polarity = cell->parameters[ID::CLK_POLARITY].as_bool(); - if (cell->type == ID($adff)) { - arst = cell->getPort(ID::ARST); - arst_polarity = cell->parameters[ID::ARST_POLARITY].as_bool(); - reset_state = cell->parameters[ID::ARST_VALUE]; + RTLIL::SigSpec sig_q = assign_map(cell->getPort("\\Q")); + RTLIL::SigSpec sig_d = assign_map(cell->getPort("\\D")); + clk = cell->getPort("\\CLK"); + clk_polarity = cell->parameters["\\CLK_POLARITY"].as_bool(); + if (cell->type == "$adff") { + arst = cell->getPort("\\ARST"); + arst_polarity = cell->parameters["\\ARST_POLARITY"].as_bool(); + reset_state = cell->parameters["\\ARST_VALUE"]; } sig_q.replace(dff_out, sig_d, &dff_in); break; @@ -320,14 +320,14 @@ static void extract_fsm(RTLIL::Wire *wire) sig2trigger.find(dff_out, cellport_list); for (auto &cellport : cellport_list) { RTLIL::Cell *cell = module->cells_.at(cellport.first); - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); RTLIL::SigSpec sig_b; - if (cell->hasPort(ID::B)) - sig_b = assign_map(cell->getPort(ID::B)); - RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y)); - if (cellport.second == ID::A && !sig_b.is_fully_const()) + if (cell->hasPort("\\B")) + sig_b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec sig_y = assign_map(cell->getPort("\\Y")); + if (cellport.second == "\\A" && !sig_b.is_fully_const()) continue; - if (cellport.second == ID::B && !sig_a.is_fully_const()) + if (cellport.second == "\\B" && !sig_a.is_fully_const()) continue; log(" found ctrl output: %s\n", log_signal(sig_y)); ctrl_out.append(sig_y); @@ -368,21 +368,21 @@ static void extract_fsm(RTLIL::Wire *wire) // create fsm cell - RTLIL::Cell *fsm_cell = module->addCell(stringf("$fsm$%s$%d", wire->name.c_str(), autoidx++), ID($fsm)); - fsm_cell->setPort(ID::CLK, clk); - fsm_cell->setPort(ID::ARST, arst); - fsm_cell->parameters[ID::CLK_POLARITY] = clk_polarity ? State::S1 : State::S0; - fsm_cell->parameters[ID::ARST_POLARITY] = arst_polarity ? State::S1 : State::S0; - fsm_cell->setPort(ID::CTRL_IN, ctrl_in); - fsm_cell->setPort(ID::CTRL_OUT, ctrl_out); - fsm_cell->parameters[ID::NAME] = RTLIL::Const(wire->name.str()); + RTLIL::Cell *fsm_cell = module->addCell(stringf("$fsm$%s$%d", wire->name.c_str(), autoidx++), "$fsm"); + fsm_cell->setPort("\\CLK", clk); + fsm_cell->setPort("\\ARST", arst); + fsm_cell->parameters["\\CLK_POLARITY"] = clk_polarity ? State::S1 : State::S0; + fsm_cell->parameters["\\ARST_POLARITY"] = arst_polarity ? State::S1 : State::S0; + fsm_cell->setPort("\\CTRL_IN", ctrl_in); + fsm_cell->setPort("\\CTRL_OUT", ctrl_out); + fsm_cell->parameters["\\NAME"] = RTLIL::Const(wire->name.str()); fsm_cell->attributes = wire->attributes; fsm_data.copy_to_cell(fsm_cell); // rename original state wire module->wires_.erase(wire->name); - wire->attributes.erase(ID::fsm_encoding); + wire->attributes.erase("\\fsm_encoding"); wire->name = stringf("$fsm$oldstate%s", wire->name.c_str()); module->wires_[wire->name] = wire; @@ -394,14 +394,14 @@ static void extract_fsm(RTLIL::Wire *wire) RTLIL::Cell *cell = module->cells_.at(cellport.first); RTLIL::SigSpec port_sig = assign_map(cell->getPort(cellport.second)); RTLIL::SigSpec unconn_sig = port_sig.extract(ctrl_out); - RTLIL::Wire *unconn_wire = module->addWire(stringf("$fsm_unconnect$%d", autoidx++), unconn_sig.size()); + RTLIL::Wire *unconn_wire = module->addWire(stringf("$fsm_unconnect$%s$%d", log_signal(unconn_sig), autoidx++), unconn_sig.size()); port_sig.replace(unconn_sig, RTLIL::SigSpec(unconn_wire), &cell->connections_[cellport.second]); } } struct FsmExtractPass : public Pass { FsmExtractPass() : Pass("fsm_extract", "extracting FSMs in design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -417,16 +417,23 @@ struct FsmExtractPass : public Pass { log("'opt_clean' pass to eliminate this signal.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing FSM_EXTRACT pass (extracting FSM from design).\n"); extra_args(args, 1, design); - CellTypes ct(design); + CellTypes ct; + ct.setup_internals(); + ct.setup_internals_mem(); + ct.setup_stdcells(); + ct.setup_stdcells_mem(); - for (auto mod : design->selected_modules()) + for (auto &mod_it : design->modules_) { - module = mod; + if (!design->selected(mod_it.second)) + continue; + + module = mod_it.second; assign_map.set(module); sig2driver.clear(); @@ -439,15 +446,15 @@ struct FsmExtractPass : public Pass { assign_map.apply(sig); sig2driver.insert(sig, sig2driver_entry_t(cell->name, conn_it.first)); } - if (ct.cell_input(cell->type, conn_it.first) && cell->hasPort(ID::Y) && - cell->getPort(ID::Y).size() == 1 && (conn_it.first == ID::A || conn_it.first == ID::B)) { + if (ct.cell_input(cell->type, conn_it.first) && cell->hasPort("\\Y") && + cell->getPort("\\Y").size() == 1 && (conn_it.first == "\\A" || conn_it.first == "\\B")) { RTLIL::SigSpec sig = conn_it.second; assign_map.apply(sig); sig2trigger.insert(sig, sig2driver_entry_t(cell->name, conn_it.first)); } } - if (cell->type == ID($pmux)) { - RTLIL::SigSpec sel_sig = assign_map(cell->getPort(ID::S)); + if (cell->type == "$pmux") { + RTLIL::SigSpec sel_sig = assign_map(cell->getPort("\\S")); for (auto &bit1 : sel_sig) for (auto &bit2 : sel_sig) if (bit1 != bit2) @@ -456,9 +463,10 @@ struct FsmExtractPass : public Pass { } std::vector wire_list; - for (auto wire : module->selected_wires()) - if (wire->attributes.count(ID::fsm_encoding) > 0 && wire->attributes[ID::fsm_encoding].decode_string() != "none") - wire_list.push_back(wire); + for (auto &wire_it : module->wires_) + if (wire_it.second->attributes.count("\\fsm_encoding") > 0 && wire_it.second->attributes["\\fsm_encoding"].decode_string() != "none") + if (design->selected(module, wire_it.second)) + wire_list.push_back(wire_it.second); for (auto wire : wire_list) extract_fsm(wire); } diff --git a/passes/fsm/fsm_info.cc b/passes/fsm/fsm_info.cc index da0982bb9e3..0548259ee0f 100644 --- a/passes/fsm/fsm_info.cc +++ b/passes/fsm/fsm_info.cc @@ -30,7 +30,7 @@ PRIVATE_NAMESPACE_BEGIN struct FsmInfoPass : public Pass { FsmInfoPass() : Pass("fsm_info", "print information on finite state machines") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -41,20 +41,21 @@ struct FsmInfoPass : public Pass { log("pass so that this information is included in the synthesis log file.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing FSM_INFO pass (dumping all available information on FSM cells).\n"); extra_args(args, 1, design); - for (auto mod : design->selected_modules()) - for (auto cell : mod->selected_cells()) - if (cell->type == ID($fsm)) { - log("\n"); - log("FSM `%s' from module `%s':\n", log_id(cell), log_id(mod)); - FsmData fsm_data; - fsm_data.copy_from_cell(cell); - fsm_data.log_info(cell); - } + for (auto &mod_it : design->modules_) + if (design->selected(mod_it.second)) + for (auto &cell_it : mod_it.second->cells_) + if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second)) { + log("\n"); + log("FSM `%s' from module `%s':\n", cell_it.second->name.c_str(), mod_it.first.c_str()); + FsmData fsm_data; + fsm_data.copy_from_cell(cell_it.second); + fsm_data.log_info(cell_it.second); + } } } FsmInfoPass; diff --git a/passes/fsm/fsm_map.cc b/passes/fsm/fsm_map.cc index a30d407f071..80913fda8ab 100644 --- a/passes/fsm/fsm_map.cc +++ b/passes/fsm/fsm_map.cc @@ -74,15 +74,15 @@ static void implement_pattern_cache(RTLIL::Module *module, std::mapaddWire(NEW_ID); and_sig.append(RTLIL::SigSpec(eq_wire)); - RTLIL::Cell *eq_cell = module->addCell(NEW_ID, ID($eq)); - eq_cell->setPort(ID::A, eq_sig_a); - eq_cell->setPort(ID::B, eq_sig_b); - eq_cell->setPort(ID::Y, RTLIL::SigSpec(eq_wire)); - eq_cell->parameters[ID::A_SIGNED] = RTLIL::Const(false); - eq_cell->parameters[ID::B_SIGNED] = RTLIL::Const(false); - eq_cell->parameters[ID::A_WIDTH] = RTLIL::Const(eq_sig_a.size()); - eq_cell->parameters[ID::B_WIDTH] = RTLIL::Const(eq_sig_b.size()); - eq_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); + RTLIL::Cell *eq_cell = module->addCell(NEW_ID, "$eq"); + eq_cell->setPort("\\A", eq_sig_a); + eq_cell->setPort("\\B", eq_sig_b); + eq_cell->setPort("\\Y", RTLIL::SigSpec(eq_wire)); + eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false); + eq_cell->parameters["\\B_SIGNED"] = RTLIL::Const(false); + eq_cell->parameters["\\A_WIDTH"] = RTLIL::Const(eq_sig_a.size()); + eq_cell->parameters["\\B_WIDTH"] = RTLIL::Const(eq_sig_b.size()); + eq_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); } std::set complete_in_state_cache = it.second; @@ -102,12 +102,12 @@ static void implement_pattern_cache(RTLIL::Module *module, std::mapaddWire(NEW_ID); and_sig.append(RTLIL::SigSpec(or_wire)); - RTLIL::Cell *or_cell = module->addCell(NEW_ID, ID($reduce_or)); - or_cell->setPort(ID::A, or_sig); - or_cell->setPort(ID::Y, RTLIL::SigSpec(or_wire)); - or_cell->parameters[ID::A_SIGNED] = RTLIL::Const(false); - or_cell->parameters[ID::A_WIDTH] = RTLIL::Const(or_sig.size()); - or_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); + RTLIL::Cell *or_cell = module->addCell(NEW_ID, "$reduce_or"); + or_cell->setPort("\\A", or_sig); + or_cell->setPort("\\Y", RTLIL::SigSpec(or_wire)); + or_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false); + or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(or_sig.size()); + or_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); } } @@ -118,15 +118,15 @@ static void implement_pattern_cache(RTLIL::Module *module, std::mapaddWire(NEW_ID); cases_vector.append(RTLIL::SigSpec(and_wire)); - RTLIL::Cell *and_cell = module->addCell(NEW_ID, ID($and)); - and_cell->setPort(ID::A, and_sig.extract(0, 1)); - and_cell->setPort(ID::B, and_sig.extract(1, 1)); - and_cell->setPort(ID::Y, RTLIL::SigSpec(and_wire)); - and_cell->parameters[ID::A_SIGNED] = RTLIL::Const(false); - and_cell->parameters[ID::B_SIGNED] = RTLIL::Const(false); - and_cell->parameters[ID::A_WIDTH] = RTLIL::Const(1); - and_cell->parameters[ID::B_WIDTH] = RTLIL::Const(1); - and_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$and"); + and_cell->setPort("\\A", and_sig.extract(0, 1)); + and_cell->setPort("\\B", and_sig.extract(1, 1)); + and_cell->setPort("\\Y", RTLIL::SigSpec(and_wire)); + and_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false); + and_cell->parameters["\\B_SIGNED"] = RTLIL::Const(false); + and_cell->parameters["\\A_WIDTH"] = RTLIL::Const(1); + and_cell->parameters["\\B_WIDTH"] = RTLIL::Const(1); + and_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); break; } case 1: @@ -141,12 +141,12 @@ static void implement_pattern_cache(RTLIL::Module *module, std::map 1) { - RTLIL::Cell *or_cell = module->addCell(NEW_ID, ID($reduce_or)); - or_cell->setPort(ID::A, cases_vector); - or_cell->setPort(ID::Y, output); - or_cell->parameters[ID::A_SIGNED] = RTLIL::Const(false); - or_cell->parameters[ID::A_WIDTH] = RTLIL::Const(cases_vector.size()); - or_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); + RTLIL::Cell *or_cell = module->addCell(NEW_ID, "$reduce_or"); + or_cell->setPort("\\A", cases_vector); + or_cell->setPort("\\Y", output); + or_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false); + or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(cases_vector.size()); + or_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); } else if (cases_vector.size() == 1) { module->connect(RTLIL::SigSig(output, cases_vector)); } else { @@ -161,31 +161,31 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module) FsmData fsm_data; fsm_data.copy_from_cell(fsm_cell); - RTLIL::SigSpec ctrl_in = fsm_cell->getPort(ID::CTRL_IN); - RTLIL::SigSpec ctrl_out = fsm_cell->getPort(ID::CTRL_OUT); + RTLIL::SigSpec ctrl_in = fsm_cell->getPort("\\CTRL_IN"); + RTLIL::SigSpec ctrl_out = fsm_cell->getPort("\\CTRL_OUT"); // create state register - RTLIL::Wire *state_wire = module->addWire(module->uniquify(fsm_cell->parameters[ID::NAME].decode_string()), fsm_data.state_bits); + RTLIL::Wire *state_wire = module->addWire(module->uniquify(fsm_cell->parameters["\\NAME"].decode_string()), fsm_data.state_bits); RTLIL::Wire *next_state_wire = module->addWire(NEW_ID, fsm_data.state_bits); RTLIL::Cell *state_dff = module->addCell(NEW_ID, ""); - if (fsm_cell->getPort(ID::ARST).is_fully_const()) { - state_dff->type = ID($dff); + if (fsm_cell->getPort("\\ARST").is_fully_const()) { + state_dff->type = "$dff"; } else { - state_dff->type = ID($adff); - state_dff->parameters[ID::ARST_POLARITY] = fsm_cell->parameters[ID::ARST_POLARITY]; - state_dff->parameters[ID::ARST_VALUE] = fsm_data.state_table[fsm_data.reset_state]; - for (auto &bit : state_dff->parameters[ID::ARST_VALUE].bits) + state_dff->type = "$adff"; + state_dff->parameters["\\ARST_POLARITY"] = fsm_cell->parameters["\\ARST_POLARITY"]; + state_dff->parameters["\\ARST_VALUE"] = fsm_data.state_table[fsm_data.reset_state]; + for (auto &bit : state_dff->parameters["\\ARST_VALUE"].bits) if (bit != RTLIL::State::S1) bit = RTLIL::State::S0; - state_dff->setPort(ID::ARST, fsm_cell->getPort(ID::ARST)); + state_dff->setPort("\\ARST", fsm_cell->getPort("\\ARST")); } - state_dff->parameters[ID::WIDTH] = RTLIL::Const(fsm_data.state_bits); - state_dff->parameters[ID::CLK_POLARITY] = fsm_cell->parameters[ID::CLK_POLARITY]; - state_dff->setPort(ID::CLK, fsm_cell->getPort(ID::CLK)); - state_dff->setPort(ID::D, RTLIL::SigSpec(next_state_wire)); - state_dff->setPort(ID::Q, RTLIL::SigSpec(state_wire)); + state_dff->parameters["\\WIDTH"] = RTLIL::Const(fsm_data.state_bits); + state_dff->parameters["\\CLK_POLARITY"] = fsm_cell->parameters["\\CLK_POLARITY"]; + state_dff->setPort("\\CLK", fsm_cell->getPort("\\CLK")); + state_dff->setPort("\\D", RTLIL::SigSpec(next_state_wire)); + state_dff->setPort("\\Q", RTLIL::SigSpec(state_wire)); // decode state register @@ -212,20 +212,20 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module) { encoding_is_onehot = false; - RTLIL::Cell *eq_cell = module->addCell(NEW_ID, ID($eq)); - eq_cell->setPort(ID::A, sig_a); - eq_cell->setPort(ID::B, sig_b); - eq_cell->setPort(ID::Y, RTLIL::SigSpec(state_onehot, i)); - eq_cell->parameters[ID::A_SIGNED] = RTLIL::Const(false); - eq_cell->parameters[ID::B_SIGNED] = RTLIL::Const(false); - eq_cell->parameters[ID::A_WIDTH] = RTLIL::Const(sig_a.size()); - eq_cell->parameters[ID::B_WIDTH] = RTLIL::Const(sig_b.size()); - eq_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); + RTLIL::Cell *eq_cell = module->addCell(NEW_ID, "$eq"); + eq_cell->setPort("\\A", sig_a); + eq_cell->setPort("\\B", sig_b); + eq_cell->setPort("\\Y", RTLIL::SigSpec(state_onehot, i)); + eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false); + eq_cell->parameters["\\B_SIGNED"] = RTLIL::Const(false); + eq_cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig_a.size()); + eq_cell->parameters["\\B_WIDTH"] = RTLIL::Const(sig_b.size()); + eq_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); } } if (encoding_is_onehot) - state_wire->set_bool_attribute(ID::onehot); + state_wire->set_bool_attribute("\\onehot"); // generate next_state signal @@ -285,13 +285,13 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module) } } - RTLIL::Cell *mux_cell = module->addCell(NEW_ID, ID($pmux)); - mux_cell->setPort(ID::A, sig_a); - mux_cell->setPort(ID::B, sig_b); - mux_cell->setPort(ID::S, sig_s); - mux_cell->setPort(ID::Y, RTLIL::SigSpec(next_state_wire)); - mux_cell->parameters[ID::WIDTH] = RTLIL::Const(sig_a.size()); - mux_cell->parameters[ID::S_WIDTH] = RTLIL::Const(sig_s.size()); + RTLIL::Cell *mux_cell = module->addCell(NEW_ID, "$pmux"); + mux_cell->setPort("\\A", sig_a); + mux_cell->setPort("\\B", sig_b); + mux_cell->setPort("\\S", sig_s); + mux_cell->setPort("\\Y", RTLIL::SigSpec(next_state_wire)); + mux_cell->parameters["\\WIDTH"] = RTLIL::Const(sig_a.size()); + mux_cell->parameters["\\S_WIDTH"] = RTLIL::Const(sig_s.size()); } } @@ -322,7 +322,7 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module) struct FsmMapPass : public Pass { FsmMapPass() : Pass("fsm_map", "mapping FSMs to basic logic") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -331,18 +331,20 @@ struct FsmMapPass : public Pass { log("This pass translates FSM cells to flip-flops and logic.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing FSM_MAP pass (mapping FSMs to basic logic).\n"); extra_args(args, 1, design); - for (auto mod : design->selected_modules()) { + for (auto &mod_it : design->modules_) { + if (!design->selected(mod_it.second)) + continue; std::vector fsm_cells; - for (auto cell : mod->selected_cells()) - if (cell->type == ID($fsm)) - fsm_cells.push_back(cell); + for (auto &cell_it : mod_it.second->cells_) + if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second)) + fsm_cells.push_back(cell_it.second); for (auto cell : fsm_cells) - map_fsm(cell, mod); + map_fsm(cell, mod_it.second); } } } FsmMapPass; diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc index 5fc1fb3bb25..048daee55f5 100644 --- a/passes/fsm/fsm_opt.cc +++ b/passes/fsm/fsm_opt.cc @@ -81,10 +81,10 @@ struct FsmOpt { RTLIL::SigBit bit = sig.as_bit(); - if (bit.wire == NULL || bit.wire->attributes.count(ID::unused_bits) == 0) + if (bit.wire == NULL || bit.wire->attributes.count("\\unused_bits") == 0) return false; - char *str = strdup(bit.wire->attributes[ID::unused_bits].decode_string().c_str()); + char *str = strdup(bit.wire->attributes["\\unused_bits"].decode_string().c_str()); for (char *tok = strtok(str, " "); tok != NULL; tok = strtok(NULL, " ")) { if (tok[0] && bit.offset == atoi(tok)) { free(str); @@ -98,7 +98,7 @@ struct FsmOpt void opt_const_and_unused_inputs() { - RTLIL::SigSpec ctrl_in = cell->getPort(ID::CTRL_IN); + RTLIL::SigSpec ctrl_in = cell->getPort("\\CTRL_IN"); std::vector ctrl_in_used(ctrl_in.size()); std::vector new_transition_table; @@ -119,15 +119,15 @@ struct FsmOpt for (int i = int(ctrl_in_used.size())-1; i >= 0; i--) { if (!ctrl_in_used[i]) { - log(" Removing unused input signal %s.\n", log_signal(cell->getPort(ID::CTRL_IN).extract(i, 1))); + log(" Removing unused input signal %s.\n", log_signal(cell->getPort("\\CTRL_IN").extract(i, 1))); for (auto &tr : new_transition_table) { RTLIL::SigSpec tmp(tr.ctrl_in); tmp.remove(i, 1); tr.ctrl_in = tmp.as_const(); } - RTLIL::SigSpec new_ctrl_in = cell->getPort(ID::CTRL_IN); + RTLIL::SigSpec new_ctrl_in = cell->getPort("\\CTRL_IN"); new_ctrl_in.remove(i, 1); - cell->setPort(ID::CTRL_IN, new_ctrl_in); + cell->setPort("\\CTRL_IN", new_ctrl_in); fsm_data.num_inputs--; } } @@ -139,12 +139,12 @@ struct FsmOpt void opt_unused_outputs() { for (int i = 0; i < fsm_data.num_outputs; i++) { - RTLIL::SigSpec sig = cell->getPort(ID::CTRL_OUT).extract(i, 1); + RTLIL::SigSpec sig = cell->getPort("\\CTRL_OUT").extract(i, 1); if (signal_is_unused(sig)) { log(" Removing unused output signal %s.\n", log_signal(sig)); - RTLIL::SigSpec new_ctrl_out = cell->getPort(ID::CTRL_OUT); + RTLIL::SigSpec new_ctrl_out = cell->getPort("\\CTRL_OUT"); new_ctrl_out.remove(i, 1); - cell->setPort(ID::CTRL_OUT, new_ctrl_out); + cell->setPort("\\CTRL_OUT", new_ctrl_out); for (auto &tr : fsm_data.transition_table) { RTLIL::SigSpec tmp(tr.ctrl_out); tmp.remove(i, 1); @@ -158,7 +158,7 @@ struct FsmOpt void opt_alias_inputs() { - RTLIL::SigSpec &ctrl_in = cell->connections_[ID::CTRL_IN]; + RTLIL::SigSpec &ctrl_in = cell->connections_["\\CTRL_IN"]; for (int i = 0; i < ctrl_in.size(); i++) for (int j = i+1; j < ctrl_in.size(); j++) @@ -195,8 +195,8 @@ struct FsmOpt void opt_feedback_inputs() { - RTLIL::SigSpec &ctrl_in = cell->connections_[ID::CTRL_IN]; - RTLIL::SigSpec &ctrl_out = cell->connections_[ID::CTRL_OUT]; + RTLIL::SigSpec &ctrl_in = cell->connections_["\\CTRL_IN"]; + RTLIL::SigSpec &ctrl_out = cell->connections_["\\CTRL_OUT"]; for (int j = 0; j < ctrl_out.size(); j++) for (int i = 0; i < ctrl_in.size(); i++) @@ -324,7 +324,7 @@ PRIVATE_NAMESPACE_BEGIN struct FsmOptPass : public Pass { FsmOptPass() : Pass("fsm_opt", "optimize finite state machines") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -335,15 +335,17 @@ struct FsmOptPass : public Pass { log("combination with the 'opt_clean' pass (see also 'help fsm').\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing FSM_OPT pass (simple optimizations of FSMs).\n"); extra_args(args, 1, design); - for (auto mod : design->selected_modules()) - for (auto cell : mod->selected_cells()) - if (cell->type == ID($fsm)) - FsmData::optimize_fsm(cell, mod); + for (auto &mod_it : design->modules_) { + if (design->selected(mod_it.second)) + for (auto &cell_it : mod_it.second->cells_) + if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second)) + FsmData::optimize_fsm(cell_it.second, mod_it.second); + } } } FsmOptPass; diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc index d4a704270c9..fa1ff48cc0f 100644 --- a/passes/fsm/fsm_recode.cc +++ b/passes/fsm/fsm_recode.cc @@ -32,7 +32,7 @@ PRIVATE_NAMESPACE_BEGIN static void fm_set_fsm_print(RTLIL::Cell *cell, RTLIL::Module *module, FsmData &fsm_data, const char *prefix, FILE *f) { - std::string name = cell->parameters[ID::NAME].decode_string(); + std::string name = cell->parameters["\\NAME"].decode_string(); fprintf(f, "set_fsm_state_vector {"); for (int i = fsm_data.state_bits-1; i >= 0; i--) @@ -53,7 +53,7 @@ static void fm_set_fsm_print(RTLIL::Cell *cell, RTLIL::Module *module, FsmData & static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fsm_file, FILE *encfile, std::string default_encoding) { - std::string encoding = cell->attributes.count(ID::fsm_encoding) ? cell->attributes.at(ID::fsm_encoding).decode_string() : "auto"; + std::string encoding = cell->attributes.count("\\fsm_encoding") ? cell->attributes.at("\\fsm_encoding").decode_string() : "auto"; log("Recoding FSM `%s' from module `%s' using `%s' encoding:\n", cell->name.c_str(), module->name.c_str(), encoding.c_str()); @@ -95,7 +95,7 @@ static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fs log_error("FSM encoding `%s' is not supported!\n", encoding.c_str()); if (encfile) - fprintf(encfile, ".fsm %s %s\n", log_id(module), RTLIL::unescape_id(cell->parameters[ID::NAME].decode_string()).c_str()); + fprintf(encfile, ".fsm %s %s\n", log_id(module), RTLIL::unescape_id(cell->parameters["\\NAME"].decode_string()).c_str()); int state_idx_counter = fsm_data.reset_state >= 0 ? 1 : 0; for (int i = 0; i < int(fsm_data.state_table.size()); i++) @@ -126,7 +126,7 @@ static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fs struct FsmRecodePass : public Pass { FsmRecodePass() : Pass("fsm_recode", "recoding finite state machines") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -151,7 +151,7 @@ struct FsmRecodePass : public Pass { log(" .map \n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { FILE *fm_set_fsm_file = NULL; FILE *encfile = NULL; @@ -181,10 +181,11 @@ struct FsmRecodePass : public Pass { } extra_args(args, argidx, design); - for (auto mod : design->selected_modules()) - for (auto cell : mod->selected_cells()) - if (cell->type == ID($fsm)) - fsm_recode(cell, mod, fm_set_fsm_file, encfile, default_encoding); + for (auto &mod_it : design->modules_) + if (design->selected(mod_it.second)) + for (auto &cell_it : mod_it.second->cells_) + if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second)) + fsm_recode(cell_it.second, mod_it.second, fm_set_fsm_file, encfile, default_encoding); if (fm_set_fsm_file != NULL) fclose(fm_set_fsm_file); diff --git a/passes/fsm/fsmdata.h b/passes/fsm/fsmdata.h index 47398b558ed..68222769a52 100644 --- a/passes/fsm/fsmdata.h +++ b/passes/fsm/fsmdata.h @@ -33,31 +33,31 @@ struct FsmData void copy_to_cell(RTLIL::Cell *cell) { - cell->parameters[ID::CTRL_IN_WIDTH] = RTLIL::Const(num_inputs); - cell->parameters[ID::CTRL_OUT_WIDTH] = RTLIL::Const(num_outputs); + cell->parameters["\\CTRL_IN_WIDTH"] = RTLIL::Const(num_inputs); + cell->parameters["\\CTRL_OUT_WIDTH"] = RTLIL::Const(num_outputs); int state_num_log2 = 0; for (int i = state_table.size(); i > 0; i = i >> 1) state_num_log2++; state_num_log2 = max(state_num_log2, 1); - cell->parameters[ID::STATE_BITS] = RTLIL::Const(state_bits); - cell->parameters[ID::STATE_NUM] = RTLIL::Const(state_table.size()); - cell->parameters[ID::STATE_NUM_LOG2] = RTLIL::Const(state_num_log2); - cell->parameters[ID::STATE_RST] = RTLIL::Const(reset_state); - cell->parameters[ID::STATE_TABLE] = RTLIL::Const(); + cell->parameters["\\STATE_BITS"] = RTLIL::Const(state_bits); + cell->parameters["\\STATE_NUM"] = RTLIL::Const(state_table.size()); + cell->parameters["\\STATE_NUM_LOG2"] = RTLIL::Const(state_num_log2); + cell->parameters["\\STATE_RST"] = RTLIL::Const(reset_state); + cell->parameters["\\STATE_TABLE"] = RTLIL::Const(); for (int i = 0; i < int(state_table.size()); i++) { - std::vector &bits_table = cell->parameters[ID::STATE_TABLE].bits; + std::vector &bits_table = cell->parameters["\\STATE_TABLE"].bits; std::vector &bits_state = state_table[i].bits; bits_table.insert(bits_table.end(), bits_state.begin(), bits_state.end()); } - cell->parameters[ID::TRANS_NUM] = RTLIL::Const(transition_table.size()); - cell->parameters[ID::TRANS_TABLE] = RTLIL::Const(); + cell->parameters["\\TRANS_NUM"] = RTLIL::Const(transition_table.size()); + cell->parameters["\\TRANS_TABLE"] = RTLIL::Const(); for (int i = 0; i < int(transition_table.size()); i++) { - std::vector &bits_table = cell->parameters[ID::TRANS_TABLE].bits; + std::vector &bits_table = cell->parameters["\\TRANS_TABLE"].bits; transition_t &tr = transition_table[i]; RTLIL::Const const_state_in = RTLIL::Const(tr.state_in, state_num_log2); @@ -78,21 +78,21 @@ struct FsmData void copy_from_cell(RTLIL::Cell *cell) { - num_inputs = cell->parameters[ID::CTRL_IN_WIDTH].as_int(); - num_outputs = cell->parameters[ID::CTRL_OUT_WIDTH].as_int(); + num_inputs = cell->parameters["\\CTRL_IN_WIDTH"].as_int(); + num_outputs = cell->parameters["\\CTRL_OUT_WIDTH"].as_int(); - state_bits = cell->parameters[ID::STATE_BITS].as_int(); - reset_state = cell->parameters[ID::STATE_RST].as_int(); + state_bits = cell->parameters["\\STATE_BITS"].as_int(); + reset_state = cell->parameters["\\STATE_RST"].as_int(); - int state_num = cell->parameters[ID::STATE_NUM].as_int(); - int state_num_log2 = cell->parameters[ID::STATE_NUM_LOG2].as_int(); - int trans_num = cell->parameters[ID::TRANS_NUM].as_int(); + int state_num = cell->parameters["\\STATE_NUM"].as_int(); + int state_num_log2 = cell->parameters["\\STATE_NUM_LOG2"].as_int(); + int trans_num = cell->parameters["\\TRANS_NUM"].as_int(); if (reset_state < 0 || reset_state >= state_num) reset_state = -1; - RTLIL::Const state_table = cell->parameters[ID::STATE_TABLE]; - RTLIL::Const trans_table = cell->parameters[ID::TRANS_TABLE]; + RTLIL::Const state_table = cell->parameters["\\STATE_TABLE"]; + RTLIL::Const trans_table = cell->parameters["\\TRANS_TABLE"]; for (int i = 0; i < state_num; i++) { RTLIL::Const state_code; @@ -134,7 +134,7 @@ struct FsmData { log("-------------------------------------\n"); log("\n"); - log(" Information on FSM %s (%s):\n", cell->name.c_str(), cell->parameters[ID::NAME].decode_string().c_str()); + log(" Information on FSM %s (%s):\n", cell->name.c_str(), cell->parameters["\\NAME"].decode_string().c_str()); log("\n"); log(" Number of input signals: %3d\n", num_inputs); log(" Number of output signals: %3d\n", num_outputs); @@ -142,13 +142,13 @@ struct FsmData log("\n"); log(" Input signals:\n"); - RTLIL::SigSpec sig_in = cell->getPort(ID::CTRL_IN); + RTLIL::SigSpec sig_in = cell->getPort("\\CTRL_IN"); for (int i = 0; i < GetSize(sig_in); i++) log(" %3d: %s\n", i, log_signal(sig_in[i])); log("\n"); log(" Output signals:\n"); - RTLIL::SigSpec sig_out = cell->getPort(ID::CTRL_OUT); + RTLIL::SigSpec sig_out = cell->getPort("\\CTRL_OUT"); for (int i = 0; i < GetSize(sig_out); i++) log(" %3d: %s\n", i, log_signal(sig_out[i])); diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index a2a428d1528..d8a628448ff 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -42,10 +42,11 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, { std::set found_celltypes; - for (auto mod : design->modules()) - for (auto cell : mod->cells()) + for (auto i1 : design->modules_) + for (auto i2 : i1.second->cells_) { - if (design->module(cell->type) != nullptr) + RTLIL::Cell *cell = i2.second; + if (design->has(cell->type)) continue; if (cell->type.begins_with("$__")) continue; @@ -61,15 +62,15 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, std::map portwidths; log("Generate module for cell type %s:\n", celltype.c_str()); - for (auto mod : design->modules()) - for (auto cell : mod->cells()) - if (cell->type == celltype) { - for (auto &conn : cell->connections()) { + for (auto i1 : design->modules_) + for (auto i2 : i1.second->cells_) + if (i2.second->type == celltype) { + for (auto &conn : i2.second->connections()) { if (conn.first[0] != '$') portnames.insert(conn.first); portwidths[conn.first] = max(portwidths[conn.first], conn.second.size()); } - for (auto ¶ : cell->parameters) + for (auto ¶ : i2.second->parameters) parameters.insert(para.first); } @@ -120,7 +121,7 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, RTLIL::Module *mod = new RTLIL::Module; mod->name = celltype; - mod->attributes[ID::blackbox] = RTLIL::Const(1); + mod->attributes["\\blackbox"] = RTLIL::Const(1); design->add(mod); for (auto &decl : ports) { @@ -166,25 +167,27 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check // If any of the ports are actually interface ports, we will always need to // reprocess the module: - if(!module->get_bool_attribute(ID::interfaces_replaced_in_module)) { - for (auto wire : module->wires()) { - if ((wire->port_input || wire->port_output) && wire->get_bool_attribute(ID::is_interface)) + if(!module->get_bool_attribute("\\interfaces_replaced_in_module")) { + for (auto &wire : module->wires_) { + if ((wire.second->port_input || wire.second->port_output) && wire.second->get_bool_attribute("\\is_interface")) has_interface_ports = true; } } // Always keep track of all derived interfaces available in the current module in 'interfaces_in_module': dict interfaces_in_module; - for (auto cell : module->cells()) + for (auto &cell_it : module->cells_) { - if(cell->get_bool_attribute(ID::is_interface)) { - RTLIL::Module *intf_module = design->module(cell->type); + RTLIL::Cell *cell = cell_it.second; + if(cell->get_bool_attribute("\\is_interface")) { + RTLIL::Module *intf_module = design->modules_[cell->type]; interfaces_in_module[cell->name] = intf_module; } } - for (auto cell : module->cells()) + for (auto &cell_it : module->cells_) { + RTLIL::Cell *cell = cell_it.second; bool has_interfaces_not_found = false; std::vector connections_to_remove; @@ -205,11 +208,11 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check dict interfaces_to_add_to_submodule; dict modports_used_in_submodule; - if (design->module(cell->type) == nullptr) + if (design->modules_.count(cell->type) == 0) { - if (design->module("$abstract" + cell->type.str()) != nullptr) + if (design->modules_.count("$abstract" + cell->type.str())) { - cell->type = design->module("$abstract" + cell->type.str())->derive(design, cell->parameters); + cell->type = design->modules_.at("$abstract" + cell->type.str())->derive(design, cell->parameters); cell->parameters.clear(); did_something = true; continue; @@ -243,7 +246,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check continue; loaded_module: - if (design->module(cell->type) == nullptr) + if (design->modules_.count(cell->type) == 0) log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str()); did_something = true; } else { @@ -253,14 +256,24 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check // Go over all connections and see if any of them are SV interfaces. If they are, then add the replacements to // some lists, so that the ports for sub-modules can be replaced further down: for (auto &conn : cell->connections()) { - if(mod->wire(conn.first) != nullptr && mod->wire(conn.first)->get_bool_attribute(ID::is_interface)) { // Check if the connection is present as an interface in the sub-module's port list - if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute(ID::is_interface)) { // Check if the connected wire is a potential interface in the parent module + if(mod->wires_.count(conn.first) != 0 && mod->wire(conn.first)->get_bool_attribute("\\is_interface")) { // Check if the connection is present as an interface in the sub-module's port list + //const pool &interface_type_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_type"); + //for (auto &d : interface_type_pool) { // TODO: Compare interface type to type in parent module (not crucially important, but good for robustness) + //} + + // Find if the sub-module has set a modport for the current interface connection: + const pool &interface_modport_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_modport"); + std::string interface_modport = ""; + for (auto &d : interface_modport_pool) { + interface_modport = "\\" + d; + } + if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute("\\is_interface")) { // Check if the connected wire is a potential interface in the parent module std::string interface_name_str = conn.second.bits()[0].wire->name.str(); interface_name_str.replace(0,23,""); // Strip the prefix '$dummywireforinterface' from the dummy wire to get the name interface_name_str = "\\" + interface_name_str; RTLIL::IdString interface_name = interface_name_str; bool not_found_interface = false; - if(module->get_bool_attribute(ID::interfaces_replaced_in_module)) { // If 'interfaces' in the cell have not be been handled yet, there is no need to derive the sub-module either + if(module->get_bool_attribute("\\interfaces_replaced_in_module")) { // If 'interfaces' in the cell have not be been handled yet, there is no need to derive the sub-module either // Check if the interface instance is present in module: // Interface instances may either have the plain name or the name appended with '_inst_from_top_dummy'. // Check for both of them here @@ -272,11 +285,11 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check if (nexactmatch != 0) // Choose the one with the plain name if it exists interface_name2 = interface_name; RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name2); - for (auto mod_wire : mod_replace_ports->wires()) { // Go over all wires in interface, and add replacements to lists. - std::string signal_name1 = conn.first.str() + "." + log_id(mod_wire->name); - std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire); + for (auto &mod_wire : mod_replace_ports->wires_) { // Go over all wires in interface, and add replacements to lists. + std::string signal_name1 = conn.first.str() + "." + log_id(mod_wire.first); + std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire.first); connections_to_add_name.push_back(RTLIL::IdString(signal_name1)); - if(module->wire(signal_name2) == nullptr) { + if(module->wires_.count(signal_name2) == 0) { log_error("Could not find signal '%s' in '%s'\n", signal_name2.c_str(), log_id(module->name)); } else { @@ -287,12 +300,9 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check connections_to_remove.push_back(conn.first); interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name2); - // Find if the sub-module has set a modport for the current - // interface connection. Add any modports to a dict which will - // be passed to AstModule::derive - string modport_name = mod->wire(conn.first)->get_string_attribute(ID::interface_modport); - if (!modport_name.empty()) { - modports_used_in_submodule[conn.first] = "\\" + modport_name; + // Add modports to a dict which will be passed to AstModule::derive + if (interface_modport != "") { + modports_used_in_submodule[conn.first] = interface_modport; } } else not_found_interface = true; @@ -302,7 +312,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check // which will delay the expansion of this cell: if (not_found_interface) { // If we have already gone over all cells in this module, and the interface has still not been found - flag it as an error: - if(!(module->get_bool_attribute(ID::cells_not_processed))) { + if(!(module->get_bool_attribute("\\cells_not_processed"))) { log_warning("Could not find interface instance for `%s' in `%s'\n", log_id(interface_name), log_id(module)); } else { @@ -327,22 +337,16 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first)); } - for (auto ¶m : cell->parameters) { - if (param.first[0] == '$' && '0' <= param.first[1] && param.first[1] <= '9') { - int id = atoi(param.first.c_str()+1); - if (id <= 0 || id > GetSize(mod->avail_parameters)) - log_error("Module `%s' referenced in module `%s' in cell `%s' has only %d parameters, requested parameter %d.\n", - log_id(cell->type), log_id(module), log_id(cell), GetSize(mod->avail_parameters), id); - } else if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL) + for (auto ¶m : cell->parameters) + if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL) log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(param.first)); - } } } - RTLIL::Module *mod = design->module(cell->type); + RTLIL::Module *mod = design->modules_[cell->type]; - if (design->module(cell->type)->get_blackbox_attribute()) { + if (design->modules_.at(cell->type)->get_blackbox_attribute()) { if (flag_simcheck) log_error("Module `%s' referenced in module `%s' in cell `%s' is a blackbox/whitebox module.\n", cell->type.c_str(), module->name.c_str(), cell->name.c_str()); @@ -366,10 +370,10 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check // If there are no overridden parameters AND not interfaces, then we can use the existing module instance as the type // for the cell: - if (cell->parameters.size() == 0 && (interfaces_to_add_to_submodule.size() == 0 || !(cell->get_bool_attribute(ID::module_not_derived)))) { + if (cell->parameters.size() == 0 && (interfaces_to_add_to_submodule.size() == 0 || !(cell->get_bool_attribute("\\module_not_derived")))) { // If the cell being processed is an the interface instance itself, go down to "handle_interface_instance:", // so that the signals of the interface are added to the parent module. - if (mod->get_bool_attribute(ID::is_interface)) { + if (mod->get_bool_attribute("\\is_interface")) { goto handle_interface_instance; } continue; @@ -383,23 +387,23 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check // We add all the signals of the interface explicitly to the parent module. This is always needed when we encounter // an interface instance: - if (mod->get_bool_attribute(ID::is_interface) && cell->get_bool_attribute(ID::module_not_derived)) { - cell->set_bool_attribute(ID::is_interface); - RTLIL::Module *derived_module = design->module(cell->type); + if (mod->get_bool_attribute("\\is_interface") && cell->get_bool_attribute("\\module_not_derived")) { + cell->set_bool_attribute("\\is_interface"); + RTLIL::Module *derived_module = design->modules_[cell->type]; interfaces_in_module[cell->name] = derived_module; did_something = true; } // We clear 'module_not_derived' such that we will not rederive the cell again (needed when there are interfaces connected to the cell) - cell->attributes.erase(ID::module_not_derived); + cell->attributes.erase("\\module_not_derived"); } // Clear the attribute 'cells_not_processed' such that it can be known that we // have been through all cells at least once, and that we can know whether // to flag an error because of interface instances not found: - module->attributes.erase(ID::cells_not_processed); + module->attributes.erase("\\cells_not_processed"); // If any interface instances or interface ports were found in the module, we need to rederive it completely: - if ((interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute(ID::interfaces_replaced_in_module)) { + if ((interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute("\\interfaces_replaced_in_module")) { module->reprocess_module(design, interfaces_in_module); return did_something; } @@ -410,25 +414,25 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check RTLIL::Cell *cell = it.first; int idx = it.second.first, num = it.second.second; - if (design->module(cell->type) == nullptr) + if (design->modules_.count(cell->type) == 0) log_error("Array cell `%s.%s' of unknown type `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); - RTLIL::Module *mod = design->module(cell->type); + RTLIL::Module *mod = design->modules_[cell->type]; for (auto &conn : cell->connections_) { int conn_size = conn.second.size(); RTLIL::IdString portname = conn.first; if (portname.begins_with("$")) { int port_id = atoi(portname.substr(1).c_str()); - for (auto wire : mod->wires()) - if (wire->port_id == port_id) { - portname = wire->name; + for (auto &wire_it : mod->wires_) + if (wire_it.second->port_id == port_id) { + portname = wire_it.first; break; } } - if (mod->wire(portname) == nullptr) + if (mod->wires_.count(portname) == 0) log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first)); - int port_size = mod->wire(portname)->width; + int port_size = mod->wires_.at(portname)->width; if (conn_size == port_size || conn_size == 0) continue; if (conn_size != port_size*num) @@ -466,21 +470,21 @@ void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib) hierarchy_worker(design, used, top, 0); std::vector del_modules; - for (auto mod : design->modules()) - if (used.count(mod) == 0) - del_modules.push_back(mod); + for (auto &it : design->modules_) + if (used.count(it.second) == 0) + del_modules.push_back(it.second); else { // Now all interface ports must have been exploded, and it is hence // safe to delete all of the remaining dummy interface ports: pool del_wires; - for(auto wire : mod->wires()) { - if ((wire->port_input || wire->port_output) && wire->get_bool_attribute(ID::is_interface)) { - del_wires.insert(wire); + for(auto &wire : it.second->wires_) { + if ((wire.second->port_input || wire.second->port_output) && wire.second->get_bool_attribute("\\is_interface")) { + del_wires.insert(wire.second); } } if (del_wires.size() > 0) { - mod->remove(del_wires); - mod->fixup_ports(); + it.second->remove(del_wires); + it.second->fixup_ports(); } } @@ -489,8 +493,9 @@ void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib) if (!purge_lib && mod->get_blackbox_attribute()) continue; log("Removing unused module `%s'.\n", mod->name.c_str()); - design->remove(mod); + design->modules_.erase(mod->name); del_counter++; + delete mod; } log("Removed %d unused modules.\n", del_counter); @@ -501,7 +506,7 @@ bool set_keep_assert(std::map &cache, RTLIL::Module *mod) if (cache.count(mod) == 0) for (auto c : mod->cells()) { RTLIL::Module *m = mod->design->module(c->type); - if ((m != nullptr && set_keep_assert(cache, m)) || c->type.in(ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) + if ((m != nullptr && set_keep_assert(cache, m)) || c->type.in("$assert", "$assume", "$live", "$fair", "$cover")) return cache[mod] = true; } return cache[mod]; @@ -531,11 +536,11 @@ int find_top_mod_score(Design *design, Module *module, dict &db) RTLIL::Module *check_if_top_has_changed(Design *design, Module *top_mod) { - if(top_mod != NULL && top_mod->get_bool_attribute(ID::initial_top)) + if(top_mod != NULL && top_mod->get_bool_attribute("\\initial_top")) return top_mod; else { for (auto mod : design->modules()) { - if (mod->get_bool_attribute(ID::top)) { + if (mod->get_bool_attribute("\\top")) { return mod; } } @@ -543,22 +548,9 @@ RTLIL::Module *check_if_top_has_changed(Design *design, Module *top_mod) return NULL; } -// Find a matching wire for an implicit port connection; traversing generate block scope -RTLIL::Wire *find_implicit_port_wire(Module *module, Cell *cell, const std::string& port) -{ - const std::string &cellname = cell->name.str(); - size_t idx = cellname.size(); - while ((idx = cellname.find_last_of('.', idx-1)) != std::string::npos) { - Wire *found = module->wire(cellname.substr(0, idx+1) + port.substr(1)); - if (found != nullptr) - return found; - } - return module->wire(port); -} - struct HierarchyPass : public Pass { HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -567,9 +559,9 @@ struct HierarchyPass : public Pass { log("\n"); log("In parametric designs, a module might exists in several variations with\n"); log("different parameter values. This pass looks at all modules in the current\n"); - log("design and re-runs the language frontends for the parametric modules as\n"); + log("design an re-runs the language frontends for the parametric modules as\n"); log("needed. It also resolves assignments to wired logic data types (wand/wor),\n"); - log("resolves positional module parameters, unrolls array instances, and more.\n"); + log("resolves positional module parameters, unroll array instances, and more.\n"); log("\n"); log(" -check\n"); log(" also check the design hierarchy. this generates an error when\n"); @@ -639,7 +631,7 @@ struct HierarchyPass : public Pass { log("in the current design.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing HIERARCHY pass (managing design hierarchy).\n"); @@ -812,9 +804,9 @@ struct HierarchyPass : public Pass { log_push(); if (top_mod == nullptr) - for (auto mod : design->modules()) - if (mod->get_bool_attribute(ID::top)) - top_mod = mod; + for (auto &mod_it : design->modules_) + if (mod_it.second->get_bool_attribute("\\top")) + top_mod = mod_it.second; if (top_mod != nullptr && top_mod->name.begins_with("$abstract")) { IdString top_name = top_mod->name.substr(strlen("$abstract")); @@ -857,11 +849,11 @@ struct HierarchyPass : public Pass { log_error("Design has no top module.\n"); if (top_mod != NULL) { - for (auto mod : design->modules()) - if (mod == top_mod) - mod->attributes[ID::initial_top] = RTLIL::Const(1); + for (auto &mod_it : design->modules_) + if (mod_it.second == top_mod) + mod_it.second->attributes["\\initial_top"] = RTLIL::Const(1); else - mod->attributes.erase(ID::initial_top); + mod_it.second->attributes.erase("\\initial_top"); } bool did_something = true; @@ -895,9 +887,9 @@ struct HierarchyPass : public Pass { // Delete modules marked as 'to_delete': std::vector modules_to_delete; - for(auto mod : design->modules()) { - if (mod->get_bool_attribute(ID::to_delete)) { - modules_to_delete.push_back(mod); + for(auto &mod_it : design->modules_) { + if (mod_it.second->get_bool_attribute("\\to_delete")) { + modules_to_delete.push_back(mod_it.second); } } for(size_t i=0; imodules()) { - if (mod == top_mod) - mod->attributes[ID::top] = RTLIL::Const(1); + for (auto &mod_it : design->modules_) { + if (mod_it.second == top_mod) + mod_it.second->attributes["\\top"] = RTLIL::Const(1); else - mod->attributes.erase(ID::top); - mod->attributes.erase(ID::initial_top); + mod_it.second->attributes.erase("\\top"); + mod_it.second->attributes.erase("\\initial_top"); } } @@ -926,7 +918,7 @@ struct HierarchyPass : public Pass { for (auto mod : design->modules()) if (set_keep_assert(cache, mod)) { log("Module %s directly or indirectly contains formal properties -> setting \"keep\" attribute.\n", log_id(mod)); - mod->set_bool_attribute(ID::keep); + mod->set_bool_attribute("\\keep"); } } @@ -936,38 +928,22 @@ struct HierarchyPass : public Pass { std::map, RTLIL::IdString> pos_map; std::vector> pos_work; - for (auto mod : design->modules()) - for (auto cell : mod->cells()) { - RTLIL::Module *cell_mod = design->module(cell->type); - if (cell_mod == nullptr) + for (auto &mod_it : design->modules_) + for (auto &cell_it : mod_it.second->cells_) { + RTLIL::Cell *cell = cell_it.second; + if (design->modules_.count(cell->type) == 0) continue; for (auto &conn : cell->connections()) if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') { - pos_mods.insert(design->module(cell->type)); - pos_work.push_back(std::pair(mod, cell)); + pos_mods.insert(design->modules_.at(cell->type)); + pos_work.push_back(std::pair(mod_it.second, cell)); break; } - - pool> params_rename; - for (const auto &p : cell->parameters) { - if (p.first[0] == '$' && '0' <= p.first[1] && p.first[1] <= '9') { - int id = atoi(p.first.c_str()+1); - if (id <= 0 || id > GetSize(cell_mod->avail_parameters)) { - log(" Failed to map positional parameter %d of cell %s.%s (%s).\n", - id, RTLIL::id2cstr(mod->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); - } else { - params_rename.insert(std::make_pair(p.first, cell_mod->avail_parameters[id - 1])); - } - } - } - for (const auto &p : params_rename) { - cell->setParam(p.second, cell->getParam(p.first)); - cell->unsetParam(p.first); - } } for (auto module : pos_mods) - for (auto wire : module->wires()) { + for (auto &wire_it : module->wires_) { + RTLIL::Wire *wire = wire_it.second; if (wire->port_id > 0) pos_map[std::pair(module, wire->port_id)] = wire->name; } @@ -981,7 +957,7 @@ struct HierarchyPass : public Pass { for (auto &conn : cell->connections()) if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') { int id = atoi(conn.first.c_str()+1); - std::pair key(design->module(cell->type), id); + std::pair key(design->modules_.at(cell->type), id); if (pos_map.count(key) == 0) { log(" Failed to map positional argument %d of cell %s.%s (%s).\n", id, RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); @@ -994,71 +970,15 @@ struct HierarchyPass : public Pass { } } - // Determine default values - dict> defaults_db; if (!nodefaults) { + dict> defaults_db; + for (auto module : design->modules()) for (auto wire : module->wires()) - if (wire->port_input && wire->attributes.count(ID::defaultvalue)) - defaults_db[module->name][wire->name] = wire->attributes.at(ID::defaultvalue); - } - // Process SV implicit wildcard port connections - std::set blackbox_derivatives; - std::vector design_modules = design->modules(); - - for (auto module : design_modules) - { - for (auto cell : module->cells()) - { - if (!cell->get_bool_attribute(ID::wildcard_port_conns)) - continue; - Module *m = design->module(cell->type); - - if (m == nullptr) - log_error("Cell %s.%s (%s) has implicit port connections but the module it instantiates is unknown.\n", - RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); - - // Need accurate port widths for error checking; so must derive blackboxes with dynamic port widths - if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute(ID::dynports)) { - IdString new_m_name = m->derive(design, cell->parameters, true); - if (new_m_name.empty()) - continue; - if (new_m_name != m->name) { - m = design->module(new_m_name); - blackbox_derivatives.insert(m); - } - } + if (wire->port_input && wire->attributes.count("\\defaultvalue")) + defaults_db[module->name][wire->name] = wire->attributes.at("\\defaultvalue"); - auto old_connections = cell->connections(); - for (auto wire : m->wires()) { - // Find ports of the module that aren't explicitly connected - if (!wire->port_input && !wire->port_output) - continue; - if (old_connections.count(wire->name)) - continue; - // Make sure a wire of correct name exists in the parent - Wire* parent_wire = find_implicit_port_wire(module, cell, wire->name.str()); - - // Missing wires are OK when a default value is set - if (!nodefaults && parent_wire == nullptr && defaults_db.count(cell->type) && defaults_db.at(cell->type).count(wire->name)) - continue; - - if (parent_wire == nullptr) - log_error("No matching wire for implicit port connection `%s' of cell %s.%s (%s).\n", - RTLIL::id2cstr(wire->name), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); - if (parent_wire->width != wire->width) - log_error("Width mismatch between wire (%d bits) and port (%d bits) for implicit port connection `%s' of cell %s.%s (%s).\n", - parent_wire->width, wire->width, - RTLIL::id2cstr(wire->name), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); - cell->setPort(wire->name, parent_wire); - } - cell->attributes.erase(ID::wildcard_port_conns); - } - } - - if (!nodefaults) - { for (auto module : design->modules()) for (auto cell : module->cells()) { @@ -1080,6 +1000,9 @@ struct HierarchyPass : public Pass { } } + std::set blackbox_derivatives; + std::vector design_modules = design->modules(); + for (auto module : design_modules) { pool wand_wor_index; @@ -1088,11 +1011,11 @@ struct HierarchyPass : public Pass { for (auto wire : module->wires()) { - if (wire->get_bool_attribute(ID::wand)) { + if (wire->get_bool_attribute("\\wand")) { wand_map[wire] = SigSpec(); wand_wor_index.insert(wire); } - if (wire->get_bool_attribute(ID::wor)) { + if (wire->get_bool_attribute("\\wor")) { wor_map[wire] = SigSpec(); wand_wor_index.insert(wire); } @@ -1203,7 +1126,7 @@ struct HierarchyPass : public Pass { if (m == nullptr) continue; - if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute(ID::dynports)) { + if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) { IdString new_m_name = m->derive(design, cell->parameters, true); if (new_m_name.empty()) continue; diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index b2826cbff85..ec242aa1fa6 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -20,7 +20,6 @@ #include "kernel/register.h" #include "kernel/celltypes.h" #include "kernel/log.h" -#include "kernel/sigtools.h" #include #include #include @@ -33,56 +32,49 @@ struct SubmodWorker CellTypes ct; RTLIL::Design *design; RTLIL::Module *module; - SigMap sigmap; bool copy_mode; - bool hidden_mode; std::string opt_name; struct SubModule { std::string name, full_name; - pool cells; + std::set cells; }; std::map submodules; struct wire_flags_t { RTLIL::Wire *new_wire; - RTLIL::Const is_int_driven; - bool is_int_used, is_ext_driven, is_ext_used; - wire_flags_t(RTLIL::Wire* wire) : new_wire(nullptr), is_int_driven(State::S0, GetSize(wire)), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } + bool is_int_driven, is_int_used, is_ext_driven, is_ext_used; + wire_flags_t() : new_wire(NULL), is_int_driven(false), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } }; std::map wire_flags; bool flag_found_something; - void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_used, bool set_ext_driven, bool set_ext_used) + void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) { if (wire_flags.count(wire) == 0) { if (!create) return; - wire_flags.emplace(wire, wire); + wire_flags[wire] = wire_flags_t(); } + if (set_int_driven) + wire_flags[wire].is_int_driven = true; if (set_int_used) - wire_flags.at(wire).is_int_used = true; + wire_flags[wire].is_int_used = true; if (set_ext_driven) - wire_flags.at(wire).is_ext_driven = true; + wire_flags[wire].is_ext_driven = true; if (set_ext_used) - wire_flags.at(wire).is_ext_used = true; + wire_flags[wire].is_ext_used = true; flag_found_something = true; } void flag_signal(const RTLIL::SigSpec &sig, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) { for (auto &c : sig.chunks()) - if (c.wire != nullptr) { - flag_wire(c.wire, create, set_int_used, set_ext_driven, set_ext_used); - if (set_int_driven) - for (int i = c.offset; i < c.offset+c.width; i++) { - wire_flags.at(c.wire).is_int_driven[i] = State::S1; - flag_found_something = true; - } - } + if (c.wire != NULL) + flag_wire(c.wire, create, set_int_driven, set_int_used, set_ext_driven, set_ext_used); } void handle_submodule(SubModule &submod) @@ -100,7 +92,8 @@ struct SubmodWorker flag_signal(conn.second, true, true, true, false, false); } } - for (auto cell : module->cells()) { + for (auto &it : module->cells_) { + RTLIL::Cell *cell = it.second; if (submod.cells.count(cell) > 0) continue; if (ct.cell_known(cell->type)) { @@ -134,39 +127,27 @@ struct SubmodWorker flags.is_ext_driven = true; if (wire->port_output) flags.is_ext_used = true; - else { - auto sig = sigmap(wire); - for (auto c : sig.chunks()) - if (c.wire && c.wire->port_output) { - flags.is_ext_used = true; - break; - } - } bool new_wire_port_input = false; bool new_wire_port_output = false; - if (!flags.is_int_driven.is_fully_zero() && flags.is_ext_used) + if (flags.is_int_driven && flags.is_ext_used) new_wire_port_output = true; if (flags.is_ext_driven && flags.is_int_used) new_wire_port_input = true; - if (!flags.is_int_driven.is_fully_zero() && flags.is_ext_driven) + if (flags.is_int_driven && flags.is_ext_driven) new_wire_port_input = true, new_wire_port_output = true; std::string new_wire_name = wire->name.str(); if (new_wire_port_input || new_wire_port_output) { - if (new_wire_name[0] == '$') - while (1) { - std::string next_wire_name = stringf("%s\\n%d", hidden_mode ? "$submod" : "", auto_name_counter++); - if (all_wire_names.count(next_wire_name) == 0) { - all_wire_names.insert(next_wire_name); - new_wire_name = next_wire_name; - break; - } + while (new_wire_name[0] == '$') { + std::string next_wire_name = stringf("\\n%d", auto_name_counter++); + if (all_wire_names.count(next_wire_name) == 0) { + all_wire_names.insert(next_wire_name); + new_wire_name = next_wire_name; } - else if (hidden_mode) - new_wire_name = stringf("$submod%s", new_wire_name.c_str()); + } } RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name, wire->width); @@ -174,22 +155,6 @@ struct SubmodWorker new_wire->port_output = new_wire_port_output; new_wire->start_offset = wire->start_offset; new_wire->attributes = wire->attributes; - if (!flags.is_int_driven.is_fully_zero()) { - new_wire->attributes.erase(ID::init); - auto sig = sigmap(wire); - for (int i = 0; i < GetSize(sig); i++) { - if (flags.is_int_driven[i] == State::S0) - continue; - if (!sig[i].wire) - continue; - auto it = sig[i].wire->attributes.find(ID::init); - if (it != sig[i].wire->attributes.end()) { - auto jt = new_wire->attributes.insert(std::make_pair(ID::init, Const(State::Sx, GetSize(sig)))).first; - jt->second[i] = it->second[sig[i].offset]; - it->second[sig[i].offset] = State::Sx; - } - } - } if (new_wire->port_input && new_wire->port_output) log(" signal %s: inout %s\n", wire->name.c_str(), new_wire->name.c_str()); @@ -210,9 +175,9 @@ struct SubmodWorker RTLIL::Cell *new_cell = new_mod->addCell(cell->name, cell); for (auto &conn : new_cell->connections_) for (auto &bit : conn.second) - if (bit.wire != nullptr) { + if (bit.wire != NULL) { log_assert(wire_flags.count(bit.wire) > 0); - bit.wire = wire_flags.at(bit.wire).new_wire; + bit.wire = wire_flags[bit.wire].new_wire; } log(" cell %s (%s)\n", new_cell->name.c_str(), new_cell->type.c_str()); if (!copy_mode) @@ -224,27 +189,16 @@ struct SubmodWorker RTLIL::Cell *new_cell = module->addCell(submod.full_name, submod.full_name); for (auto &it : wire_flags) { - RTLIL::SigSpec old_sig = sigmap(it.first); + RTLIL::Wire *old_wire = it.first; RTLIL::Wire *new_wire = it.second.new_wire; - if (new_wire->port_id > 0) { - if (new_wire->port_output) - for (int i = 0; i < GetSize(old_sig); i++) { - auto &b = old_sig[i]; - // Prevents "ERROR: Mismatch in directionality ..." when flattening - if (!b.wire) - b = module->addWire(NEW_ID); - // Prevents "Warning: multiple conflicting drivers ..." - else if (!it.second.is_int_driven[i]) - b = module->addWire(NEW_ID); - } - new_cell->setPort(new_wire->name, old_sig); - } + if (new_wire->port_id > 0) + new_cell->setPort(new_wire->name, RTLIL::SigSpec(old_wire)); } } } - SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, bool hidden_mode = false, std::string opt_name = std::string()) : - design(design), module(module), sigmap(module), copy_mode(copy_mode), hidden_mode(hidden_mode), opt_name(opt_name) + SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, std::string opt_name = std::string()) : + design(design), module(module), copy_mode(copy_mode), opt_name(opt_name) { if (!design->selected_whole_module(module->name) && opt_name.empty()) return; @@ -265,31 +219,26 @@ struct SubmodWorker ct.setup_stdcells_mem(); ct.setup_design(design); - for (auto port : module->ports) { - auto wire = module->wire(port); - if (wire->port_output) - sigmap.add(wire); - } - if (opt_name.empty()) { - for (auto wire : module->wires()) - wire->attributes.erase(ID::submod); + for (auto &it : module->wires_) + it.second->attributes.erase("\\submod"); - for (auto cell : module->cells()) + for (auto &it : module->cells_) { - if (cell->attributes.count(ID::submod) == 0 || cell->attributes[ID::submod].bits.size() == 0) { - cell->attributes.erase(ID::submod); + RTLIL::Cell *cell = it.second; + if (cell->attributes.count("\\submod") == 0 || cell->attributes["\\submod"].bits.size() == 0) { + cell->attributes.erase("\\submod"); continue; } - std::string submod_str = cell->attributes[ID::submod].decode_string(); - cell->attributes.erase(ID::submod); + std::string submod_str = cell->attributes["\\submod"].decode_string(); + cell->attributes.erase("\\submod"); if (submodules.count(submod_str) == 0) { submodules[submod_str].name = submod_str; submodules[submod_str].full_name = module->name.str() + "_" + submod_str; - while (design->module(submodules[submod_str].full_name) != nullptr || + while (design->modules_.count(submodules[submod_str].full_name) != 0 || module->count_id(submodules[submod_str].full_name) != 0) submodules[submod_str].full_name += "_"; } @@ -299,8 +248,9 @@ struct SubmodWorker } else { - for (auto cell : module->cells()) + for (auto &it : module->cells_) { + RTLIL::Cell *cell = it.second; if (!design->selected(module, cell)) continue; submodules[opt_name].name = opt_name; @@ -319,11 +269,11 @@ struct SubmodWorker struct SubmodPass : public Pass { SubmodPass() : Pass("submod", "moving part of a module to a new submodule") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" submod [options] [selection]\n"); + log(" submod [-copy] [selection]\n"); log("\n"); log("This pass identifies all cells with the 'submod' attribute and moves them to\n"); log("a newly created module. The value of the attribute is used as name for the\n"); @@ -335,30 +285,25 @@ struct SubmodPass : public Pass { log("This pass only operates on completely selected modules with no processes\n"); log("or memories.\n"); log("\n"); - log(" -copy\n"); - log(" by default the cells are 'moved' from the source module and the source\n"); - log(" module will use an instance of the new module after this command is\n"); - log(" finished. call with -copy to not modify the source module.\n"); log("\n"); - log(" -name \n"); - log(" don't use the 'submod' attribute but instead use the selection. only\n"); - log(" objects from one module might be selected. the value of the -name option\n"); - log(" is used as the value of the 'submod' attribute instead.\n"); + log(" submod -name [-copy] [selection]\n"); log("\n"); - log(" -hidden\n"); - log(" instead of creating submodule ports with public names, create ports with\n"); - log(" private names so that a subsequent 'flatten; clean' call will restore the\n"); - log(" original module with original public names.\n"); + log("As above, but don't use the 'submod' attribute but instead use the selection.\n"); + log("Only objects from one module might be selected. The value of the -name option\n"); + log("is used as the value of the 'submod' attribute above.\n"); + log("\n"); + log("By default the cells are 'moved' from the source module and the source module\n"); + log("will use an instance of the new module after this command is finished. Call\n"); + log("with -copy to not modify the source module.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing SUBMOD pass (moving cells to submodules as requested).\n"); log_push(); std::string opt_name; bool copy_mode = false; - bool hidden_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -370,10 +315,6 @@ struct SubmodPass : public Pass { copy_mode = true; continue; } - if (args[argidx] == "-hidden") { - hidden_mode = true; - continue; - } break; } extra_args(args, argidx, design); @@ -389,12 +330,12 @@ struct SubmodPass : public Pass { while (did_something) { did_something = false; std::vector queued_modules; - for (auto mod : design->modules()) - if (handled_modules.count(mod->name) == 0 && design->selected_whole_module(mod->name)) - queued_modules.push_back(mod->name); + for (auto &mod_it : design->modules_) + if (handled_modules.count(mod_it.first) == 0 && design->selected_whole_module(mod_it.first)) + queued_modules.push_back(mod_it.first); for (auto &modname : queued_modules) - if (design->module(modname) != nullptr) { - SubmodWorker worker(design, design->module(modname), copy_mode, hidden_mode); + if (design->modules_.count(modname) != 0) { + SubmodWorker worker(design, design->modules_[modname], copy_mode); handled_modules.insert(modname); did_something = true; } @@ -404,18 +345,20 @@ struct SubmodPass : public Pass { } else { - RTLIL::Module *module = nullptr; - for (auto mod : design->selected_modules()) { - if (module != nullptr) - log_cmd_error("More than one module selected: %s %s\n", module->name.c_str(), mod->name.c_str()); - module = mod; + RTLIL::Module *module = NULL; + for (auto &mod_it : design->modules_) { + if (!design->selected_module(mod_it.first)) + continue; + if (module != NULL) + log_cmd_error("More than one module selected: %s %s\n", module->name.c_str(), mod_it.first.c_str()); + module = mod_it.second; } - if (module == nullptr) + if (module == NULL) log("Nothing selected -> do nothing.\n"); else { Pass::call_on_module(design, module, "opt_clean"); log_header(design, "Continuing SUBMOD pass.\n"); - SubmodWorker worker(design, module, copy_mode, hidden_mode, opt_name); + SubmodWorker worker(design, module, copy_mode, opt_name); } } diff --git a/passes/hierarchy/uniquify.cc b/passes/hierarchy/uniquify.cc index 3f9443a63f0..ad3220918c8 100644 --- a/passes/hierarchy/uniquify.cc +++ b/passes/hierarchy/uniquify.cc @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN struct UniquifyPass : public Pass { UniquifyPass() : Pass("uniquify", "create unique copies of modules") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -41,7 +41,7 @@ struct UniquifyPass : public Pass { log("attribute set (the 'top' module is unique implicitly).\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing UNIQUIFY pass (creating unique copies of modules).\n"); @@ -64,7 +64,7 @@ struct UniquifyPass : public Pass { for (auto module : design->selected_modules()) { - if (!module->get_bool_attribute(ID::unique) && !module->get_bool_attribute(ID::top)) + if (!module->get_bool_attribute("\\unique") && !module->get_bool_attribute("\\top")) continue; for (auto cell : module->selected_cells()) @@ -78,7 +78,7 @@ struct UniquifyPass : public Pass { if (tmod->get_blackbox_attribute()) continue; - if (tmod->get_bool_attribute(ID::unique) && newname == tmod->name) + if (tmod->get_bool_attribute("\\unique") && newname == tmod->name) continue; log("Creating module %s from %s.\n", log_id(newname), log_id(tmod)); @@ -86,9 +86,9 @@ struct UniquifyPass : public Pass { auto smod = tmod->clone(); smod->name = newname; cell->type = newname; - smod->set_bool_attribute(ID::unique); - if (smod->attributes.count(ID::hdlname) == 0) - smod->attributes[ID::hdlname] = string(log_id(tmod->name)); + smod->set_bool_attribute("\\unique"); + if (smod->attributes.count("\\hdlname") == 0) + smod->attributes["\\hdlname"] = string(log_id(tmod->name)); design->add(smod); did_something = true; diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc index 282517992a5..cee63bdd8c5 100644 --- a/passes/memory/memory.cc +++ b/passes/memory/memory.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct MemoryPass : public Pass { MemoryPass() : Pass("memory", "translate memories to basic cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -49,7 +49,7 @@ struct MemoryPass : public Pass { log("or multiport memory blocks if called with the -nomap option.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_nomap = false; bool flag_nordff = false; diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 3cb0728b797..aa8f9414976 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -105,11 +105,11 @@ struct rules_t log_error("Bram %s variants %d and %d have different values for 'groups'.\n", log_id(name), variant, other.variant); if (abits != other.abits) - variant_params[ID::CFG_ABITS] = abits; + variant_params["\\CFG_ABITS"] = abits; if (dbits != other.dbits) - variant_params[ID::CFG_DBITS] = dbits; + variant_params["\\CFG_DBITS"] = dbits; if (init != other.init) - variant_params[ID::CFG_INIT] = init; + variant_params["\\CFG_INIT"] = init; for (int i = 0; i < groups; i++) { @@ -134,29 +134,11 @@ struct rules_t dict min_limits, max_limits; bool or_next_if_better, make_transp, make_outreg; char shuffle_enable; - vector>> attributes; }; - bool attr_icase; dict> brams; vector matches; - std::string map_case(std::string value) const - { - if (attr_icase) { - for (char &c : value) - c = tolower(c); - } - return value; - } - - RTLIL::Const map_case(RTLIL::Const value) const - { - if (value.flags & RTLIL::CONST_FLAG_STRING) - return map_case(value.decode_string()); - return value; - } - std::ifstream infile; vector tokens; vector labels; @@ -345,20 +327,6 @@ struct rules_t continue; } - if (GetSize(tokens) >= 2 && tokens[0] == "attribute") { - data.attributes.emplace_back(); - for (int idx = 1; idx < GetSize(tokens); idx++) { - size_t c1 = tokens[idx][0] == '!' ? 1 : 0; - size_t c2 = tokens[idx].find("="); - bool exists = (c1 == 0); - IdString key = RTLIL::escape_id(tokens[idx].substr(c1, c2)); - Const val = c2 != std::string::npos ? tokens[idx].substr(c2+1) : RTLIL::Const(1); - - data.attributes.back().emplace_back(exists, key, map_case(val)); - } - continue; - } - syntax_error(); } } @@ -368,7 +336,6 @@ struct rules_t rewrite_filename(filename); infile.open(filename); linecount = 0; - attr_icase = false; if (infile.fail()) log_error("Can't open rules file `%s'.\n", filename.c_str()); @@ -378,11 +345,6 @@ struct rules_t if (!labels.empty()) syntax_error(); - if (GetSize(tokens) == 2 && tokens[0] == "attr_icase") { - attr_icase = atoi(tokens[1].c_str()); - continue; - } - if (tokens[0] == "bram") { parse_bram(); continue; @@ -437,44 +399,44 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram, log(" Mapping to bram type %s (variant %d):\n", log_id(bram.name), bram.variant); // bram.dump_config(); - int mem_size = cell->getParam(ID::SIZE).as_int(); - int mem_abits = cell->getParam(ID::ABITS).as_int(); - int mem_width = cell->getParam(ID::WIDTH).as_int(); - // int mem_offset = cell->getParam(ID::OFFSET).as_int(); + int mem_size = cell->getParam("\\SIZE").as_int(); + int mem_abits = cell->getParam("\\ABITS").as_int(); + int mem_width = cell->getParam("\\WIDTH").as_int(); + // int mem_offset = cell->getParam("\\OFFSET").as_int(); - bool cell_init = !SigSpec(cell->getParam(ID::INIT)).is_fully_undef(); + bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef(); vector initdata; if (cell_init) { - Const initparam = cell->getParam(ID::INIT); + Const initparam = cell->getParam("\\INIT"); initdata.reserve(mem_size); for (int i=0; i < mem_size; i++) initdata.push_back(initparam.extract(mem_width*i, mem_width, State::Sx)); } - int wr_ports = cell->getParam(ID::WR_PORTS).as_int(); - auto wr_clken = SigSpec(cell->getParam(ID::WR_CLK_ENABLE)); - auto wr_clkpol = SigSpec(cell->getParam(ID::WR_CLK_POLARITY)); + int wr_ports = cell->getParam("\\WR_PORTS").as_int(); + auto wr_clken = SigSpec(cell->getParam("\\WR_CLK_ENABLE")); + auto wr_clkpol = SigSpec(cell->getParam("\\WR_CLK_POLARITY")); wr_clken.extend_u0(wr_ports); wr_clkpol.extend_u0(wr_ports); - SigSpec wr_en = cell->getPort(ID::WR_EN); - SigSpec wr_clk = cell->getPort(ID::WR_CLK); - SigSpec wr_data = cell->getPort(ID::WR_DATA); - SigSpec wr_addr = cell->getPort(ID::WR_ADDR); + SigSpec wr_en = cell->getPort("\\WR_EN"); + SigSpec wr_clk = cell->getPort("\\WR_CLK"); + SigSpec wr_data = cell->getPort("\\WR_DATA"); + SigSpec wr_addr = cell->getPort("\\WR_ADDR"); - int rd_ports = cell->getParam(ID::RD_PORTS).as_int(); - auto rd_clken = SigSpec(cell->getParam(ID::RD_CLK_ENABLE)); - auto rd_clkpol = SigSpec(cell->getParam(ID::RD_CLK_POLARITY)); - auto rd_transp = SigSpec(cell->getParam(ID::RD_TRANSPARENT)); + int rd_ports = cell->getParam("\\RD_PORTS").as_int(); + auto rd_clken = SigSpec(cell->getParam("\\RD_CLK_ENABLE")); + auto rd_clkpol = SigSpec(cell->getParam("\\RD_CLK_POLARITY")); + auto rd_transp = SigSpec(cell->getParam("\\RD_TRANSPARENT")); rd_clken.extend_u0(rd_ports); rd_clkpol.extend_u0(rd_ports); rd_transp.extend_u0(rd_ports); - SigSpec rd_en = cell->getPort(ID::RD_EN); - SigSpec rd_clk = cell->getPort(ID::RD_CLK); - SigSpec rd_data = cell->getPort(ID::RD_DATA); - SigSpec rd_addr = cell->getPort(ID::RD_ADDR); + SigSpec rd_en = cell->getPort("\\RD_EN"); + SigSpec rd_clk = cell->getPort("\\RD_CLK"); + SigSpec rd_data = cell->getPort("\\RD_DATA"); + SigSpec rd_addr = cell->getPort("\\RD_ADDR"); if (match.shuffle_enable && bram.dbits >= portinfos.at(match.shuffle_enable - 'A').enable*2 && portinfos.at(match.shuffle_enable - 'A').enable > 0 && wr_ports > 0) { @@ -762,7 +724,7 @@ grow_read_ports:; if (match.make_transp && wr_ports <= 1) { pi.make_transp = true; if (pi.clocks != 0) { - if (wr_ports == 1 && wr_clkdom != clkdom) { + if (wr_ports == 1 && wr_clkdom != clkdom) { log(" Bram port %c%d.%d cannot have soft transparency logic added as read and write clock domains differ.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } @@ -851,43 +813,6 @@ grow_read_ports:; return false; } - for (const auto &sums : match.attributes) { - bool found = false; - for (const auto &term : sums) { - bool exists = std::get<0>(term); - IdString key = std::get<1>(term); - const Const &value = std::get<2>(term); - auto it = cell->attributes.find(key); - if (it == cell->attributes.end()) { - if (exists) - continue; - found = true; - break; - } - else if (!exists) - continue; - if (rules.map_case(it->second) != value) - continue; - found = true; - break; - } - if (!found) { - std::stringstream ss; - bool exists = std::get<0>(sums.front()); - if (!exists) - ss << "!"; - IdString key = std::get<1>(sums.front()); - ss << log_id(key); - const Const &value = rules.map_case(std::get<2>(sums.front())); - if (exists && value != Const(1)) - ss << "=\"" << value.decode_string() << "\""; - - log(" Rule for bram type %s rejected: requirement 'attribute %s ...' not met.\n", - log_id(match.name), ss.str().c_str()); - return false; - } - } - if (mode == 1) return true; } @@ -938,7 +863,7 @@ grow_read_ports:; else initparam[i*bram.dbits+j] = padding; } - c->setParam(ID::INIT, initparam); + c->setParam("\\INIT", initparam); } for (auto &pi : portinfos) @@ -1071,14 +996,14 @@ void handle_cell(Cell *cell, const rules_t &rules) { log("Processing %s.%s:\n", log_id(cell->module), log_id(cell)); - bool cell_init = !SigSpec(cell->getParam(ID::INIT)).is_fully_undef(); + bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef(); dict match_properties; - match_properties["words"] = cell->getParam(ID::SIZE).as_int(); - match_properties["abits"] = cell->getParam(ID::ABITS).as_int(); - match_properties["dbits"] = cell->getParam(ID::WIDTH).as_int(); - match_properties["wports"] = cell->getParam(ID::WR_PORTS).as_int(); - match_properties["rports"] = cell->getParam(ID::RD_PORTS).as_int(); + match_properties["words"] = cell->getParam("\\SIZE").as_int(); + match_properties["abits"] = cell->getParam("\\ABITS").as_int(); + match_properties["dbits"] = cell->getParam("\\WIDTH").as_int(); + match_properties["wports"] = cell->getParam("\\WR_PORTS").as_int(); + match_properties["rports"] = cell->getParam("\\RD_PORTS").as_int(); match_properties["bits"] = match_properties["words"] * match_properties["dbits"]; match_properties["ports"] = match_properties["wports"] + match_properties["rports"]; @@ -1102,6 +1027,9 @@ void handle_cell(Cell *cell, const rules_t &rules) auto &bram = rules.brams.at(match.name).at(vi); bool or_next_if_better = match.or_next_if_better || vi+1 < GetSize(rules.brams.at(match.name)); + if (failed_brams.count(pair(bram.name, bram.variant))) + continue; + int avail_rd_ports = 0; int avail_wr_ports = 0; for (int j = 0; j < bram.groups; j++) { @@ -1137,9 +1065,6 @@ void handle_cell(Cell *cell, const rules_t &rules) int efficiency = (100 * match_properties["bits"]) / (dups * cells * bram.dbits * (1 << bram.abits)); match_properties["efficiency"] = efficiency; - if (failed_brams.count(pair(bram.name, bram.variant))) - goto next_match_rule; - log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n", log_id(match.name), awaste, dwaste, bwaste, waste, efficiency); @@ -1175,43 +1100,6 @@ void handle_cell(Cell *cell, const rules_t &rules) goto next_match_rule; } - for (const auto &sums : match.attributes) { - bool found = false; - for (const auto &term : sums) { - bool exists = std::get<0>(term); - IdString key = std::get<1>(term); - const Const &value = std::get<2>(term); - auto it = cell->attributes.find(key); - if (it == cell->attributes.end()) { - if (exists) - continue; - found = true; - break; - } - else if (!exists) - continue; - if (rules.map_case(it->second) != value) - continue; - found = true; - break; - } - if (!found) { - std::stringstream ss; - bool exists = std::get<0>(sums.front()); - if (!exists) - ss << "!"; - IdString key = std::get<1>(sums.front()); - ss << log_id(key); - const Const &value = rules.map_case(std::get<2>(sums.front())); - if (exists && value != Const(1)) - ss << "=\"" << value.decode_string() << "\""; - - log(" Rule for bram type %s (variant %d) rejected: requirement 'attribute %s ...' not met.\n", - log_id(bram.name), bram.variant, ss.str().c_str()); - goto next_match_rule; - } - } - log(" Rule #%d for bram type %s (variant %d) accepted.\n", i+1, log_id(bram.name), bram.variant); if (or_next_if_better || !best_rule_cache.empty()) @@ -1265,7 +1153,7 @@ void handle_cell(Cell *cell, const rules_t &rules) struct MemoryBramPass : public Pass { MemoryBramPass() : Pass("memory_bram", "map memories to block rams") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1275,13 +1163,8 @@ struct MemoryBramPass : public Pass { log("The given rules file describes the available resources and how they should be\n"); log("used.\n"); log("\n"); - log("The rules file contains configuration options, a set of block ram description\n"); - log("and a sequence of match rules.\n"); - log("\n"); - log("The option 'attr_icase' configures how attribute values are matched. The value 0\n"); - log("means case-sensitive, 1 means case-insensitive.\n"); - log("\n"); - log("A block ram description looks like this:\n"); + log("The rules file contains a set of block ram description and a sequence of match\n"); + log("rules. A block ram description looks like this:\n"); log("\n"); log(" bram RAMB1024X32 # name of BRAM cell\n"); log(" init 1 # set to '1' if BRAM can be initialized\n"); @@ -1342,13 +1225,6 @@ struct MemoryBramPass : public Pass { log(" dcells ....... number of cells in 'data-direction'\n"); log(" cells ........ total number of cells (acells*dcells*dups)\n"); log("\n"); - log("A match containing the command 'attribute' followed by a list of space\n"); - log("separated 'name[=string_value]' values requires that the memory contains any\n"); - log("one of the given attribute name and string values (where specified), or name\n"); - log("and integer 1 value (if no string_value given, since Verilog will interpret\n"); - log("'(* attr *)' as '(* attr=1 *)').\n"); - log("A name prefixed with '!' indicates that the attribute must not exist.\n"); - log("\n"); log("The interface for the created bram instances is derived from the bram\n"); log("description. Use 'techmap' to convert the created bram instances into\n"); log("instances of the actual bram cells of your target architecture.\n"); @@ -1367,7 +1243,7 @@ struct MemoryBramPass : public Pass { log("the data bits to accommodate the enable pattern of port A.\n"); log("\n"); } - void execute(vector args, Design *design) override + void execute(vector args, Design *design) YS_OVERRIDE { rules_t rules; @@ -1385,7 +1261,7 @@ struct MemoryBramPass : public Pass { for (auto mod : design->selected_modules()) for (auto cell : mod->selected_cells()) - if (cell->type == ID($mem)) + if (cell->type == "$mem") handle_cell(cell, rules); } } MemoryBramPass; diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index 7e82f47dc79..9dcb3f0246d 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -25,11 +25,11 @@ PRIVATE_NAMESPACE_BEGIN bool memcells_cmp(Cell *a, Cell *b) { - if (a->type == ID($memrd) && b->type == ID($memrd)) + if (a->type == "$memrd" && b->type == "$memrd") return a->name < b->name; - if (a->type == ID($memrd) || b->type == ID($memrd)) - return (a->type == ID($memrd)) < (b->type == ID($memrd)); - return a->parameters.at(ID::PRIORITY).as_int() < b->parameters.at(ID::PRIORITY).as_int(); + if (a->type == "$memrd" || b->type == "$memrd") + return (a->type == "$memrd") < (b->type == "$memrd"); + return a->parameters.at("\\PRIORITY").as_int() < b->parameters.at("\\PRIORITY").as_int(); } Cell *handle_memory(Module *module, RTLIL::Memory *memory) @@ -60,14 +60,16 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) int addr_bits = 0; std::vector memcells; - for (auto cell : module->cells()) - if (cell->type.in(ID($memrd), ID($memwr), ID($meminit)) && memory->name == cell->parameters[ID::MEMID].decode_string()) { - SigSpec addr = sigmap(cell->getPort(ID::ADDR)); + for (auto &cell_it : module->cells_) { + Cell *cell = cell_it.second; + if (cell->type.in("$memrd", "$memwr", "$meminit") && memory->name == cell->parameters["\\MEMID"].decode_string()) { + SigSpec addr = sigmap(cell->getPort("\\ADDR")); for (int i = 0; i < GetSize(addr); i++) if (addr[i] != State::S0) addr_bits = std::max(addr_bits, i+1); memcells.push_back(cell); } + } if (memory->start_offset == 0 && addr_bits < 30 && (1 << addr_bits) < memory->size) memory->size = 1 << addr_bits; @@ -88,10 +90,10 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) { log(" %s (%s)\n", log_id(cell), log_id(cell->type)); - if (cell->type == ID($meminit)) + if (cell->type == "$meminit") { - SigSpec addr = sigmap(cell->getPort(ID::ADDR)); - SigSpec data = sigmap(cell->getPort(ID::DATA)); + SigSpec addr = sigmap(cell->getPort("\\ADDR")); + SigSpec data = sigmap(cell->getPort("\\DATA")); if (!addr.is_fully_const()) log_error("Non-constant address %s in memory initialization %s.\n", log_signal(addr), log_id(cell)); @@ -110,14 +112,14 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) continue; } - if (cell->type == ID($memwr)) + if (cell->type == "$memwr") { - SigSpec clk = sigmap(cell->getPort(ID::CLK)); - SigSpec clk_enable = SigSpec(cell->parameters[ID::CLK_ENABLE]); - SigSpec clk_polarity = SigSpec(cell->parameters[ID::CLK_POLARITY]); - SigSpec addr = sigmap(cell->getPort(ID::ADDR)); - SigSpec data = sigmap(cell->getPort(ID::DATA)); - SigSpec en = sigmap(cell->getPort(ID::EN)); + SigSpec clk = sigmap(cell->getPort("\\CLK")); + SigSpec clk_enable = SigSpec(cell->parameters["\\CLK_ENABLE"]); + SigSpec clk_polarity = SigSpec(cell->parameters["\\CLK_POLARITY"]); + SigSpec addr = sigmap(cell->getPort("\\ADDR")); + SigSpec data = sigmap(cell->getPort("\\DATA")); + SigSpec en = sigmap(cell->getPort("\\EN")); if (!en.is_fully_zero()) { @@ -140,15 +142,15 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) continue; } - if (cell->type == ID($memrd)) + if (cell->type == "$memrd") { - SigSpec clk = sigmap(cell->getPort(ID::CLK)); - SigSpec clk_enable = SigSpec(cell->parameters[ID::CLK_ENABLE]); - SigSpec clk_polarity = SigSpec(cell->parameters[ID::CLK_POLARITY]); - SigSpec transparent = SigSpec(cell->parameters[ID::TRANSPARENT]); - SigSpec addr = sigmap(cell->getPort(ID::ADDR)); - SigSpec data = sigmap(cell->getPort(ID::DATA)); - SigSpec en = sigmap(cell->getPort(ID::EN)); + SigSpec clk = sigmap(cell->getPort("\\CLK")); + SigSpec clk_enable = SigSpec(cell->parameters["\\CLK_ENABLE"]); + SigSpec clk_polarity = SigSpec(cell->parameters["\\CLK_POLARITY"]); + SigSpec transparent = SigSpec(cell->parameters["\\TRANSPARENT"]); + SigSpec addr = sigmap(cell->getPort("\\ADDR")); + SigSpec data = sigmap(cell->getPort("\\DATA")); + SigSpec en = sigmap(cell->getPort("\\EN")); if (!en.is_fully_zero()) { @@ -176,13 +178,13 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) std::stringstream sstr; sstr << "$mem$" << memory->name.str() << "$" << (autoidx++); - Cell *mem = module->addCell(sstr.str(), ID($mem)); - mem->parameters[ID::MEMID] = Const(memory->name.str()); - mem->parameters[ID::WIDTH] = Const(memory->width); - mem->parameters[ID::OFFSET] = Const(memory->start_offset); - mem->parameters[ID::SIZE] = Const(memory->size); - mem->parameters[ID::ABITS] = Const(addr_bits); - mem->parameters[ID::INIT] = init_data; + Cell *mem = module->addCell(sstr.str(), "$mem"); + mem->parameters["\\MEMID"] = Const(memory->name.str()); + mem->parameters["\\WIDTH"] = Const(memory->width); + mem->parameters["\\OFFSET"] = Const(memory->start_offset); + mem->parameters["\\SIZE"] = Const(memory->size); + mem->parameters["\\ABITS"] = Const(addr_bits); + mem->parameters["\\INIT"] = init_data; log_assert(sig_wr_clk.size() == wr_ports); log_assert(sig_wr_clk_enable.size() == wr_ports && sig_wr_clk_enable.is_fully_const()); @@ -191,14 +193,14 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) log_assert(sig_wr_data.size() == wr_ports * memory->width); log_assert(sig_wr_en.size() == wr_ports * memory->width); - mem->parameters[ID::WR_PORTS] = Const(wr_ports); - mem->parameters[ID::WR_CLK_ENABLE] = wr_ports ? sig_wr_clk_enable.as_const() : State::S0; - mem->parameters[ID::WR_CLK_POLARITY] = wr_ports ? sig_wr_clk_polarity.as_const() : State::S0; + mem->parameters["\\WR_PORTS"] = Const(wr_ports); + mem->parameters["\\WR_CLK_ENABLE"] = wr_ports ? sig_wr_clk_enable.as_const() : State::S0; + mem->parameters["\\WR_CLK_POLARITY"] = wr_ports ? sig_wr_clk_polarity.as_const() : State::S0; - mem->setPort(ID::WR_CLK, sig_wr_clk); - mem->setPort(ID::WR_ADDR, sig_wr_addr); - mem->setPort(ID::WR_DATA, sig_wr_data); - mem->setPort(ID::WR_EN, sig_wr_en); + mem->setPort("\\WR_CLK", sig_wr_clk); + mem->setPort("\\WR_ADDR", sig_wr_addr); + mem->setPort("\\WR_DATA", sig_wr_data); + mem->setPort("\\WR_EN", sig_wr_en); log_assert(sig_rd_clk.size() == rd_ports); log_assert(sig_rd_clk_enable.size() == rd_ports && sig_rd_clk_enable.is_fully_const()); @@ -206,15 +208,15 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) log_assert(sig_rd_addr.size() == rd_ports * addr_bits); log_assert(sig_rd_data.size() == rd_ports * memory->width); - mem->parameters[ID::RD_PORTS] = Const(rd_ports); - mem->parameters[ID::RD_CLK_ENABLE] = rd_ports ? sig_rd_clk_enable.as_const() : State::S0; - mem->parameters[ID::RD_CLK_POLARITY] = rd_ports ? sig_rd_clk_polarity.as_const() : State::S0; - mem->parameters[ID::RD_TRANSPARENT] = rd_ports ? sig_rd_transparent.as_const() : State::S0; + mem->parameters["\\RD_PORTS"] = Const(rd_ports); + mem->parameters["\\RD_CLK_ENABLE"] = rd_ports ? sig_rd_clk_enable.as_const() : State::S0; + mem->parameters["\\RD_CLK_POLARITY"] = rd_ports ? sig_rd_clk_polarity.as_const() : State::S0; + mem->parameters["\\RD_TRANSPARENT"] = rd_ports ? sig_rd_transparent.as_const() : State::S0; - mem->setPort(ID::RD_CLK, sig_rd_clk); - mem->setPort(ID::RD_ADDR, sig_rd_addr); - mem->setPort(ID::RD_DATA, sig_rd_data); - mem->setPort(ID::RD_EN, sig_rd_en); + mem->setPort("\\RD_CLK", sig_rd_clk); + mem->setPort("\\RD_ADDR", sig_rd_addr); + mem->setPort("\\RD_DATA", sig_rd_data); + mem->setPort("\\RD_EN", sig_rd_en); // Copy attributes from RTLIL memory to $mem for (auto attr : memory->attributes) @@ -245,7 +247,7 @@ static void handle_module(Design *design, Module *module) struct MemoryCollectPass : public Pass { MemoryCollectPass() : Pass("memory_collect", "creating multi-port memory cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -255,11 +257,12 @@ struct MemoryCollectPass : public Pass { log("memory cells.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override { + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing MEMORY_COLLECT pass (generating $mem cells).\n"); extra_args(args, 1, design); - for (auto module : design->selected_modules()) - handle_module(design, module); + for (auto &mod_it : design->modules_) + if (design->selected(mod_it.second)) + handle_module(design, mod_it.second); } } MemoryCollectPass; diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index 947cf7b3560..be4b3c1000a 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -39,10 +39,10 @@ struct MemoryDffWorker MemoryDffWorker(Module *module) : module(module), sigmap(module) { for (auto wire : module->wires()) { - if (wire->attributes.count(ID::init) == 0) + if (wire->attributes.count("\\init") == 0) continue; SigSpec sig = sigmap(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++) if (initval[i] == State::S0 || initval[i] == State::S1) init_bits.insert(sig[i]); @@ -66,8 +66,8 @@ struct MemoryDffWorker if (after && forward_merged_dffs.count(cell)) continue; - SigSpec this_clk = cell->getPort(ID::CLK); - bool this_clk_polarity = cell->parameters[ID::CLK_POLARITY].as_bool(); + SigSpec this_clk = cell->getPort("\\CLK"); + bool this_clk_polarity = cell->parameters["\\CLK_POLARITY"].as_bool(); if (invbits.count(this_clk)) { this_clk = invbits.at(this_clk); @@ -81,10 +81,10 @@ struct MemoryDffWorker continue; } - RTLIL::SigSpec q_norm = cell->getPort(after ? ID::D : ID::Q); + RTLIL::SigSpec q_norm = cell->getPort(after ? "\\D" : "\\Q"); sigmap.apply(q_norm); - RTLIL::SigSpec d = q_norm.extract(bit, &cell->getPort(after ? ID::Q : ID::D)); + RTLIL::SigSpec d = q_norm.extract(bit, &cell->getPort(after ? "\\Q" : "\\D")); if (d.size() != 1) continue; @@ -113,19 +113,19 @@ struct MemoryDffWorker bool clk_polarity = 0; candidate_dffs.clear(); - RTLIL::SigSpec sig_addr = cell->getPort(ID::ADDR); + RTLIL::SigSpec sig_addr = cell->getPort("\\ADDR"); if (!find_sig_before_dff(sig_addr, clk, clk_polarity)) { log("no (compatible) $dff for address input found.\n"); return; } - RTLIL::SigSpec sig_data = cell->getPort(ID::DATA); + RTLIL::SigSpec sig_data = cell->getPort("\\DATA"); if (!find_sig_before_dff(sig_data, clk, clk_polarity)) { log("no (compatible) $dff for data input found.\n"); return; } - RTLIL::SigSpec sig_en = cell->getPort(ID::EN); + RTLIL::SigSpec sig_en = cell->getPort("\\EN"); if (!find_sig_before_dff(sig_en, clk, clk_polarity)) { log("no (compatible) $dff for enable input found.\n"); return; @@ -136,12 +136,12 @@ struct MemoryDffWorker for (auto cell : candidate_dffs) forward_merged_dffs.insert(cell); - cell->setPort(ID::CLK, clk); - cell->setPort(ID::ADDR, sig_addr); - cell->setPort(ID::DATA, sig_data); - cell->setPort(ID::EN, sig_en); - cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1); - cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity); + cell->setPort("\\CLK", clk); + cell->setPort("\\ADDR", sig_addr); + cell->setPort("\\DATA", sig_data); + cell->setPort("\\EN", sig_en); + cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity); log("merged $dff to cell.\n"); return; @@ -161,10 +161,10 @@ struct MemoryDffWorker RTLIL::SigSpec new_sig = module->addWire(sstr.str(), sig.size()); for (auto cell : module->cells()) - if (cell->type == ID($dff)) { - RTLIL::SigSpec new_q = cell->getPort(ID::Q); + if (cell->type == "$dff") { + RTLIL::SigSpec new_q = cell->getPort("\\Q"); new_q.replace(sig, new_sig); - cell->setPort(ID::Q, new_q); + cell->setPort("\\Q", new_q); } } @@ -175,7 +175,7 @@ struct MemoryDffWorker bool clk_polarity = 0; RTLIL::SigSpec clk_data = RTLIL::SigSpec(RTLIL::State::Sx); - RTLIL::SigSpec sig_data = cell->getPort(ID::DATA); + RTLIL::SigSpec sig_data = cell->getPort("\\DATA"); for (auto bit : sigmap(sig_data)) if (sigbit_users_count[bit] > 1) @@ -189,9 +189,9 @@ struct MemoryDffWorker do { bool enable_invert = mux_cells_a.count(sig_data) != 0; Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data); - check_q.push_back(sigmap(mux->getPort(enable_invert ? ID::B : ID::A))); - sig_data = sigmap(mux->getPort(ID::Y)); - en.append(enable_invert ? module->LogicNot(NEW_ID, mux->getPort(ID::S)) : mux->getPort(ID::S)); + check_q.push_back(sigmap(mux->getPort(enable_invert ? "\\B" : "\\A"))); + sig_data = sigmap(mux->getPort("\\Y")); + en.append(enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S")); } while (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data)); for (auto bit : sig_data) @@ -202,12 +202,12 @@ struct MemoryDffWorker std::all_of(check_q.begin(), check_q.end(), [&](const SigSpec &cq) {return cq == sig_data; })) { disconnect_dff(sig_data); - cell->setPort(ID::CLK, clk_data); - cell->setPort(ID::EN, en.size() > 1 ? module->ReduceAnd(NEW_ID, en) : en); - cell->setPort(ID::DATA, sig_data); - cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1); - cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity); - cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0); + cell->setPort("\\CLK", clk_data); + cell->setPort("\\EN", en.size() > 1 ? module->ReduceAnd(NEW_ID, en) : en); + cell->setPort("\\DATA", sig_data); + cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity); + cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0); log("merged data $dff with rd enable to cell.\n"); return; } @@ -217,12 +217,12 @@ struct MemoryDffWorker if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx)) { disconnect_dff(sig_data); - cell->setPort(ID::CLK, clk_data); - cell->setPort(ID::EN, State::S1); - cell->setPort(ID::DATA, sig_data); - cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1); - cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity); - cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0); + cell->setPort("\\CLK", clk_data); + cell->setPort("\\EN", State::S1); + cell->setPort("\\DATA", sig_data); + cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity); + cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0); log("merged data $dff to cell.\n"); return; } @@ -230,16 +230,16 @@ struct MemoryDffWorker skip_ff_after_read_merging:; RTLIL::SigSpec clk_addr = RTLIL::SigSpec(RTLIL::State::Sx); - RTLIL::SigSpec sig_addr = cell->getPort(ID::ADDR); + RTLIL::SigSpec sig_addr = cell->getPort("\\ADDR"); if (find_sig_before_dff(sig_addr, clk_addr, clk_polarity) && clk_addr != RTLIL::SigSpec(RTLIL::State::Sx)) { - cell->setPort(ID::CLK, clk_addr); - cell->setPort(ID::EN, State::S1); - cell->setPort(ID::ADDR, sig_addr); - cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1); - cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity); - cell->parameters[ID::TRANSPARENT] = RTLIL::Const(1); + cell->setPort("\\CLK", clk_addr); + cell->setPort("\\EN", State::S1); + cell->setPort("\\ADDR", sig_addr); + cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity); + cell->parameters["\\TRANSPARENT"] = RTLIL::Const(1); log("merged address $dff to cell.\n"); return; } @@ -256,18 +256,18 @@ struct MemoryDffWorker } for (auto cell : module->cells()) { - if (cell->type == ID($dff)) + if (cell->type == "$dff") dff_cells.push_back(cell); - if (cell->type == ID($mux)) { - mux_cells_a[sigmap(cell->getPort(ID::A))] = cell; - mux_cells_b[sigmap(cell->getPort(ID::B))] = cell; + if (cell->type == "$mux") { + mux_cells_a[sigmap(cell->getPort("\\A"))] = cell; + mux_cells_b[sigmap(cell->getPort("\\B"))] = cell; } - if (cell->type.in(ID($not), ID($_NOT_)) || (cell->type == ID($logic_not) && GetSize(cell->getPort(ID::A)) == 1)) { - SigSpec sig_a = cell->getPort(ID::A); - SigSpec sig_y = cell->getPort(ID::Y); - if (cell->type == ID($not)) - sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID::A_SIGNED).as_bool()); - if (cell->type == ID($logic_not)) + if (cell->type.in("$not", "$_NOT_") || (cell->type == "$logic_not" && GetSize(cell->getPort("\\A")) == 1)) { + SigSpec sig_a = cell->getPort("\\A"); + SigSpec sig_y = cell->getPort("\\Y"); + if (cell->type == "$not") + sig_a.extend_u0(GetSize(sig_y), cell->getParam("\\A_SIGNED").as_bool()); + if (cell->type == "$logic_not") sig_y.extend_u0(1); for (int i = 0; i < GetSize(sig_y); i++) invbits[sig_y[i]] = sig_a[i]; @@ -279,19 +279,19 @@ struct MemoryDffWorker } for (auto cell : module->selected_cells()) - if (cell->type == ID($memwr) && !cell->parameters[ID::CLK_ENABLE].as_bool()) + if (cell->type == "$memwr" && !cell->parameters["\\CLK_ENABLE"].as_bool()) handle_wr_cell(cell); if (!flag_wr_only) for (auto cell : module->selected_cells()) - if (cell->type == ID($memrd) && !cell->parameters[ID::CLK_ENABLE].as_bool()) + if (cell->type == "$memrd" && !cell->parameters["\\CLK_ENABLE"].as_bool()) handle_rd_cell(cell); } }; struct MemoryDffPass : public Pass { MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memories") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -305,7 +305,7 @@ struct MemoryDffPass : public Pass { log(" do not merge registers on read ports\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_wr_only = false; diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index 80dd3957d96..65bccb5ef99 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -28,32 +28,11 @@ PRIVATE_NAMESPACE_BEGIN struct MemoryMapWorker { - bool attr_icase = false; - dict> attributes; - RTLIL::Design *design; RTLIL::Module *module; std::map, RTLIL::SigBit> decoder_cache; - MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module) {} - - std::string map_case(std::string value) const - { - if (attr_icase) { - for (char &c : value) - c = tolower(c); - } - return value; - } - - RTLIL::Const map_case(RTLIL::Const value) const - { - if (value.flags & RTLIL::CONST_FLAG_STRING) - return map_case(value.decode_string()); - return value; - } - std::string genid(RTLIL::IdString name, std::string token1 = "", int i = -1, std::string token2 = "", int j = -1, std::string token3 = "", int k = -1, std::string token4 = "") { std::stringstream sstr; @@ -102,15 +81,15 @@ struct MemoryMapWorker std::set static_ports; std::map static_cells_map; - int wr_ports = cell->parameters[ID::WR_PORTS].as_int(); - int rd_ports = cell->parameters[ID::RD_PORTS].as_int(); + int wr_ports = cell->parameters["\\WR_PORTS"].as_int(); + int rd_ports = cell->parameters["\\RD_PORTS"].as_int(); - int mem_size = cell->parameters[ID::SIZE].as_int(); - int mem_width = cell->parameters[ID::WIDTH].as_int(); - int mem_offset = cell->parameters[ID::OFFSET].as_int(); - int mem_abits = cell->parameters[ID::ABITS].as_int(); + int mem_size = cell->parameters["\\SIZE"].as_int(); + int mem_width = cell->parameters["\\WIDTH"].as_int(); + int mem_offset = cell->parameters["\\OFFSET"].as_int(); + int mem_abits = cell->parameters["\\ABITS"].as_int(); - SigSpec init_data = cell->getParam(ID::INIT); + SigSpec init_data = cell->getParam("\\INIT"); init_data.extend_u0(mem_size*mem_width, true); // delete unused memory cell @@ -119,53 +98,23 @@ struct MemoryMapWorker return; } - // check if attributes allow us to infer FFRAM for this cell - for (const auto &attr : attributes) { - if (cell->attributes.count(attr.first)) { - const auto &cell_attr = cell->attributes[attr.first]; - if (attr.second.empty()) { - log("Not mapping memory cell %s in module %s (attribute %s is set).\n", - cell->name.c_str(), module->name.c_str(), attr.first.c_str()); - return; - } - - bool found = false; - for (auto &value : attr.second) { - if (map_case(cell_attr) == map_case(value)) { - found = true; - break; - } - } - if (!found) { - if (cell_attr.flags & RTLIL::CONST_FLAG_STRING) { - log("Not mapping memory cell %s in module %s (attribute %s is set to \"%s\").\n", - cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.decode_string().c_str()); - } else { - log("Not mapping memory cell %s in module %s (attribute %s is set to %d).\n", - cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.as_int()); - } - return; - } - } - } - // all write ports must share the same clock - RTLIL::SigSpec clocks = cell->getPort(ID::WR_CLK); - RTLIL::Const clocks_pol = cell->parameters[ID::WR_CLK_POLARITY]; - RTLIL::Const clocks_en = cell->parameters[ID::WR_CLK_ENABLE]; + RTLIL::SigSpec clocks = cell->getPort("\\WR_CLK"); + RTLIL::Const clocks_pol = cell->parameters["\\WR_CLK_POLARITY"]; + RTLIL::Const clocks_en = cell->parameters["\\WR_CLK_ENABLE"]; clocks_pol.bits.resize(wr_ports); clocks_en.bits.resize(wr_ports); RTLIL::SigSpec refclock; RTLIL::State refclock_pol = RTLIL::State::Sx; for (int i = 0; i < clocks.size(); i++) { - RTLIL::SigSpec wr_en = cell->getPort(ID::WR_EN).extract(i * mem_width, mem_width); + RTLIL::SigSpec wr_en = cell->getPort("\\WR_EN").extract(i * mem_width, mem_width); if (wr_en.is_fully_const() && !wr_en.as_bool()) { static_ports.insert(i); continue; } if (clocks_en.bits[i] != RTLIL::State::S1) { - RTLIL::SigSpec wr_addr = cell->getPort(ID::WR_ADDR).extract(i*mem_abits, mem_abits); - RTLIL::SigSpec wr_data = cell->getPort(ID::WR_DATA).extract(i*mem_width, mem_width); + RTLIL::SigSpec wr_addr = cell->getPort("\\WR_ADDR").extract(i*mem_abits, mem_abits); + RTLIL::SigSpec wr_data = cell->getPort("\\WR_DATA").extract(i*mem_width, mem_width); if (wr_addr.is_fully_const()) { // FIXME: Actually we should check for wr_en.is_fully_const() also and // create a $adff cell with this ports wr_en input as reset pin when wr_en @@ -206,21 +155,21 @@ struct MemoryMapWorker } else { - RTLIL::Cell *c = module->addCell(genid(cell->name, "", i), ID($dff)); - c->parameters[ID::WIDTH] = cell->parameters[ID::WIDTH]; + RTLIL::Cell *c = module->addCell(genid(cell->name, "", i), "$dff"); + c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"]; if (clocks_pol.bits.size() > 0) { - c->parameters[ID::CLK_POLARITY] = RTLIL::Const(clocks_pol.bits[0]); - c->setPort(ID::CLK, clocks.extract(0, 1)); + c->parameters["\\CLK_POLARITY"] = RTLIL::Const(clocks_pol.bits[0]); + c->setPort("\\CLK", clocks.extract(0, 1)); } else { - c->parameters[ID::CLK_POLARITY] = RTLIL::Const(RTLIL::State::S1); - c->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::S0)); + c->parameters["\\CLK_POLARITY"] = RTLIL::Const(RTLIL::State::S1); + c->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::S0)); } RTLIL::Wire *w_in = module->addWire(genid(cell->name, "", i, "$d"), mem_width); data_reg_in.push_back(RTLIL::SigSpec(w_in)); - c->setPort(ID::D, data_reg_in.back()); + c->setPort("\\D", data_reg_in.back()); - std::string w_out_name = stringf("%s[%d]", cell->parameters[ID::MEMID].decode_string().c_str(), i); + std::string w_out_name = stringf("%s[%d]", cell->parameters["\\MEMID"].decode_string().c_str(), i); if (module->wires_.count(w_out_name) > 0) w_out_name = genid(cell->name, "", i, "$q"); @@ -228,10 +177,10 @@ struct MemoryMapWorker SigSpec w_init = init_data.extract(i*mem_width, mem_width); if (!w_init.is_fully_undef()) - w_out->attributes[ID::init] = w_init.as_const(); + w_out->attributes["\\init"] = w_init.as_const(); data_reg_out.push_back(RTLIL::SigSpec(w_out)); - c->setPort(ID::Q, data_reg_out.back()); + c->setPort("\\Q", data_reg_out.back()); } } @@ -239,55 +188,55 @@ struct MemoryMapWorker int count_dff = 0, count_mux = 0, count_wrmux = 0; - for (int i = 0; i < cell->parameters[ID::RD_PORTS].as_int(); i++) + for (int i = 0; i < cell->parameters["\\RD_PORTS"].as_int(); i++) { - RTLIL::SigSpec rd_addr = cell->getPort(ID::RD_ADDR).extract(i*mem_abits, mem_abits); + RTLIL::SigSpec rd_addr = cell->getPort("\\RD_ADDR").extract(i*mem_abits, mem_abits); if (mem_offset) rd_addr = module->Sub(NEW_ID, rd_addr, SigSpec(mem_offset, GetSize(rd_addr))); std::vector rd_signals; - rd_signals.push_back(cell->getPort(ID::RD_DATA).extract(i*mem_width, mem_width)); + rd_signals.push_back(cell->getPort("\\RD_DATA").extract(i*mem_width, mem_width)); - if (cell->parameters[ID::RD_CLK_ENABLE].bits[i] == RTLIL::State::S1) + if (cell->parameters["\\RD_CLK_ENABLE"].bits[i] == RTLIL::State::S1) { RTLIL::Cell *dff_cell = nullptr; - if (cell->parameters[ID::RD_TRANSPARENT].bits[i] == RTLIL::State::S1) + if (cell->parameters["\\RD_TRANSPARENT"].bits[i] == RTLIL::State::S1) { - dff_cell = module->addCell(genid(cell->name, "$rdreg", i), ID($dff)); - dff_cell->parameters[ID::WIDTH] = RTLIL::Const(mem_abits); - dff_cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(cell->parameters[ID::RD_CLK_POLARITY].bits[i]); - dff_cell->setPort(ID::CLK, cell->getPort(ID::RD_CLK).extract(i, 1)); - dff_cell->setPort(ID::D, rd_addr); + dff_cell = module->addCell(genid(cell->name, "$rdreg", i), "$dff"); + dff_cell->parameters["\\WIDTH"] = RTLIL::Const(mem_abits); + dff_cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); + dff_cell->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1)); + dff_cell->setPort("\\D", rd_addr); count_dff++; RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$q"), mem_abits); - dff_cell->setPort(ID::Q, RTLIL::SigSpec(w)); + dff_cell->setPort("\\Q", RTLIL::SigSpec(w)); rd_addr = RTLIL::SigSpec(w); } else { - dff_cell = module->addCell(genid(cell->name, "$rdreg", i), ID($dff)); - dff_cell->parameters[ID::WIDTH] = cell->parameters[ID::WIDTH]; - dff_cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(cell->parameters[ID::RD_CLK_POLARITY].bits[i]); - dff_cell->setPort(ID::CLK, cell->getPort(ID::RD_CLK).extract(i, 1)); - dff_cell->setPort(ID::Q, rd_signals.back()); + dff_cell = module->addCell(genid(cell->name, "$rdreg", i), "$dff"); + dff_cell->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"]; + dff_cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); + dff_cell->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1)); + dff_cell->setPort("\\Q", rd_signals.back()); count_dff++; RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$d"), mem_width); rd_signals.clear(); rd_signals.push_back(RTLIL::SigSpec(w)); - dff_cell->setPort(ID::D, rd_signals.back()); + dff_cell->setPort("\\D", rd_signals.back()); } - SigBit en_bit = cell->getPort(ID::RD_EN).extract(i); + SigBit en_bit = cell->getPort("\\RD_EN").extract(i); if (en_bit != State::S1) { SigSpec new_d = module->Mux(genid(cell->name, "$rdenmux", i), - dff_cell->getPort(ID::Q), dff_cell->getPort(ID::D), en_bit); - dff_cell->setPort(ID::D, new_d); + dff_cell->getPort("\\Q"), dff_cell->getPort("\\D"), en_bit); + dff_cell->setPort("\\D", new_d); } } @@ -297,17 +246,17 @@ struct MemoryMapWorker for (size_t k = 0; k < rd_signals.size(); k++) { - RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdmux", i, "", j, "", k), ID($mux)); - c->parameters[ID::WIDTH] = cell->parameters[ID::WIDTH]; - c->setPort(ID::Y, rd_signals[k]); - c->setPort(ID::S, rd_addr.extract(mem_abits-j-1, 1)); + RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdmux", i, "", j, "", k), "$mux"); + c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"]; + c->setPort("\\Y", rd_signals[k]); + c->setPort("\\S", rd_addr.extract(mem_abits-j-1, 1)); count_mux++; - c->setPort(ID::A, module->addWire(genid(cell->name, "$rdmux", i, "", j, "", k, "$a"), mem_width)); - c->setPort(ID::B, module->addWire(genid(cell->name, "$rdmux", i, "", j, "", k, "$b"), mem_width)); + c->setPort("\\A", module->addWire(genid(cell->name, "$rdmux", i, "", j, "", k, "$a"), mem_width)); + c->setPort("\\B", module->addWire(genid(cell->name, "$rdmux", i, "", j, "", k, "$b"), mem_width)); - next_rd_signals.push_back(c->getPort(ID::A)); - next_rd_signals.push_back(c->getPort(ID::B)); + next_rd_signals.push_back(c->getPort("\\A")); + next_rd_signals.push_back(c->getPort("\\B")); } next_rd_signals.swap(rd_signals); @@ -326,11 +275,11 @@ struct MemoryMapWorker RTLIL::SigSpec sig = data_reg_out[i]; - for (int j = 0; j < cell->parameters[ID::WR_PORTS].as_int(); j++) + for (int j = 0; j < cell->parameters["\\WR_PORTS"].as_int(); j++) { - RTLIL::SigSpec wr_addr = cell->getPort(ID::WR_ADDR).extract(j*mem_abits, mem_abits); - RTLIL::SigSpec wr_data = cell->getPort(ID::WR_DATA).extract(j*mem_width, mem_width); - RTLIL::SigSpec wr_en = cell->getPort(ID::WR_EN).extract(j*mem_width, mem_width); + RTLIL::SigSpec wr_addr = cell->getPort("\\WR_ADDR").extract(j*mem_abits, mem_abits); + RTLIL::SigSpec wr_data = cell->getPort("\\WR_DATA").extract(j*mem_width, mem_width); + RTLIL::SigSpec wr_en = cell->getPort("\\WR_EN").extract(j*mem_width, mem_width); if (mem_offset) wr_addr = module->Sub(NEW_ID, wr_addr, SigSpec(mem_offset, GetSize(wr_addr))); @@ -354,27 +303,27 @@ struct MemoryMapWorker if (wr_bit != State::S1) { - RTLIL::Cell *c = module->addCell(genid(cell->name, "$wren", i, "", j, "", wr_offset), ID($and)); - c->parameters[ID::A_SIGNED] = RTLIL::Const(0); - c->parameters[ID::B_SIGNED] = RTLIL::Const(0); - c->parameters[ID::A_WIDTH] = RTLIL::Const(1); - c->parameters[ID::B_WIDTH] = RTLIL::Const(1); - c->parameters[ID::Y_WIDTH] = RTLIL::Const(1); - c->setPort(ID::A, w); - c->setPort(ID::B, wr_bit); + RTLIL::Cell *c = module->addCell(genid(cell->name, "$wren", i, "", j, "", wr_offset), "$and"); + c->parameters["\\A_SIGNED"] = RTLIL::Const(0); + c->parameters["\\B_SIGNED"] = RTLIL::Const(0); + c->parameters["\\A_WIDTH"] = RTLIL::Const(1); + c->parameters["\\B_WIDTH"] = RTLIL::Const(1); + c->parameters["\\Y_WIDTH"] = RTLIL::Const(1); + c->setPort("\\A", w); + c->setPort("\\B", wr_bit); w = module->addWire(genid(cell->name, "$wren", i, "", j, "", wr_offset, "$y")); - c->setPort(ID::Y, RTLIL::SigSpec(w)); + c->setPort("\\Y", RTLIL::SigSpec(w)); } - RTLIL::Cell *c = module->addCell(genid(cell->name, "$wrmux", i, "", j, "", wr_offset), ID($mux)); - c->parameters[ID::WIDTH] = wr_width; - c->setPort(ID::A, sig.extract(wr_offset, wr_width)); - c->setPort(ID::B, wr_data.extract(wr_offset, wr_width)); - c->setPort(ID::S, RTLIL::SigSpec(w)); + RTLIL::Cell *c = module->addCell(genid(cell->name, "$wrmux", i, "", j, "", wr_offset), "$mux"); + c->parameters["\\WIDTH"] = wr_width; + c->setPort("\\A", sig.extract(wr_offset, wr_width)); + c->setPort("\\B", wr_data.extract(wr_offset, wr_width)); + c->setPort("\\S", RTLIL::SigSpec(w)); w = module->addWire(genid(cell->name, "$wrmux", i, "", j, "", wr_offset, "$y"), wr_width); - c->setPort(ID::Y, w); + c->setPort("\\Y", w); sig.replace(wr_offset, w); wr_offset += wr_width; @@ -390,11 +339,11 @@ struct MemoryMapWorker module->remove(cell); } - void run() + MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module) { std::vector cells; for (auto cell : module->selected_cells()) - if (cell->type == ID($mem)) + if (cell->type == "$mem" && design->selected(module, cell)) cells.push_back(cell); for (auto cell : cells) handle_cell(cell); @@ -403,77 +352,21 @@ struct MemoryMapWorker struct MemoryMapPass : public Pass { MemoryMapPass() : Pass("memory_map", "translate multiport memories to basic cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" memory_map [options] [selection]\n"); + log(" memory_map [selection]\n"); log("\n"); log("This pass converts multiport memory cells as generated by the memory_collect\n"); log("pass to word-wide DFFs and address decoders.\n"); log("\n"); - log(" -attr !\n"); - log(" do not map memories that have attribute set.\n"); - log("\n"); - log(" -attr [=]\n"); - log(" for memories that have attribute set, only map them if its value\n"); - log(" is a string (if specified), or an integer 1 (otherwise). if this\n"); - log(" option is specified multiple times, map the memory if the attribute is\n"); - log(" to any of the values.\n"); - log("\n"); - log(" -iattr\n"); - log(" for -attr, ignore case of .\n"); - log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override - { - bool attr_icase = false; - dict> attributes; - + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-attr" && argidx + 1 < args.size()) - { - std::string attr_arg = args[++argidx]; - std::string name; - RTLIL::Const value; - size_t eq_at = attr_arg.find('='); - if (eq_at != std::string::npos) { - name = attr_arg.substr(0, eq_at); - value = attr_arg.substr(eq_at + 1); - } else { - name = attr_arg; - value = RTLIL::Const(1); - } - if (attr_arg.size() > 1 && attr_arg[0] == '!') { - if (value != RTLIL::Const(1)) { - --argidx; - break; // we don't support -attr != - } - attributes[RTLIL::escape_id(name.substr(1))].clear(); - } else { - attributes[RTLIL::escape_id(name)].push_back(value); - } - continue; - } - if (args[argidx] == "-iattr") - { - attr_icase = true; - continue; - } - break; - } - extra_args(args, argidx, design); - - for (auto mod : design->selected_modules()) { - MemoryMapWorker worker(design, mod); - worker.attr_icase = attr_icase; - worker.attributes = attributes; - worker.run(); - } + extra_args(args, 1, design); + for (auto mod : design->selected_modules()) + MemoryMapWorker(design, mod); } } MemoryMapPass; diff --git a/passes/memory/memory_memx.cc b/passes/memory/memory_memx.cc index 02e00cf3031..9583701645a 100644 --- a/passes/memory/memory_memx.cc +++ b/passes/memory/memory_memx.cc @@ -28,7 +28,7 @@ PRIVATE_NAMESPACE_BEGIN struct MemoryMemxPass : public Pass { MemoryMemxPass() : Pass("memory_memx", "emulate vlog sim behavior for mem ports") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -38,7 +38,7 @@ struct MemoryMemxPass : public Pass { log("behavior for out-of-bounds memory reads and writes.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override { + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing MEMORY_MEMX pass (converting $mem cells to logic and flip-flops).\n"); extra_args(args, 1, design); @@ -47,18 +47,18 @@ struct MemoryMemxPass : public Pass { vector mem_port_cells; for (auto cell : module->selected_cells()) - if (cell->type.in(ID($memrd), ID($memwr))) + if (cell->type.in("$memrd", "$memwr")) mem_port_cells.push_back(cell); for (auto cell : mem_port_cells) { - IdString memid = cell->getParam(ID::MEMID).decode_string(); + IdString memid = cell->getParam("\\MEMID").decode_string(); RTLIL::Memory *mem = module->memories.at(memid); int lowest_addr = mem->start_offset; int highest_addr = mem->start_offset + mem->size - 1; - SigSpec addr = cell->getPort(ID::ADDR); + SigSpec addr = cell->getPort("\\ADDR"); addr.extend_u0(32); SigSpec addr_ok = module->Nex(NEW_ID, module->ReduceXor(NEW_ID, addr), module->ReduceXor(NEW_ID, {addr, State::S1})); @@ -66,23 +66,23 @@ struct MemoryMemxPass : public Pass { addr_ok = module->LogicAnd(NEW_ID, addr_ok, module->Ge(NEW_ID, addr, lowest_addr)); addr_ok = module->LogicAnd(NEW_ID, addr_ok, module->Le(NEW_ID, addr, highest_addr)); - if (cell->type == ID($memrd)) + if (cell->type == "$memrd") { - if (cell->getParam(ID::CLK_ENABLE).as_bool()) + if (cell->getParam("\\CLK_ENABLE").as_bool()) log_error("Cell %s.%s (%s) has an enabled clock. Clocked $memrd cells are not supported by memory_memx!\n", log_id(module), log_id(cell), log_id(cell->type)); - SigSpec rdata = cell->getPort(ID::DATA); + SigSpec rdata = cell->getPort("\\DATA"); Wire *raw_rdata = module->addWire(NEW_ID, GetSize(rdata)); module->addMux(NEW_ID, SigSpec(State::Sx, GetSize(rdata)), raw_rdata, addr_ok, rdata); - cell->setPort(ID::DATA, raw_rdata); + cell->setPort("\\DATA", raw_rdata); } - if (cell->type == ID($memwr)) + if (cell->type == "$memwr") { - SigSpec en = cell->getPort(ID::EN); + SigSpec en = cell->getPort("\\EN"); en = module->And(NEW_ID, en, addr_ok.repeat(GetSize(en))); - cell->setPort(ID::EN, en); + cell->setPort("\\EN", en); } } } diff --git a/passes/memory/memory_nordff.cc b/passes/memory/memory_nordff.cc index 07bbd9fe830..ba0361c0f61 100644 --- a/passes/memory/memory_nordff.cc +++ b/passes/memory/memory_nordff.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct MemoryNordffPass : public Pass { MemoryNordffPass() : Pass("memory_nordff", "extract read port FFs from memories") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -35,7 +35,7 @@ struct MemoryNordffPass : public Pass { log("similar to what one would get from calling memory_dff with -nordff.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing MEMORY_NORDFF pass (extracting $dff cells from $mem).\n"); @@ -52,19 +52,19 @@ struct MemoryNordffPass : public Pass { for (auto module : design->selected_modules()) for (auto cell : vector(module->selected_cells())) { - if (cell->type != ID($mem)) + if (cell->type != "$mem") continue; - int rd_ports = cell->getParam(ID::RD_PORTS).as_int(); - int abits = cell->getParam(ID::ABITS).as_int(); - int width = cell->getParam(ID::WIDTH).as_int(); + int rd_ports = cell->getParam("\\RD_PORTS").as_int(); + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); - SigSpec rd_addr = cell->getPort(ID::RD_ADDR); - SigSpec rd_data = cell->getPort(ID::RD_DATA); - SigSpec rd_clk = cell->getPort(ID::RD_CLK); - SigSpec rd_en = cell->getPort(ID::RD_EN); - Const rd_clk_enable = cell->getParam(ID::RD_CLK_ENABLE); - Const rd_clk_polarity = cell->getParam(ID::RD_CLK_POLARITY); + SigSpec rd_addr = cell->getPort("\\RD_ADDR"); + SigSpec rd_data = cell->getPort("\\RD_DATA"); + SigSpec rd_clk = cell->getPort("\\RD_CLK"); + SigSpec rd_en = cell->getPort("\\RD_EN"); + Const rd_clk_enable = cell->getParam("\\RD_CLK_ENABLE"); + Const rd_clk_polarity = cell->getParam("\\RD_CLK_POLARITY"); for (int i = 0; i < rd_ports; i++) { @@ -72,11 +72,11 @@ struct MemoryNordffPass : public Pass { if (clk_enable) { - bool clk_polarity = cell->getParam(ID::RD_CLK_POLARITY)[i] == State::S1; - bool transparent = cell->getParam(ID::RD_TRANSPARENT)[i] == State::S1; + bool clk_polarity = cell->getParam("\\RD_CLK_POLARITY")[i] == State::S1; + bool transparent = cell->getParam("\\RD_TRANSPARENT")[i] == State::S1; - SigSpec clk = cell->getPort(ID::RD_CLK)[i] ; - SigSpec en = cell->getPort(ID::RD_EN)[i]; + SigSpec clk = cell->getPort("\\RD_CLK")[i] ; + SigSpec en = cell->getPort("\\RD_EN")[i]; Cell *c; if (transparent) @@ -108,12 +108,12 @@ struct MemoryNordffPass : public Pass { rd_clk_polarity[i] = State::S1; } - cell->setPort(ID::RD_ADDR, rd_addr); - cell->setPort(ID::RD_DATA, rd_data); - cell->setPort(ID::RD_CLK, rd_clk); - cell->setPort(ID::RD_EN, rd_en); - cell->setParam(ID::RD_CLK_ENABLE, rd_clk_enable); - cell->setParam(ID::RD_CLK_POLARITY, rd_clk_polarity); + cell->setPort("\\RD_ADDR", rd_addr); + cell->setPort("\\RD_DATA", rd_data); + cell->setPort("\\RD_CLK", rd_clk); + cell->setPort("\\RD_EN", rd_en); + cell->setParam("\\RD_CLK_ENABLE", rd_clk_enable); + cell->setParam("\\RD_CLK_POLARITY", rd_clk_polarity); } } } MemoryNordffPass; diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc index 7315aeae10d..eb912cfd44e 100644 --- a/passes/memory/memory_share.cc +++ b/passes/memory/memory_share.cc @@ -27,11 +27,11 @@ PRIVATE_NAMESPACE_BEGIN bool memcells_cmp(RTLIL::Cell *a, RTLIL::Cell *b) { - if (a->type == ID($memrd) && b->type == ID($memrd)) + if (a->type == "$memrd" && b->type == "$memrd") return a->name < b->name; - if (a->type == ID($memrd) || b->type == ID($memrd)) - return (a->type == ID($memrd)) < (b->type == ID($memrd)); - return a->parameters.at(ID::PRIORITY).as_int() < b->parameters.at(ID::PRIORITY).as_int(); + if (a->type == "$memrd" || b->type == "$memrd") + return (a->type == "$memrd") < (b->type == "$memrd"); + return a->parameters.at("\\PRIORITY").as_int() < b->parameters.at("\\PRIORITY").as_int(); } struct MemoryShareWorker @@ -64,18 +64,18 @@ struct MemoryShareWorker RTLIL::Cell *cell = sig_to_mux.at(sig).first; int bit_idx = sig_to_mux.at(sig).second; - std::vector sig_a = sigmap(cell->getPort(ID::A)); - std::vector sig_b = sigmap(cell->getPort(ID::B)); - std::vector sig_s = sigmap(cell->getPort(ID::S)); - std::vector sig_y = sigmap(cell->getPort(ID::Y)); + std::vector sig_a = sigmap(cell->getPort("\\A")); + std::vector sig_b = sigmap(cell->getPort("\\B")); + std::vector sig_s = sigmap(cell->getPort("\\S")); + std::vector sig_y = sigmap(cell->getPort("\\Y")); log_assert(sig_y.at(bit_idx) == sig); for (int i = 0; i < int(sig_s.size()); i++) if (state.count(sig_s[i]) && state.at(sig_s[i]) == true) { if (find_data_feedback(async_rd_bits, sig_b.at(bit_idx + i*sig_y.size()), state, conditions)) { - RTLIL::SigSpec new_b = cell->getPort(ID::B); + RTLIL::SigSpec new_b = cell->getPort("\\B"); new_b.replace(bit_idx + i*sig_y.size(), RTLIL::State::Sx); - cell->setPort(ID::B, new_b); + cell->setPort("\\B", new_b); } return false; } @@ -90,9 +90,9 @@ struct MemoryShareWorker new_state[sig_s[i]] = true; if (find_data_feedback(async_rd_bits, sig_b.at(bit_idx + i*sig_y.size()), new_state, conditions)) { - RTLIL::SigSpec new_b = cell->getPort(ID::B); + RTLIL::SigSpec new_b = cell->getPort("\\B"); new_b.replace(bit_idx + i*sig_y.size(), RTLIL::State::Sx); - cell->setPort(ID::B, new_b); + cell->setPort("\\B", new_b); } } @@ -101,9 +101,9 @@ struct MemoryShareWorker new_state[sig_s[i]] = false; if (find_data_feedback(async_rd_bits, sig_a.at(bit_idx), new_state, conditions)) { - RTLIL::SigSpec new_a = cell->getPort(ID::A); + RTLIL::SigSpec new_a = cell->getPort("\\A"); new_a.replace(bit_idx, RTLIL::State::Sx); - cell->setPort(ID::A, new_a); + cell->setPort("\\A", new_a); } return false; @@ -120,8 +120,8 @@ struct MemoryShareWorker for (auto &cond : conditions) { RTLIL::SigSpec sig1, sig2; for (auto &it : cond) { - sig1.append(it.first); - sig2.append(it.second ? RTLIL::State::S1 : RTLIL::State::S0); + sig1.append_bit(it.first); + sig2.append_bit(it.second ? RTLIL::State::S1 : RTLIL::State::S0); } terms.append(module->Ne(NEW_ID, sig1, sig2)); created_conditions++; @@ -155,12 +155,12 @@ struct MemoryShareWorker { bool ignore_data_port = false; - if (cell->type.in(ID($mux), ID($pmux))) + if (cell->type.in("$mux", "$pmux")) { - std::vector sig_a = sigmap(cell->getPort(ID::A)); - std::vector sig_b = sigmap(cell->getPort(ID::B)); - std::vector sig_s = sigmap(cell->getPort(ID::S)); - std::vector sig_y = sigmap(cell->getPort(ID::Y)); + std::vector sig_a = sigmap(cell->getPort("\\A")); + std::vector sig_b = sigmap(cell->getPort("\\B")); + std::vector sig_s = sigmap(cell->getPort("\\S")); + std::vector sig_y = sigmap(cell->getPort("\\Y")); non_feedback_nets.insert(sig_s.begin(), sig_s.end()); @@ -173,13 +173,13 @@ struct MemoryShareWorker continue; } - if (cell->type.in(ID($memwr), ID($memrd)) && - cell->parameters.at(ID::MEMID).decode_string() == memid) + if (cell->type.in("$memwr", "$memrd") && + cell->parameters.at("\\MEMID").decode_string() == memid) ignore_data_port = true; for (auto conn : cell->connections()) { - if (ignore_data_port && conn.first == ID::DATA) + if (ignore_data_port && conn.first == "\\DATA") continue; std::vector bits = sigmap(conn.second); non_feedback_nets.insert(bits.begin(), bits.end()); @@ -204,11 +204,11 @@ struct MemoryShareWorker for (auto cell : rd_ports) { - if (cell->parameters.at(ID::CLK_ENABLE).as_bool()) + if (cell->parameters.at("\\CLK_ENABLE").as_bool()) continue; - RTLIL::SigSpec sig_addr = sigmap(cell->getPort(ID::ADDR)); - std::vector sig_data = sigmap(cell->getPort(ID::DATA)); + RTLIL::SigSpec sig_addr = sigmap(cell->getPort("\\ADDR")); + std::vector sig_data = sigmap(cell->getPort("\\DATA")); for (int i = 0; i < int(sig_data.size()); i++) if (non_feedback_nets.count(sig_data[i])) @@ -228,14 +228,14 @@ struct MemoryShareWorker for (auto cell : wr_ports) { - RTLIL::SigSpec sig_addr = sigmap_xmux(cell->getPort(ID::ADDR)); + RTLIL::SigSpec sig_addr = sigmap_xmux(cell->getPort("\\ADDR")); if (!async_rd_bits.count(sig_addr)) continue; log(" Analyzing write port %s.\n", log_id(cell)); - std::vector cell_data = cell->getPort(ID::DATA); - std::vector cell_en = cell->getPort(ID::EN); + std::vector cell_data = cell->getPort("\\DATA"); + std::vector cell_en = cell->getPort("\\EN"); int created_conditions = 0; for (int i = 0; i < int(cell_data.size()); i++) @@ -250,7 +250,7 @@ struct MemoryShareWorker if (created_conditions) { log(" Added enable logic for %d different cases.\n", created_conditions); - cell->setPort(ID::EN, cell_en); + cell->setPort("\\EN", cell_en); } } } @@ -284,8 +284,8 @@ struct MemoryShareWorker std::pair key(v_bits[i], v_mask_bits[i]); if (groups.count(key) == 0) { groups[key].first = grouped_bits.size(); - grouped_bits.append(v_bits[i]); - grouped_mask_bits.append(v_mask_bits[i]); + grouped_bits.append_bit(v_bits[i]); + grouped_mask_bits.append_bit(v_mask_bits[i]); } groups[key].second.push_back(i); } @@ -295,7 +295,7 @@ struct MemoryShareWorker for (int i = 0; i < bits.size(); i++) { std::pair key(v_bits[i], v_mask_bits[i]); - result.append(grouped_result.at(groups.at(key).first)); + result.append_bit(grouped_result.at(groups.at(key).first)); } return result; @@ -326,7 +326,7 @@ struct MemoryShareWorker for (int i = 0; i < int(v_old_en.size()); i++) { std::pair key(v_old_en[i], v_next_en[i]); - new_merged_en.append(grouped_new_en.at(groups.at(key))); + new_merged_en.append_bit(grouped_new_en.at(groups.at(key))); } // Create the new merged_data signal. @@ -368,15 +368,15 @@ struct MemoryShareWorker for (int i = 0; i < int(wr_ports.size()); i++) { RTLIL::Cell *cell = wr_ports.at(i); - RTLIL::SigSpec addr = sigmap_xmux(cell->getPort(ID::ADDR)); + RTLIL::SigSpec addr = sigmap_xmux(cell->getPort("\\ADDR")); - if (cell->parameters.at(ID::CLK_ENABLE).as_bool() != cache_clk_enable || - (cache_clk_enable && (sigmap(cell->getPort(ID::CLK)) != cache_clk || - cell->parameters.at(ID::CLK_POLARITY).as_bool() != cache_clk_polarity))) + if (cell->parameters.at("\\CLK_ENABLE").as_bool() != cache_clk_enable || + (cache_clk_enable && (sigmap(cell->getPort("\\CLK")) != cache_clk || + cell->parameters.at("\\CLK_POLARITY").as_bool() != cache_clk_polarity))) { - cache_clk_enable = cell->parameters.at(ID::CLK_ENABLE).as_bool(); - cache_clk_polarity = cell->parameters.at(ID::CLK_POLARITY).as_bool(); - cache_clk = sigmap(cell->getPort(ID::CLK)); + cache_clk_enable = cell->parameters.at("\\CLK_ENABLE").as_bool(); + cache_clk_polarity = cell->parameters.at("\\CLK_POLARITY").as_bool(); + cache_clk = sigmap(cell->getPort("\\CLK")); last_port_by_addr.clear(); if (cache_clk_enable) @@ -388,7 +388,7 @@ struct MemoryShareWorker log(" Port %d (%s) has addr %s.\n", i, log_id(cell), log_signal(addr)); log(" Active bits: "); - std::vector en_bits = sigmap(cell->getPort(ID::EN)); + std::vector en_bits = sigmap(cell->getPort("\\EN")); active_bits_on_port.push_back(std::vector(en_bits.size())); for (int k = int(en_bits.size())-1; k >= 0; k--) { active_bits_on_port[i][k] = en_bits[k].wire != NULL || en_bits[k].data != RTLIL::State::S0; @@ -410,13 +410,13 @@ struct MemoryShareWorker // Force this ports addr input to addr directly (skip don't care muxes) - cell->setPort(ID::ADDR, addr); + cell->setPort("\\ADDR", addr); // If any of the ports between `last_i' and `i' write to the same address, this // will have priority over whatever `last_i` wrote. So we need to revisit those // ports and mask the EN bits accordingly. - RTLIL::SigSpec merged_en = sigmap(wr_ports[last_i]->getPort(ID::EN)); + RTLIL::SigSpec merged_en = sigmap(wr_ports[last_i]->getPort("\\EN")); for (int j = last_i+1; j < i; j++) { @@ -431,20 +431,20 @@ struct MemoryShareWorker found_overlapping_bits_i_j: log(" Creating collosion-detect logic for port %d.\n", j); RTLIL::SigSpec is_same_addr = module->addWire(NEW_ID); - module->addEq(NEW_ID, addr, wr_ports[j]->getPort(ID::ADDR), is_same_addr); - merged_en = mask_en_grouped(is_same_addr, merged_en, sigmap(wr_ports[j]->getPort(ID::EN))); + module->addEq(NEW_ID, addr, wr_ports[j]->getPort("\\ADDR"), is_same_addr); + merged_en = mask_en_grouped(is_same_addr, merged_en, sigmap(wr_ports[j]->getPort("\\EN"))); } } // Then we need to merge the (masked) EN and the DATA signals. - RTLIL::SigSpec merged_data = wr_ports[last_i]->getPort(ID::DATA); + RTLIL::SigSpec merged_data = wr_ports[last_i]->getPort("\\DATA"); if (found_overlapping_bits) { log(" Creating logic for merging DATA and EN ports.\n"); - merge_en_data(merged_en, merged_data, sigmap(cell->getPort(ID::EN)), sigmap(cell->getPort(ID::DATA))); + merge_en_data(merged_en, merged_data, sigmap(cell->getPort("\\EN")), sigmap(cell->getPort("\\DATA"))); } else { - RTLIL::SigSpec cell_en = sigmap(cell->getPort(ID::EN)); - RTLIL::SigSpec cell_data = sigmap(cell->getPort(ID::DATA)); + RTLIL::SigSpec cell_en = sigmap(cell->getPort("\\EN")); + RTLIL::SigSpec cell_data = sigmap(cell->getPort("\\DATA")); for (int k = 0; k < int(en_bits.size()); k++) if (!active_bits_on_port[last_i][k]) { merged_en.replace(k, cell_en.extract(k, 1)); @@ -454,14 +454,14 @@ struct MemoryShareWorker // Connect the new EN and DATA signals and remove the old write port. - cell->setPort(ID::EN, merged_en); - cell->setPort(ID::DATA, merged_data); + cell->setPort("\\EN", merged_en); + cell->setPort("\\DATA", merged_data); module->remove(wr_ports[last_i]); wr_ports[last_i] = NULL; log(" Active bits: "); - std::vector en_bits = sigmap(cell->getPort(ID::EN)); + std::vector en_bits = sigmap(cell->getPort("\\EN")); active_bits_on_port.push_back(std::vector(en_bits.size())); for (int k = int(en_bits.size())-1; k >= 0; k--) log("%c", active_bits_on_port[i][k] ? '1' : '0'); @@ -500,7 +500,7 @@ struct MemoryShareWorker std::set considered_port_pairs; for (int i = 0; i < int(wr_ports.size()); i++) { - std::vector bits = modwalker.sigmap(wr_ports[i]->getPort(ID::EN)); + std::vector bits = modwalker.sigmap(wr_ports[i]->getPort("\\EN")); for (auto bit : bits) if (bit == RTLIL::State::S1) goto port_is_always_active; @@ -519,13 +519,13 @@ struct MemoryShareWorker { RTLIL::Cell *cell = wr_ports.at(i); - if (cell->parameters.at(ID::CLK_ENABLE).as_bool() != cache_clk_enable || - (cache_clk_enable && (sigmap(cell->getPort(ID::CLK)) != cache_clk || - cell->parameters.at(ID::CLK_POLARITY).as_bool() != cache_clk_polarity))) + if (cell->parameters.at("\\CLK_ENABLE").as_bool() != cache_clk_enable || + (cache_clk_enable && (sigmap(cell->getPort("\\CLK")) != cache_clk || + cell->parameters.at("\\CLK_POLARITY").as_bool() != cache_clk_polarity))) { - cache_clk_enable = cell->parameters.at(ID::CLK_ENABLE).as_bool(); - cache_clk_polarity = cell->parameters.at(ID::CLK_POLARITY).as_bool(); - cache_clk = sigmap(cell->getPort(ID::CLK)); + cache_clk_enable = cell->parameters.at("\\CLK_ENABLE").as_bool(); + cache_clk_polarity = cell->parameters.at("\\CLK_POLARITY").as_bool(); + cache_clk = sigmap(cell->getPort("\\CLK")); } else if (i > 0 && considered_ports.count(i-1) && considered_ports.count(i)) considered_port_pairs.insert(i); @@ -554,7 +554,7 @@ struct MemoryShareWorker for (int i = 0; i < int(wr_ports.size()); i++) if (considered_port_pairs.count(i) || considered_port_pairs.count(i+1)) { - RTLIL::SigSpec sig = modwalker.sigmap(wr_ports[i]->getPort(ID::EN)); + RTLIL::SigSpec sig = modwalker.sigmap(wr_ports[i]->getPort("\\EN")); port_to_sat_variable[i] = ez->expression(ez->OpOr, satgen.importSigSpec(sig)); std::vector bits = sig; @@ -564,7 +564,7 @@ struct MemoryShareWorker while (!bits_queue.empty()) { for (auto bit : bits_queue) - if (bit.wire && bit.wire->get_bool_attribute(ID::onehot)) + if (bit.wire && bit.wire->get_bool_attribute("\\onehot")) one_hot_wires.insert(bit.wire); pool portbits; @@ -609,13 +609,13 @@ struct MemoryShareWorker log(" Merging port %d into port %d.\n", i-1, i); port_to_sat_variable.at(i) = ez->OR(port_to_sat_variable.at(i-1), port_to_sat_variable.at(i)); - RTLIL::SigSpec last_addr = wr_ports[i-1]->getPort(ID::ADDR); - RTLIL::SigSpec last_data = wr_ports[i-1]->getPort(ID::DATA); - std::vector last_en = modwalker.sigmap(wr_ports[i-1]->getPort(ID::EN)); + RTLIL::SigSpec last_addr = wr_ports[i-1]->getPort("\\ADDR"); + RTLIL::SigSpec last_data = wr_ports[i-1]->getPort("\\DATA"); + std::vector last_en = modwalker.sigmap(wr_ports[i-1]->getPort("\\EN")); - RTLIL::SigSpec this_addr = wr_ports[i]->getPort(ID::ADDR); - RTLIL::SigSpec this_data = wr_ports[i]->getPort(ID::DATA); - std::vector this_en = modwalker.sigmap(wr_ports[i]->getPort(ID::EN)); + RTLIL::SigSpec this_addr = wr_ports[i]->getPort("\\ADDR"); + RTLIL::SigSpec this_data = wr_ports[i]->getPort("\\DATA"); + std::vector this_en = modwalker.sigmap(wr_ports[i]->getPort("\\EN")); RTLIL::SigBit this_en_active = module->ReduceOr(NEW_ID, this_en); @@ -624,9 +624,9 @@ struct MemoryShareWorker else this_addr.extend_u0(GetSize(last_addr)); - wr_ports[i]->setParam(ID::ABITS, GetSize(this_addr)); - wr_ports[i]->setPort(ID::ADDR, module->Mux(NEW_ID, last_addr, this_addr, this_en_active)); - wr_ports[i]->setPort(ID::DATA, module->Mux(NEW_ID, last_data, this_data, this_en_active)); + wr_ports[i]->setParam("\\ABITS", GetSize(this_addr)); + wr_ports[i]->setPort("\\ADDR", module->Mux(NEW_ID, last_addr, this_addr, this_en_active)); + wr_ports[i]->setPort("\\DATA", module->Mux(NEW_ID, last_data, this_data, this_en_active)); std::map, int> groups_en; RTLIL::SigSpec grouped_last_en, grouped_this_en, en; @@ -635,8 +635,8 @@ struct MemoryShareWorker for (int j = 0; j < int(this_en.size()); j++) { std::pair key(last_en[j], this_en[j]); if (!groups_en.count(key)) { - grouped_last_en.append(last_en[j]); - grouped_this_en.append(this_en[j]); + grouped_last_en.append_bit(last_en[j]); + grouped_this_en.append_bit(this_en[j]); groups_en[key] = grouped_en->width; grouped_en->width++; } @@ -644,7 +644,7 @@ struct MemoryShareWorker } module->addMux(NEW_ID, grouped_last_en, grouped_this_en, this_en_active, grouped_en); - wr_ports[i]->setPort(ID::EN, en); + wr_ports[i]->setPort("\\EN", en); module->remove(wr_ports[i-1]); wr_ports[i-1] = NULL; @@ -665,40 +665,34 @@ struct MemoryShareWorker // Setup and run // ------------- - MemoryShareWorker(RTLIL::Design *design) : design(design), modwalker(design) {} - - void operator()(RTLIL::Module* module) + MemoryShareWorker(RTLIL::Design *design, RTLIL::Module *module) : + design(design), module(module), sigmap(module) { std::map, std::vector>> memindex; - this->module = module; - sigmap.set(module); - sig_to_mux.clear(); - conditions_logic_cache.clear(); - sigmap_xmux = sigmap; for (auto cell : module->cells()) { - if (cell->type == ID($memrd)) - memindex[cell->parameters.at(ID::MEMID).decode_string()].first.push_back(cell); + if (cell->type == "$memrd") + memindex[cell->parameters.at("\\MEMID").decode_string()].first.push_back(cell); - if (cell->type == ID($memwr)) - memindex[cell->parameters.at(ID::MEMID).decode_string()].second.push_back(cell); + if (cell->type == "$memwr") + memindex[cell->parameters.at("\\MEMID").decode_string()].second.push_back(cell); - if (cell->type == ID($mux)) + if (cell->type == "$mux") { - RTLIL::SigSpec sig_a = sigmap_xmux(cell->getPort(ID::A)); - RTLIL::SigSpec sig_b = sigmap_xmux(cell->getPort(ID::B)); + RTLIL::SigSpec sig_a = sigmap_xmux(cell->getPort("\\A")); + RTLIL::SigSpec sig_b = sigmap_xmux(cell->getPort("\\B")); if (sig_a.is_fully_undef()) - sigmap_xmux.add(cell->getPort(ID::Y), sig_b); + sigmap_xmux.add(cell->getPort("\\Y"), sig_b); else if (sig_b.is_fully_undef()) - sigmap_xmux.add(cell->getPort(ID::Y), sig_a); + sigmap_xmux.add(cell->getPort("\\Y"), sig_a); } - if (cell->type.in(ID($mux), ID($pmux))) + if (cell->type.in("$mux", "$pmux")) { - std::vector sig_y = sigmap(cell->getPort(ID::Y)); + std::vector sig_y = sigmap(cell->getPort("\\Y")); for (int i = 0; i < int(sig_y.size()); i++) sig_to_mux[sig_y[i]] = std::pair(cell, i); } @@ -712,20 +706,18 @@ struct MemoryShareWorker } cone_ct.setup_internals(); - cone_ct.cell_types.erase(ID($mul)); - cone_ct.cell_types.erase(ID($mod)); - cone_ct.cell_types.erase(ID($div)); - cone_ct.cell_types.erase(ID($modfloor)); - cone_ct.cell_types.erase(ID($divfloor)); - cone_ct.cell_types.erase(ID($pow)); - cone_ct.cell_types.erase(ID($shl)); - cone_ct.cell_types.erase(ID($shr)); - cone_ct.cell_types.erase(ID($sshl)); - cone_ct.cell_types.erase(ID($sshr)); - cone_ct.cell_types.erase(ID($shift)); - cone_ct.cell_types.erase(ID($shiftx)); - - modwalker.setup(module, &cone_ct); + cone_ct.cell_types.erase("$mul"); + cone_ct.cell_types.erase("$mod"); + cone_ct.cell_types.erase("$div"); + cone_ct.cell_types.erase("$pow"); + cone_ct.cell_types.erase("$shl"); + cone_ct.cell_types.erase("$shr"); + cone_ct.cell_types.erase("$sshl"); + cone_ct.cell_types.erase("$sshr"); + cone_ct.cell_types.erase("$shift"); + cone_ct.cell_types.erase("$shiftx"); + + modwalker.setup(design, module, &cone_ct); for (auto &it : memindex) consolidate_wr_using_sat(it.first, it.second.second); @@ -734,7 +726,7 @@ struct MemoryShareWorker struct MemorySharePass : public Pass { MemorySharePass() : Pass("memory_share", "consolidate memory ports") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -760,13 +752,11 @@ struct MemorySharePass : public Pass { log("optimizations) such as \"share\" and \"opt_merge\".\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override { + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing MEMORY_SHARE pass (consolidating $memrd/$memwr cells).\n"); extra_args(args, 1, design); - MemoryShareWorker msw(design); - for (auto module : design->selected_modules()) - msw(module); + MemoryShareWorker(design, module); } } MemorySharePass; diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc index d04d4ba7a7f..49ec667923b 100644 --- a/passes/memory/memory_unpack.cc +++ b/passes/memory/memory_unpack.cc @@ -31,53 +31,53 @@ void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) log("Creating $memrd and $memwr for memory `%s' in module `%s':\n", memory->name.c_str(), module->name.c_str()); - RTLIL::IdString mem_name = RTLIL::escape_id(memory->parameters.at(ID::MEMID).decode_string()); + RTLIL::IdString mem_name = RTLIL::escape_id(memory->parameters.at("\\MEMID").decode_string()); while (module->memories.count(mem_name) != 0) mem_name = mem_name.str() + stringf("_%d", autoidx++); RTLIL::Memory *mem = new RTLIL::Memory; mem->name = mem_name; - mem->width = memory->parameters.at(ID::WIDTH).as_int(); - mem->start_offset = memory->parameters.at(ID::OFFSET).as_int(); - mem->size = memory->parameters.at(ID::SIZE).as_int(); + mem->width = memory->parameters.at("\\WIDTH").as_int(); + mem->start_offset = memory->parameters.at("\\OFFSET").as_int(); + mem->size = memory->parameters.at("\\SIZE").as_int(); module->memories[mem_name] = mem; - int abits = memory->parameters.at(ID::ABITS).as_int(); - int num_rd_ports = memory->parameters.at(ID::RD_PORTS).as_int(); - int num_wr_ports = memory->parameters.at(ID::WR_PORTS).as_int(); + int abits = memory->parameters.at("\\ABITS").as_int(); + int num_rd_ports = memory->parameters.at("\\RD_PORTS").as_int(); + int num_wr_ports = memory->parameters.at("\\WR_PORTS").as_int(); for (int i = 0; i < num_rd_ports; i++) { - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($memrd)); - cell->parameters[ID::MEMID] = mem_name.str(); - cell->parameters[ID::ABITS] = memory->parameters.at(ID::ABITS); - cell->parameters[ID::WIDTH] = memory->parameters.at(ID::WIDTH); - cell->parameters[ID::CLK_ENABLE] = RTLIL::SigSpec(memory->parameters.at(ID::RD_CLK_ENABLE)).extract(i, 1).as_const(); - cell->parameters[ID::CLK_POLARITY] = RTLIL::SigSpec(memory->parameters.at(ID::RD_CLK_POLARITY)).extract(i, 1).as_const(); - cell->parameters[ID::TRANSPARENT] = RTLIL::SigSpec(memory->parameters.at(ID::RD_TRANSPARENT)).extract(i, 1).as_const(); - cell->setPort(ID::CLK, memory->getPort(ID::RD_CLK).extract(i, 1)); - cell->setPort(ID::EN, memory->getPort(ID::RD_EN).extract(i, 1)); - cell->setPort(ID::ADDR, memory->getPort(ID::RD_ADDR).extract(i*abits, abits)); - cell->setPort(ID::DATA, memory->getPort(ID::RD_DATA).extract(i*mem->width, mem->width)); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$memrd"); + cell->parameters["\\MEMID"] = mem_name.str(); + cell->parameters["\\ABITS"] = memory->parameters.at("\\ABITS"); + cell->parameters["\\WIDTH"] = memory->parameters.at("\\WIDTH"); + cell->parameters["\\CLK_ENABLE"] = RTLIL::SigSpec(memory->parameters.at("\\RD_CLK_ENABLE")).extract(i, 1).as_const(); + cell->parameters["\\CLK_POLARITY"] = RTLIL::SigSpec(memory->parameters.at("\\RD_CLK_POLARITY")).extract(i, 1).as_const(); + cell->parameters["\\TRANSPARENT"] = RTLIL::SigSpec(memory->parameters.at("\\RD_TRANSPARENT")).extract(i, 1).as_const(); + cell->setPort("\\CLK", memory->getPort("\\RD_CLK").extract(i, 1)); + cell->setPort("\\EN", memory->getPort("\\RD_EN").extract(i, 1)); + cell->setPort("\\ADDR", memory->getPort("\\RD_ADDR").extract(i*abits, abits)); + cell->setPort("\\DATA", memory->getPort("\\RD_DATA").extract(i*mem->width, mem->width)); } for (int i = 0; i < num_wr_ports; i++) { - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($memwr)); - cell->parameters[ID::MEMID] = mem_name.str(); - cell->parameters[ID::ABITS] = memory->parameters.at(ID::ABITS); - cell->parameters[ID::WIDTH] = memory->parameters.at(ID::WIDTH); - cell->parameters[ID::CLK_ENABLE] = RTLIL::SigSpec(memory->parameters.at(ID::WR_CLK_ENABLE)).extract(i, 1).as_const(); - cell->parameters[ID::CLK_POLARITY] = RTLIL::SigSpec(memory->parameters.at(ID::WR_CLK_POLARITY)).extract(i, 1).as_const(); - cell->parameters[ID::PRIORITY] = i; - cell->setPort(ID::CLK, memory->getPort(ID::WR_CLK).extract(i, 1)); - cell->setPort(ID::EN, memory->getPort(ID::WR_EN).extract(i*mem->width, mem->width)); - cell->setPort(ID::ADDR, memory->getPort(ID::WR_ADDR).extract(i*abits, abits)); - cell->setPort(ID::DATA, memory->getPort(ID::WR_DATA).extract(i*mem->width, mem->width)); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$memwr"); + cell->parameters["\\MEMID"] = mem_name.str(); + cell->parameters["\\ABITS"] = memory->parameters.at("\\ABITS"); + cell->parameters["\\WIDTH"] = memory->parameters.at("\\WIDTH"); + cell->parameters["\\CLK_ENABLE"] = RTLIL::SigSpec(memory->parameters.at("\\WR_CLK_ENABLE")).extract(i, 1).as_const(); + cell->parameters["\\CLK_POLARITY"] = RTLIL::SigSpec(memory->parameters.at("\\WR_CLK_POLARITY")).extract(i, 1).as_const(); + cell->parameters["\\PRIORITY"] = i; + cell->setPort("\\CLK", memory->getPort("\\WR_CLK").extract(i, 1)); + cell->setPort("\\EN", memory->getPort("\\WR_EN").extract(i*mem->width, mem->width)); + cell->setPort("\\ADDR", memory->getPort("\\WR_ADDR").extract(i*abits, abits)); + cell->setPort("\\DATA", memory->getPort("\\WR_DATA").extract(i*mem->width, mem->width)); } - Const initval = memory->parameters.at(ID::INIT); + Const initval = memory->parameters.at("\\INIT"); RTLIL::Cell *last_init_cell = nullptr; SigSpec last_init_data; int last_init_addr=0; @@ -90,19 +90,19 @@ void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) continue; found_non_undef_initval: if (last_init_cell && last_init_addr+1 == i/mem->width) { - last_init_cell->parameters[ID::WORDS] = last_init_cell->parameters[ID::WORDS].as_int() + 1; + last_init_cell->parameters["\\WORDS"] = last_init_cell->parameters["\\WORDS"].as_int() + 1; last_init_data.append(val); last_init_addr++; } else { if (last_init_cell) - last_init_cell->setPort(ID::DATA, last_init_data); - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($meminit)); - cell->parameters[ID::MEMID] = mem_name.str(); - cell->parameters[ID::ABITS] = memory->parameters.at(ID::ABITS); - cell->parameters[ID::WIDTH] = memory->parameters.at(ID::WIDTH); - cell->parameters[ID::WORDS] = 1; - cell->parameters[ID::PRIORITY] = i/mem->width; - cell->setPort(ID::ADDR, SigSpec(i/mem->width, abits)); + last_init_cell->setPort("\\DATA", last_init_data); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$meminit"); + cell->parameters["\\MEMID"] = mem_name.str(); + cell->parameters["\\ABITS"] = memory->parameters.at("\\ABITS"); + cell->parameters["\\WIDTH"] = memory->parameters.at("\\WIDTH"); + cell->parameters["\\WORDS"] = 1; + cell->parameters["\\PRIORITY"] = i/mem->width; + cell->setPort("\\ADDR", SigSpec(i/mem->width, abits)); last_init_cell = cell; last_init_addr = i/mem->width; last_init_data = val; @@ -110,7 +110,7 @@ void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) } if (last_init_cell) - last_init_cell->setPort(ID::DATA, last_init_data); + last_init_cell->setPort("\\DATA", last_init_data); module->remove(memory); } @@ -118,16 +118,16 @@ void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) void handle_module(RTLIL::Design *design, RTLIL::Module *module) { std::vector memcells; - for (auto cell : module->cells()) - if (cell->type == ID($mem) && design->selected(module, cell)) - memcells.push_back(cell->name); + for (auto &cell_it : module->cells_) + if (cell_it.second->type == "$mem" && design->selected(module, cell_it.second)) + memcells.push_back(cell_it.first); for (auto &it : memcells) - handle_memory(module, module->cell(it)); + handle_memory(module, module->cells_.at(it)); } struct MemoryUnpackPass : public Pass { MemoryUnpackPass() : Pass("memory_unpack", "unpack multi-port memory cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -137,11 +137,12 @@ struct MemoryUnpackPass : public Pass { log("$memwr cells. It is the counterpart to the memory_collect pass.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override { + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing MEMORY_UNPACK pass (generating $memrd/$memwr cells form $mem cells).\n"); extra_args(args, 1, design); - for (auto module : design->selected_modules()) - handle_module(design, module); + for (auto &mod_it : design->modules_) + if (design->selected(mod_it.second)) + handle_module(design, mod_it.second); } } MemoryUnpackPass; diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index 3133927bbcf..002c1a6a1de 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -15,7 +15,6 @@ OBJS += passes/opt/wreduce.o OBJS += passes/opt/opt_demorgan.o OBJS += passes/opt/rmports.o OBJS += passes/opt/opt_lut.o -OBJS += passes/opt/opt_lut_ins.o OBJS += passes/opt/pmux2shiftx.o OBJS += passes/opt/muxpack.o endif diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index aa5f8243744..c40c02acd51 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -208,8 +208,8 @@ struct MuxpackWorker { Cell *prev_cell = sig_chain_prev.at(a_sig); log_assert(prev_cell); - SigSpec s_sig = sigmap(cell->getPort(ID::S)); - s_sig.append(sigmap(prev_cell->getPort(ID::S))); + SigSpec s_sig = sigmap(cell->getPort(ID(S))); + s_sig.append(sigmap(prev_cell->getPort(ID(S)))); if (!excl_db.query(s_sig)) goto start_cell; } @@ -271,26 +271,26 @@ struct MuxpackWorker first_cell->type = ID($pmux); SigSpec b_sig = first_cell->getPort(ID::B); - SigSpec s_sig = first_cell->getPort(ID::S); + SigSpec s_sig = first_cell->getPort(ID(S)); for (int i = 1; i < cases; i++) { Cell* prev_cell = chain[cursor+i-1]; Cell* cursor_cell = chain[cursor+i]; if (sigmap(prev_cell->getPort(ID::Y)) == sigmap(cursor_cell->getPort(ID::A))) { b_sig.append(cursor_cell->getPort(ID::B)); - s_sig.append(cursor_cell->getPort(ID::S)); + s_sig.append(cursor_cell->getPort(ID(S))); } else { log_assert(cursor_cell->type == ID($mux)); b_sig.append(cursor_cell->getPort(ID::A)); - s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort(ID::S))); + s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort(ID(S)))); } remove_cells.insert(cursor_cell); } first_cell->setPort(ID::B, b_sig); - first_cell->setPort(ID::S, s_sig); - first_cell->setParam(ID::S_WIDTH, GetSize(s_sig)); + first_cell->setPort(ID(S), s_sig); + first_cell->setParam(ID(S_WIDTH), GetSize(s_sig)); first_cell->setPort(ID::Y, last_cell->getPort(ID::Y)); cursor += cases; @@ -326,7 +326,7 @@ struct MuxpackWorker struct MuxpackPass : public Pass { MuxpackPass() : Pass("muxpack", "$mux/$pmux cascades to $pmux") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -341,7 +341,7 @@ struct MuxpackPass : public Pass { log("certain that their select inputs are mutually exclusive.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n"); diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc index 8be94e3459d..3968198832d 100644 --- a/passes/opt/opt.cc +++ b/passes/opt/opt.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct OptPass : public Pass { OptPass() : Pass("opt", "perform simple optimizations") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -44,8 +44,8 @@ struct OptPass : public Pass { log(" opt_muxtree\n"); log(" opt_reduce [-fine] [-full]\n"); log(" opt_merge [-share_all]\n"); - log(" opt_share (-full only)\n"); - log(" opt_rmdff [-keepdc] [-sat] (except when called with -noff)\n"); + log(" opt_share (-full only)\n"); + log(" opt_rmdff [-keepdc] [-sat]\n"); log(" opt_clean [-purge]\n"); log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n"); log(" while \n"); @@ -55,7 +55,7 @@ struct OptPass : public Pass { log(" do\n"); log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n"); log(" opt_merge [-share_all]\n"); - log(" opt_rmdff [-keepdc] [-sat] (except when called with -noff)\n"); + log(" opt_rmdff [-keepdc] [-sat]\n"); log(" opt_clean [-purge]\n"); log(" while \n"); log("\n"); @@ -64,7 +64,7 @@ struct OptPass : public Pass { log("\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string opt_clean_args; std::string opt_expr_args; @@ -73,7 +73,6 @@ struct OptPass : public Pass { std::string opt_rmdff_args; bool opt_share = false; bool fast_mode = false; - bool noff_mode = false; log_header(design, "Executing OPT pass (performing simple optimizations).\n"); log_push(); @@ -128,10 +127,6 @@ struct OptPass : public Pass { fast_mode = true; continue; } - if (args[argidx] == "-noff") { - noff_mode = true; - continue; - } break; } extra_args(args, argidx, design); @@ -142,8 +137,7 @@ struct OptPass : public Pass { Pass::call(design, "opt_expr" + opt_expr_args); Pass::call(design, "opt_merge" + opt_merge_args); design->scratchpad_unset("opt.did_something"); - if (!noff_mode) - Pass::call(design, "opt_rmdff" + opt_rmdff_args); + Pass::call(design, "opt_rmdff" + opt_rmdff_args); if (design->scratchpad_get_bool("opt.did_something") == false) break; Pass::call(design, "opt_clean" + opt_clean_args); @@ -162,8 +156,7 @@ struct OptPass : public Pass { Pass::call(design, "opt_merge" + opt_merge_args); if (opt_share) Pass::call(design, "opt_share"); - if (!noff_mode) - 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_expr" + opt_expr_args); if (design->scratchpad_get_bool("opt.did_something") == false) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 44de60b48c4..2f69b3d4c1b 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -53,24 +53,18 @@ struct keep_cache_t cache[module] = true; if (!module->get_bool_attribute(ID::keep)) { - bool found_keep = false; - for (auto cell : module->cells()) - if (query(cell, true /* ignore_specify */)) { - found_keep = true; - break; - } - cache[module] = found_keep; + bool found_keep = false; + for (auto cell : module->cells()) + if (query(cell)) found_keep = true; + cache[module] = found_keep; } return cache[module]; } - bool query(Cell *cell, bool ignore_specify = false) + bool query(Cell *cell) { - if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) - return true; - - if (!ignore_specify && cell->type.in(ID($specify2), ID($specify3), ID($specrule))) + if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover), ID($specify2), ID($specify3), ID($specrule))) return true; if (cell->has_keep_attr()) @@ -183,8 +177,8 @@ void rmunused_module_cells(Module *module, bool verbose) int count_nontrivial_wire_attrs(RTLIL::Wire *w) { int count = w->attributes.size(); - count -= w->attributes.count(ID::src); - count -= w->attributes.count(ID::unused_bits); + count -= w->attributes.count(ID(src)); + count -= w->attributes.count(ID(unused_bits)); return count; } @@ -203,8 +197,8 @@ bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool ®s, SigPoo return !(w2->port_input && w2->port_output); if (w1->name[0] == '\\' && w2->name[0] == '\\') { - if (regs.check(s1) != regs.check(s2)) - return regs.check(s2); + if (regs.check_any(s1) != regs.check_any(s2)) + return regs.check_any(s2); if (direct_wires.count(w1) != direct_wires.count(w2)) return direct_wires.count(w2) != 0; if (conns.check_any(s1) != conns.check_any(s2)) @@ -317,12 +311,12 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos log_assert(GetSize(s1) == GetSize(s2)); Const initval; - if (wire->attributes.count(ID::init)) - initval = wire->attributes.at(ID::init); + if (wire->attributes.count(ID(init))) + initval = wire->attributes.at(ID(init)); if (GetSize(initval) != GetSize(wire)) initval.bits.resize(GetSize(wire), State::Sx); if (initval.is_fully_undef()) - wire->attributes.erase(ID::init); + wire->attributes.erase(ID(init)); if (GetSize(wire) == 0) { // delete zero-width wires, unless they are module ports @@ -358,14 +352,14 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos s2[i] = initval[i]; initval[i] = State::Sx; } - new_conn.first.append(s1[i]); - new_conn.second.append(s2[i]); + new_conn.first.append_bit(s1[i]); + new_conn.second.append_bit(s2[i]); } if (new_conn.first.size() > 0) { if (initval.is_fully_undef()) - wire->attributes.erase(ID::init); + wire->attributes.erase(ID(init)); else - wire->attributes.at(ID::init) = initval; + wire->attributes.at(ID(init)) = initval; used_signals.add(new_conn.first); used_signals.add(new_conn.second); module->connect(new_conn); @@ -383,11 +377,11 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } if (unused_bits.empty() || wire->port_id != 0) - wire->attributes.erase(ID::unused_bits); + wire->attributes.erase(ID(unused_bits)); else - wire->attributes[ID::unused_bits] = RTLIL::Const(unused_bits); + wire->attributes[ID(unused_bits)] = RTLIL::Const(unused_bits); } else { - wire->attributes.erase(ID::unused_bits); + wire->attributes.erase(ID(unused_bits)); } } } @@ -406,13 +400,10 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (verbose && del_temp_wires_count) log_debug(" removed %d unused temporary wires.\n", del_temp_wires_count); - if (!del_wires_queue.empty()) - module->design->scratchpad_set_bool("opt.did_something", true); - return !del_wires_queue.empty(); } -bool rmunused_module_init(RTLIL::Module *module, bool verbose) +bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) { bool did_something = false; CellTypes fftypes; @@ -422,18 +413,18 @@ bool rmunused_module_init(RTLIL::Module *module, bool verbose) dict qbits; for (auto cell : module->cells()) - if (fftypes.cell_known(cell->type) && cell->hasPort(ID::Q)) + if (fftypes.cell_known(cell->type) && cell->hasPort(ID(Q))) { - SigSpec sig = cell->getPort(ID::Q); + SigSpec sig = cell->getPort(ID(Q)); for (int i = 0; i < GetSize(sig); i++) { SigBit bit = sig[i]; - if (bit.wire == nullptr || bit.wire->attributes.count(ID::init) == 0) + if (bit.wire == nullptr || bit.wire->attributes.count(ID(init)) == 0) continue; - Const init = bit.wire->attributes.at(ID::init); + Const init = bit.wire->attributes.at(ID(init)); if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz) continue; @@ -445,10 +436,13 @@ bool rmunused_module_init(RTLIL::Module *module, bool verbose) for (auto wire : module->wires()) { - if (wire->attributes.count(ID::init) == 0) + if (!purge_mode && wire->name[0] == '\\') + continue; + + if (wire->attributes.count(ID(init)) == 0) continue; - Const init = wire->attributes.at(ID::init); + Const init = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++) { @@ -461,35 +455,21 @@ bool rmunused_module_init(RTLIL::Module *module, bool verbose) if (wire_bit == mapped_wire_bit) goto next_wire; - if (mapped_wire_bit.wire) { - if (qbits.count(mapped_wire_bit) == 0) - goto next_wire; - - if (qbits.at(mapped_wire_bit) != init[i]) - goto next_wire; - } - else { - if (mapped_wire_bit == State::Sx || mapped_wire_bit == State::Sz) - goto next_wire; + if (qbits.count(sigmap(SigBit(wire, i))) == 0) + goto next_wire; - if (mapped_wire_bit != init[i]) { - log_warning("Initial value conflict for %s resolving to %s but with init %s.\n", log_signal(wire_bit), log_signal(mapped_wire_bit), log_signal(init[i])); - goto next_wire; - } - } + if (qbits.at(sigmap(SigBit(wire, i))) != init[i]) + goto next_wire; } if (verbose) log_debug(" removing redundant init attribute on %s.\n", log_id(wire)); - wire->attributes.erase(ID::init); + wire->attributes.erase(ID(init)); did_something = true; next_wire:; } - if (did_something) - module->design->scratchpad_set_bool("opt.did_something", true); - return did_something; } @@ -501,7 +481,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool std::vector delcells; for (auto cell : module->cells()) if (cell->type.in(ID($pos), ID($_BUF_)) && !cell->has_keep_attr()) { - bool is_signed = cell->type == ID($pos) && cell->getParam(ID::A_SIGNED).as_bool(); + bool is_signed = cell->type == ID($pos) && cell->getParam(ID(A_SIGNED)).as_bool(); RTLIL::SigSpec a = cell->getPort(ID::A); RTLIL::SigSpec y = cell->getPort(ID::Y); a.extend_u0(GetSize(y), is_signed); @@ -520,13 +500,13 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool rmunused_module_cells(module, verbose); while (rmunused_module_signals(module, purge_mode, verbose)) { } - if (rminit && rmunused_module_init(module, verbose)) + if (rminit && rmunused_module_init(module, purge_mode, verbose)) while (rmunused_module_signals(module, purge_mode, verbose)) { } } struct OptCleanPass : public Pass { OptCleanPass() : Pass("opt_clean", "remove unused cells and wires") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -543,7 +523,7 @@ struct OptCleanPass : public Pass { log(" also remove internal nets if they have a public name\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool purge_mode = false; @@ -592,7 +572,7 @@ struct OptCleanPass : public Pass { struct CleanPass : public Pass { CleanPass() : Pass("clean", "remove unused cells and wires") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -607,7 +587,7 @@ struct CleanPass : public Pass { log("in -purge mode between the commands.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool purge_mode = false; @@ -619,7 +599,8 @@ struct CleanPass : public Pass { } break; } - extra_args(args, argidx, design); + if (argidx < args.size()) + extra_args(args, argidx, design); keep_cache.reset(design); @@ -634,7 +615,7 @@ struct CleanPass : public Pass { for (auto module : design->selected_whole_modules()) { if (module->has_processes()) continue; - rmunused_module(module, purge_mode, ys_debug(), true); + rmunused_module(module, purge_mode, ys_debug(), false); } log_suppressed(); diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc index f0fa86f42ba..4bc82815bde 100644 --- a/passes/opt/opt_demorgan.cc +++ b/passes/opt/opt_demorgan.cc @@ -169,7 +169,7 @@ void demorgan_worker( struct OptDemorganPass : public Pass { OptDemorganPass() : Pass("opt_demorgan", "Optimize reductions with DeMorgan equivalents") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -179,7 +179,7 @@ struct OptDemorganPass : public Pass { log("overall gate count of the circuit\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_DEMORGAN pass (push inverters through $reduce_* cells).\n"); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 1051a59f278..6cf66fb95ae 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -31,8 +31,9 @@ PRIVATE_NAMESPACE_BEGIN bool did_something; -void replace_undriven(RTLIL::Module *module, const CellTypes &ct) +void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) { + CellTypes ct(design); SigMap sigmap(module); SigPool driven_signals; SigPool used_signals; @@ -50,9 +51,9 @@ void replace_undriven(RTLIL::Module *module, const CellTypes &ct) } for (auto wire : module->wires()) { - if (wire->attributes.count(ID::init)) { + if (wire->attributes.count(ID(init))) { SigSpec sig = sigmap(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { if (initval[i] == State::S0 || initval[i] == State::S1) initbits[sig[i]] = make_pair(wire, initval[i]); @@ -98,18 +99,18 @@ void replace_undriven(RTLIL::Module *module, const CellTypes &ct) for (auto wire : revisit_initwires) { SigSpec sig = sm2(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { if (SigBit(initval[i]) == sig[i]) initval[i] = State::Sx; } if (initval.is_fully_undef()) { log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire)); - wire->attributes.erase(ID::init); + wire->attributes.erase(ID(init)); did_something = true; - } else if (initval != wire->attributes.at(ID::init)) { + } else if (initval != wire->attributes.at(ID(init))) { log_debug("Updating init attribute on %s/%s: %s\n", log_id(module), log_id(wire), log_signal(initval)); - wire->attributes[ID::init] = initval; + wire->attributes[ID(init)] = initval; did_something = true; } } @@ -117,7 +118,7 @@ void replace_undriven(RTLIL::Module *module, const CellTypes &ct) } void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, - const std::string &info, IdString out_port, RTLIL::SigSpec out_val) + const std::string &info YS_ATTRIBUTE(unused), IdString out_port, RTLIL::SigSpec out_val) { RTLIL::SigSpec Y = cell->getPort(out_port); out_val.extend_u0(Y.size(), false); @@ -132,11 +133,11 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, did_something = true; } -bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap, bool keepdc) +bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap) { IdString b_name = cell->hasPort(ID::B) ? ID::B : ID::A; - bool a_signed = cell->parameters.at(ID::A_SIGNED).as_bool(); + bool a_signed = cell->parameters.at(ID(A_SIGNED)).as_bool(); bool b_signed = cell->parameters.at(b_name.str() + "_SIGNED").as_bool(); RTLIL::SigSpec sig_a = sigmap(cell->getPort(ID::A)); @@ -156,36 +157,20 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ int group_idx = GRP_DYN; RTLIL::SigBit bit_a = bits_a[i], bit_b = bits_b[i]; - if (cell->type == ID($or)) { - if (bit_a == RTLIL::State::S1 || bit_b == RTLIL::State::S1) - bit_a = bit_b = RTLIL::State::S1; - } - else if (cell->type == ID($and)) { - if (bit_a == RTLIL::State::S0 || bit_b == RTLIL::State::S0) - bit_a = bit_b = RTLIL::State::S0; - } - else if (!keepdc) { - if (cell->type == ID($xor)) { - if (bit_a == bit_b) - bit_a = bit_b = RTLIL::State::S0; - } - else if (cell->type == ID($xnor)) { - if (bit_a == bit_b) - bit_a = bit_b = RTLIL::State::S1; // For consistency with gate-level which does $xnor -> $_XOR_ + $_NOT_ - } - } + if (cell->type == ID($or) && (bit_a == RTLIL::State::S1 || bit_b == RTLIL::State::S1)) + bit_a = bit_b = RTLIL::State::S1; - bool def = (bit_a != State::Sx && bit_a != State::Sz && bit_b != State::Sx && bit_b != State::Sz); - if (def || !keepdc) { - if (bit_a.wire == NULL && bit_b.wire == NULL) - group_idx = GRP_CONST_AB; - else if (bit_a.wire == NULL) - group_idx = GRP_CONST_A; - else if (bit_b.wire == NULL && commutative) - group_idx = GRP_CONST_A, std::swap(bit_a, bit_b); - else if (bit_b.wire == NULL) - group_idx = GRP_CONST_B; - } + if (cell->type == ID($and) && (bit_a == RTLIL::State::S0 || bit_b == RTLIL::State::S0)) + bit_a = bit_b = RTLIL::State::S0; + + if (bit_a.wire == NULL && bit_b.wire == NULL) + group_idx = GRP_CONST_AB; + else if (bit_a.wire == NULL) + group_idx = GRP_CONST_A; + else if (bit_b.wire == NULL && commutative) + group_idx = GRP_CONST_A, std::swap(bit_a, bit_b); + else if (bit_b.wire == NULL) + group_idx = GRP_CONST_B; grouped_bits[group_idx][std::pair(bit_a, bit_b)].insert(bits_y[i]); } @@ -202,91 +187,40 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ if (grouped_bits[i].empty()) continue; - RTLIL::SigSpec new_y = module->addWire(NEW_ID, GetSize(grouped_bits[i])); + RTLIL::Wire *new_y = module->addWire(NEW_ID, GetSize(grouped_bits[i])); RTLIL::SigSpec new_a, new_b; RTLIL::SigSig new_conn; for (auto &it : grouped_bits[i]) { for (auto &bit : it.second) { - new_conn.first.append(bit); - new_conn.second.append(new_y[new_a.size()]); + new_conn.first.append_bit(bit); + new_conn.second.append_bit(RTLIL::SigBit(new_y, new_a.size())); } - new_a.append(it.first.first); - new_b.append(it.first.second); + new_a.append_bit(it.first.first); + new_b.append_bit(it.first.second); } if (cell->type.in(ID($and), ID($or)) && i == GRP_CONST_A) { - if (!keepdc) { - if (cell->type == ID($and)) - new_a.replace(dict{{State::Sx, State::S0}, {State::Sz, State::S0}}, &new_b); - else if (cell->type == ID($or)) - new_a.replace(dict{{State::Sx, State::S1}, {State::Sz, State::S1}}, &new_b); - else log_abort(); - } log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a)); module->connect(new_y, new_b); module->connect(new_conn); continue; } - if (cell->type.in(ID($xor), ID($xnor)) && i == GRP_CONST_A) { - SigSpec undef_a, undef_y, undef_b; - SigSpec def_y, def_a, def_b; - for (int i = 0; i < GetSize(new_y); i++) { - bool undef = new_a[i] == State::Sx || new_a[i] == State::Sz; - if (!keepdc && (undef || new_a[i] == new_b[i])) { - undef_a.append(new_a[i]); - if (cell->type == ID($xor)) - undef_b.append(State::S0); - // For consistency since simplemap does $xnor -> $_XOR_ + $_NOT_ - else if (cell->type == ID($xnor)) - undef_b.append(State::S1); - else log_abort(); - undef_y.append(new_y[i]); - } - else if (new_a[i] == State::S0 || new_a[i] == State::S1) { - undef_a.append(new_a[i]); - if (cell->type == ID($xor)) - undef_b.append(new_a[i] == State::S1 ? module->Not(NEW_ID, new_b[i]).as_bit() : new_b[i]); - else if (cell->type == ID($xnor)) - undef_b.append(new_a[i] == State::S1 ? new_b[i] : module->Not(NEW_ID, new_b[i]).as_bit()); - else log_abort(); - undef_y.append(new_y[i]); - } - else { - def_a.append(new_a[i]); - def_b.append(new_b[i]); - def_y.append(new_y[i]); - } - } - if (!undef_y.empty()) { - log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(undef_b), log_id(cell->type), log_signal(undef_a)); - module->connect(undef_y, undef_b); - if (def_y.empty()) { - module->connect(new_conn); - continue; - } - } - new_a = std::move(def_a); - new_b = std::move(def_b); - new_y = std::move(def_y); - } - - RTLIL::Cell *c = module->addCell(NEW_ID, cell->type); c->setPort(ID::A, new_a); - c->parameters[ID::A_WIDTH] = new_a.size(); - c->parameters[ID::A_SIGNED] = false; + c->parameters[ID(A_WIDTH)] = new_a.size(); + c->parameters[ID(A_SIGNED)] = false; if (b_name == ID::B) { c->setPort(ID::B, new_b); - c->parameters[ID::B_WIDTH] = new_b.size(); - c->parameters[ID::B_SIGNED] = false; + c->parameters[ID(B_WIDTH)] = new_b.size(); + c->parameters[ID(B_SIGNED)] = false; } c->setPort(ID::Y, new_y); - c->parameters[ID::Y_WIDTH] = GetSize(new_y); + c->parameters[ID(Y_WIDTH)] = new_y->width; c->check(); module->connect(new_conn); @@ -439,7 +373,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID::A)); if (cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == SigSpec(State::S1) && cell->getPort(ID::B) == SigSpec(State::S0)) - invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID::S)); + invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID(S))); if (ct_combinational.cell_known(cell->type)) for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = assign_map(conn.second); @@ -467,66 +401,37 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (clkinv) { - if (cell->type.in(ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), ID($fsm), ID($memrd), ID($memwr))) - handle_polarity_inv(cell, ID::CLK, ID::CLK_POLARITY, assign_map, invert_map); + if (cell->type.in(ID($dff), ID($dffe), ID($dffsr), ID($adff), ID($fsm), ID($memrd), ID($memwr))) + handle_polarity_inv(cell, ID(CLK), ID(CLK_POLARITY), assign_map, invert_map); - if (cell->type.in(ID($sr), ID($dffsr), ID($dffsre), ID($dlatchsr))) { - handle_polarity_inv(cell, ID::SET, ID::SET_POLARITY, assign_map, invert_map); - handle_polarity_inv(cell, ID::CLR, ID::CLR_POLARITY, assign_map, invert_map); + if (cell->type.in(ID($sr), ID($dffsr), ID($dlatchsr))) { + handle_polarity_inv(cell, ID(SET), ID(SET_POLARITY), assign_map, invert_map); + handle_polarity_inv(cell, ID(CLR), ID(CLR_POLARITY), assign_map, invert_map); } - if (cell->type.in(ID($adff), ID($adffe), ID($adlatch))) - handle_polarity_inv(cell, ID::ARST, ID::ARST_POLARITY, assign_map, invert_map); - - if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) - handle_polarity_inv(cell, ID::SRST, ID::SRST_POLARITY, assign_map, invert_map); - - if (cell->type.in(ID($dffe), ID($adffe), ID($sdffe), ID($sdffce), ID($dffsre), ID($dlatch), ID($adlatch), ID($dlatchsr))) - handle_polarity_inv(cell, ID::EN, ID::EN_POLARITY, assign_map, invert_map); - - handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", ID::S, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SR_?N_", "$_SR_?P_", ID::R, assign_map, invert_map); - - handle_clkpol_celltype_swap(cell, "$_DFF_N_", "$_DFF_P_", ID::C, assign_map, invert_map); - - handle_clkpol_celltype_swap(cell, "$_DFFE_N?_", "$_DFFE_P?_", ID::C, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFE_?N_", "$_DFFE_?P_", ID::E, assign_map, invert_map); - - handle_clkpol_celltype_swap(cell, "$_DFF_N??_", "$_DFF_P??_", ID::C, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFF_?N?_", "$_DFF_?P?_", ID::R, assign_map, invert_map); - - handle_clkpol_celltype_swap(cell, "$_DFFE_N???_", "$_DFFE_P???_", ID::C, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFE_?N??_", "$_DFFE_?P??_", ID::R, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFE_???N_", "$_DFFE_???P_", ID::E, assign_map, invert_map); + if (cell->type.in(ID($dffe), ID($dlatch), ID($dlatchsr))) + handle_polarity_inv(cell, ID(EN), ID(EN_POLARITY), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SDFF_N??_", "$_SDFF_P??_", ID::C, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SDFF_?N?_", "$_SDFF_?P?_", ID::R, assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", ID(S), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_SR_?N_", "$_SR_?P_", ID(R), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SDFFE_N???_", "$_SDFFE_P???_", ID::C, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SDFFE_?N??_", "$_SDFFE_?P??_", ID::R, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SDFFE_???N_", "$_SDFFE_???P_", ID::E, assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFF_N_", "$_DFF_P_", ID(C), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SDFFCE_N???_", "$_SDFFCE_P???_", ID::C, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SDFFCE_?N??_", "$_SDFFCE_?P??_", ID::R, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SDFFCE_???N_", "$_SDFFCE_???P_", ID::E, assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFE_N?_", "$_DFFE_P?_", ID(C), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFE_?N_", "$_DFFE_?P_", ID(E), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSR_N??_", "$_DFFSR_P??_", ID::C, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSR_?N?_", "$_DFFSR_?P?_", ID::S, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSR_??N_", "$_DFFSR_??P_", ID::R, assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFF_N??_", "$_DFF_P??_", ID(C), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFF_?N?_", "$_DFF_?P?_", ID(R), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSRE_N???_", "$_DFFSRE_P???_", ID::C, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSRE_?N??_", "$_DFFSRE_?P??_", ID::S, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSRE_??N?_", "$_DFFSRE_??P?_", ID::R, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSRE_???N_", "$_DFFSRE_???P_", ID::E, assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFSR_N??_", "$_DFFSR_P??_", ID(C), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFSR_?N?_", "$_DFFSR_?P?_", ID(S), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFSR_??N_", "$_DFFSR_??P_", ID(R), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCH_N_", "$_DLATCH_P_", ID::E, assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DLATCH_N_", "$_DLATCH_P_", ID(E), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCH_N??_", "$_DLATCH_P??_", ID::E, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCH_?N?_", "$_DLATCH_?P?_", ID::R, assign_map, invert_map); - - handle_clkpol_celltype_swap(cell, "$_DLATCHSR_N??_", "$_DLATCHSR_P??_", ID::E, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCHSR_?N?_", "$_DLATCHSR_?P?_", ID::S, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", ID::R, assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DLATCHSR_N??_", "$_DLATCHSR_P??_", ID(E), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DLATCHSR_?N?_", "$_DLATCHSR_?P?_", ID(S), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", ID(R), assign_map, invert_map); } bool detect_const_and = false; @@ -535,13 +440,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($reduce_and), ID($_AND_))) detect_const_and = true; - if (cell->type.in(ID($and), ID($logic_and)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID::A_SIGNED).as_bool()) + if (cell->type.in(ID($and), ID($logic_and)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool()) detect_const_and = true; if (cell->type.in(ID($reduce_or), ID($reduce_bool), ID($_OR_))) detect_const_or = true; - if (cell->type.in(ID($or), ID($logic_or)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID::A_SIGNED).as_bool()) + if (cell->type.in(ID($or), ID($logic_or)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool()) detect_const_or = true; if (detect_const_and || detect_const_or) @@ -572,13 +477,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (detect_const_and && (found_zero || found_inv || (found_undef && consume_x))) { + if (detect_const_and && (found_zero || found_inv)) { cover("opt.opt_expr.const_and"); replace_cell(assign_map, module, cell, "const_and", ID::Y, RTLIL::State::S0); goto next_cell; } - if (detect_const_or && (found_one || found_inv || (found_undef && consume_x))) { + if (detect_const_or && (found_one || found_inv)) { cover("opt.opt_expr.const_or"); replace_cell(assign_map, module, cell, "const_or", ID::Y, RTLIL::State::S1); goto next_cell; @@ -591,58 +496,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type.in(ID($_XOR_), ID($_XNOR_)) || (cell->type.in(ID($xor), ID($xnor)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID::A_SIGNED).as_bool())) - { - SigBit sig_a = assign_map(cell->getPort(ID::A)); - SigBit sig_b = assign_map(cell->getPort(ID::B)); - if (!keepdc && (sig_a == sig_b || sig_a == State::Sx || sig_a == State::Sz || sig_b == State::Sx || sig_b == State::Sz)) { - if (cell->type.in(ID($xor), ID($_XOR_))) { - cover("opt.opt_expr.const_xor"); - replace_cell(assign_map, module, cell, "const_xor", ID::Y, RTLIL::State::S0); - goto next_cell; - } - if (cell->type.in(ID($xnor), ID($_XNOR_))) { - cover("opt.opt_expr.const_xnor"); - // For consistency since simplemap does $xnor -> $_XOR_ + $_NOT_ - int width = cell->getParam(ID::Y_WIDTH).as_int(); - replace_cell(assign_map, module, cell, "const_xnor", ID::Y, SigSpec(RTLIL::State::S1, width)); - goto next_cell; - } - log_abort(); - } - - if (!sig_a.wire) - std::swap(sig_a, sig_b); - if (sig_b == State::S0 || sig_b == State::S1) { - if (cell->type.in(ID($xor), ID($_XOR_))) { - cover("opt.opt_expr.xor_buffer"); - SigSpec sig_y; - if (cell->type == ID($xor)) - sig_y = (sig_b == State::S1 ? module->Not(NEW_ID, sig_a).as_bit() : sig_a); - else if (cell->type == ID($_XOR_)) - sig_y = (sig_b == State::S1 ? module->NotGate(NEW_ID, sig_a) : sig_a); - else log_abort(); - replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_y); - goto next_cell; - } - if (cell->type.in(ID($xnor), ID($_XNOR_))) { - cover("opt.opt_expr.xnor_buffer"); - SigSpec sig_y; - if (cell->type == ID($xnor)) { - sig_y = (sig_b == State::S1 ? sig_a : module->Not(NEW_ID, sig_a).as_bit()); - int width = cell->getParam(ID::Y_WIDTH).as_int(); - sig_y.append(RTLIL::Const(State::S1, width-1)); - } - else if (cell->type == ID($_XNOR_)) - sig_y = (sig_b == State::S1 ? sig_a : module->NotGate(NEW_ID, sig_a)); - else log_abort(); - replace_cell(assign_map, module, cell, "xnor_buffer", ID::Y, sig_y); - goto next_cell; - } - log_abort(); - } - } - if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1) { @@ -662,7 +515,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (do_fine) { if (cell->type.in(ID($not), ID($pos), ID($and), ID($or), ID($xor), ID($xnor))) - if (group_cell_inputs(module, cell, true, assign_map, keepdc)) + if (group_cell_inputs(module, cell, true, assign_map)) goto next_cell; if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_and), ID($reduce_bool))) @@ -683,7 +536,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a)); cell->setPort(ID::A, new_sig_a); - cell->parameters.at(ID::A_WIDTH) = GetSize(new_sig_a); + cell->parameters.at(ID(A_WIDTH)) = GetSize(new_sig_a); did_something = true; } } @@ -706,7 +559,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b)); cell->setPort(ID::B, new_sig_b); - cell->parameters.at(ID::B_WIDTH) = GetSize(new_sig_b); + cell->parameters.at(ID(B_WIDTH)) = GetSize(new_sig_b); did_something = true; } } @@ -732,7 +585,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); cell->setPort(ID::A, sig_a = new_a); - cell->parameters.at(ID::A_WIDTH) = 1; + cell->parameters.at(ID(A_WIDTH)) = 1; did_something = true; } } @@ -758,7 +611,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); cell->setPort(ID::A, sig_a = new_a); - cell->parameters.at(ID::A_WIDTH) = 1; + cell->parameters.at(ID(A_WIDTH)) = 1; did_something = true; } } @@ -784,7 +637,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b)); cell->setPort(ID::B, sig_b = new_b); - cell->parameters.at(ID::B_WIDTH) = 1; + cell->parameters.at(ID(B_WIDTH)) = 1; did_something = true; } } @@ -794,106 +647,77 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); bool sub = cell->type == ID($sub); - int minsz = GetSize(sig_y); - minsz = std::min(minsz, GetSize(sig_a)); - minsz = std::min(minsz, GetSize(sig_b)); - int i; - for (i = 0; i < minsz; i++) { - RTLIL::SigBit b = sig_b[i]; - RTLIL::SigBit a = sig_a[i]; - if (b == State::S0) - module->connect(sig_y[i], a); - else if (sub && b == State::S1 && a == State::S1) - module->connect(sig_y[i], State::S0); - else if (!sub && a == State::S0) - module->connect(sig_y[i], b); + for (i = 0; i < GetSize(sig_y); i++) { + if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) + module->connect(sig_y[i], sig_a[i]); + else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) + module->connect(sig_y[i], sig_b[i]); else break; } if (i > 0) { cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); - log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module)); - SigSpec new_a = sig_a.extract_end(i); - SigSpec new_b = sig_b.extract_end(i); - if (new_a.empty() && is_signed) - new_a = sig_a[i-1]; - if (new_b.empty() && is_signed) - new_b = sig_b[i-1]; - cell->setPort(ID::A, new_a); - cell->setPort(ID::B, new_b); + cell->setPort(ID::A, sig_a.extract_end(i)); + cell->setPort(ID::B, sig_b.extract_end(i)); cell->setPort(ID::Y, sig_y.extract_end(i)); cell->fixup_parameters(); did_something = true; } } - if (cell->type == ID($alu)) + if (cell->type == "$alu") { RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); - RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID::CI)); - RTLIL::SigBit sig_bi = assign_map(cell->getPort(ID::BI)); - RTLIL::SigSpec sig_x = cell->getPort(ID::X); + RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID(CI))); + RTLIL::SigBit sig_bi = assign_map(cell->getPort(ID(BI))); + RTLIL::SigSpec sig_x = cell->getPort(ID(X)); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); - RTLIL::SigSpec sig_co = cell->getPort(ID::CO); - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); + RTLIL::SigSpec sig_co = cell->getPort(ID(CO)); - if (sig_bi != State::S0 && sig_bi != State::S1) - goto skip_fine_alu; - if (sig_ci != State::S0 && sig_ci != State::S1) - goto skip_fine_alu; + if (sig_ci.wire || sig_bi.wire) + goto next_cell; - bool bi = sig_bi == State::S1; - bool ci = sig_ci == State::S1; + bool sub = (sig_ci == State::S1 && sig_bi == State::S1); - int minsz = GetSize(sig_y); - minsz = std::min(minsz, GetSize(sig_a)); - minsz = std::min(minsz, GetSize(sig_b)); + // If not a subtraction, yet there is a carry or B is inverted + // then no optimisation is possible as carry will not be constant + if (!sub && (sig_ci != State::S0 || sig_bi != State::S0)) + goto next_cell; int i; - for (i = 0; i < minsz; i++) { - RTLIL::SigBit b = sig_b[i]; - RTLIL::SigBit a = sig_a[i]; - if (b == ((bi ^ ci) ? State::S1 : State::S0)) { - module->connect(sig_y[i], a); - module->connect(sig_x[i], ci ? module->Not(NEW_ID, a).as_bit() : a); - module->connect(sig_co[i], ci ? State::S1 : State::S0); + for (i = 0; i < GetSize(sig_y); i++) { + if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) { + module->connect(sig_x[i], sub ? module->Not(NEW_ID, sig_a[i]).as_bit() : sig_a[i]); + module->connect(sig_y[i], sig_a[i]); + module->connect(sig_co[i], sub ? State::S1 : State::S0); } - else if (a == (ci ? State::S1 : State::S0)) { - module->connect(sig_y[i], bi ? module->Not(NEW_ID, b).as_bit() : b); - module->connect(sig_x[i], (bi ^ ci) ? module->Not(NEW_ID, b).as_bit() : b); - module->connect(sig_co[i], ci ? State::S1 : State::S0); + else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) { + module->connect(sig_x[i], sig_b[i]); + module->connect(sig_y[i], sig_b[i]); + module->connect(sig_co[i], State::S0); } else break; } if (i > 0) { cover("opt.opt_expr.fine.$alu"); - log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module)); - SigSpec new_a = sig_a.extract_end(i); - SigSpec new_b = sig_b.extract_end(i); - if (new_a.empty() && is_signed) - new_a = sig_a[i-1]; - if (new_b.empty() && is_signed) - new_b = sig_b[i-1]; - cell->setPort(ID::A, new_a); - cell->setPort(ID::B, new_b); - cell->setPort(ID::X, sig_x.extract_end(i)); + cell->setPort(ID::A, sig_a.extract_end(i)); + cell->setPort(ID::B, sig_b.extract_end(i)); + cell->setPort(ID(X), sig_x.extract_end(i)); cell->setPort(ID::Y, sig_y.extract_end(i)); - cell->setPort(ID::CO, sig_co.extract_end(i)); + cell->setPort(ID(CO), sig_co.extract_end(i)); cell->fixup_parameters(); did_something = true; } } } -skip_fine_alu: if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr), - ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow))) + ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow))) { RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec sig_b = cell->hasPort(ID::B) ? assign_map(cell->getPort(ID::B)) : RTLIL::SigSpec(); @@ -912,7 +736,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (0) { found_the_x_bit: cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", - "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$divfloor", "$modfloor", "$pow", cell->type.str()); + "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str()); if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt))) replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::State::Sx); else @@ -937,7 +761,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.trim", "$shiftx", "$shift", cell->type.str()); sig_a.remove(width, GetSize(sig_a)-width); cell->setPort(ID::A, sig_a); - cell->setParam(ID::A_WIDTH, width); + cell->setParam(ID(A_WIDTH), width); did_something = true; goto next_cell; } @@ -950,13 +774,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } - if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID::S))) != 0) { + if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID(S)))) != 0) { cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str()); log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module)); RTLIL::SigSpec tmp = cell->getPort(ID::A); cell->setPort(ID::A, cell->getPort(ID::B)); cell->setPort(ID::B, tmp); - cell->setPort(ID::S, invert_map.at(assign_map(cell->getPort(ID::S)))); + cell->setPort(ID(S), invert_map.at(assign_map(cell->getPort(ID(S))))); did_something = true; goto next_cell; } @@ -1016,15 +840,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match("01")) ACTION_DO_Y(1); if (input.match("10")) ACTION_DO_Y(1); if (input.match("11")) ACTION_DO_Y(0); - if (consume_x) { - if (input.match(" *")) ACTION_DO_Y(0); - if (input.match("* ")) ACTION_DO_Y(0); - } + if (input.match(" *")) ACTION_DO_Y(x); + if (input.match("* ")) ACTION_DO_Y(x); + if (input.match(" 0")) ACTION_DO(ID::Y, input.extract(1, 1)); + if (input.match("0 ")) ACTION_DO(ID::Y, input.extract(0, 1)); } if (cell->type == ID($_MUX_)) { RTLIL::SigSpec input; - input.append(cell->getPort(ID::S)); + input.append(cell->getPort(ID(S))); input.append(cell->getPort(ID::B)); input.append(cell->getPort(ID::A)); assign_map.apply(input); @@ -1038,7 +862,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->type = ID($_NOT_); cell->setPort(ID::A, input.extract(0, 1)); cell->unsetPort(ID::B); - cell->unsetPort(ID::S); + cell->unsetPort(ID(S)); goto next_cell; } if (input.match("11 ")) ACTION_DO_Y(1); @@ -1054,7 +878,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (cell->type.in(ID($_TBUF_), ID($tribuf))) { - RTLIL::SigSpec input = cell->getPort(cell->type == ID($_TBUF_) ? ID::E : ID::EN); + RTLIL::SigSpec input = cell->getPort(cell->type == ID($_TBUF_) ? ID(E) : ID(EN)); RTLIL::SigSpec a = cell->getPort(ID::A); assign_map.apply(input); assign_map.apply(a); @@ -1075,10 +899,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons RTLIL::SigSpec a = cell->getPort(ID::A); RTLIL::SigSpec b = cell->getPort(ID::B); - if (cell->parameters[ID::A_WIDTH].as_int() != cell->parameters[ID::B_WIDTH].as_int()) { - int width = max(cell->parameters[ID::A_WIDTH].as_int(), cell->parameters[ID::B_WIDTH].as_int()); - a.extend_u0(width, cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()); - b.extend_u0(width, cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()); + if (cell->parameters[ID(A_WIDTH)].as_int() != cell->parameters[ID(B_WIDTH)].as_int()) { + int width = max(cell->parameters[ID(A_WIDTH)].as_int(), cell->parameters[ID(B_WIDTH)].as_int()); + a.extend_u0(width, cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()); + b.extend_u0(width, cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()); } RTLIL::SigSpec new_a, new_b; @@ -1088,7 +912,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (a[i].wire == NULL && b[i].wire == NULL && a[i] != b[i] && a[i].data <= RTLIL::State::S1 && b[i].data <= RTLIL::State::S1) { cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S0 : RTLIL::State::S1); - new_y.extend_u0(cell->parameters[ID::Y_WIDTH].as_int(), false); + new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false); replace_cell(assign_map, module, cell, "isneq", ID::Y, new_y); goto next_cell; } @@ -1101,7 +925,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_a.size() == 0) { cover_list("opt.opt_expr.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S1 : RTLIL::State::S0); - new_y.extend_u0(cell->parameters[ID::Y_WIDTH].as_int(), false); + new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false); replace_cell(assign_map, module, cell, "empty", ID::Y, new_y); goto next_cell; } @@ -1110,13 +934,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.eqneq.resize", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); cell->setPort(ID::A, new_a); cell->setPort(ID::B, new_b); - cell->parameters[ID::A_WIDTH] = new_a.size(); - cell->parameters[ID::B_WIDTH] = new_b.size(); + cell->parameters[ID(A_WIDTH)] = new_a.size(); + cell->parameters[ID(B_WIDTH)] = new_b.size(); } } - if (cell->type.in(ID($eq), ID($ne)) && cell->parameters[ID::Y_WIDTH].as_int() == 1 && - cell->parameters[ID::A_WIDTH].as_int() == 1 && cell->parameters[ID::B_WIDTH].as_int() == 1) + if (cell->type.in(ID($eq), ID($ne)) && cell->parameters[ID(Y_WIDTH)].as_int() == 1 && + cell->parameters[ID(A_WIDTH)].as_int() == 1 && cell->parameters[ID(B_WIDTH)].as_int() == 1) { RTLIL::SigSpec a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec b = assign_map(cell->getPort(ID::B)); @@ -1140,8 +964,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->type = ID($not); - cell->parameters.erase(ID::B_WIDTH); - cell->parameters.erase(ID::B_SIGNED); + cell->parameters.erase(ID(B_WIDTH)); + cell->parameters.erase(ID(B_SIGNED)); cell->unsetPort(ID::B); did_something = true; } @@ -1154,33 +978,33 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell), - log_id(module), cell->type == ID($eq) ? "$logic_not" : "$reduce_bool"); + log_id(module), "$eq" ? "$logic_not" : "$reduce_bool"); cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool); if (assign_map(cell->getPort(ID::A)).is_fully_zero()) { cell->setPort(ID::A, cell->getPort(ID::B)); - cell->setParam(ID::A_SIGNED, cell->getParam(ID::B_SIGNED)); - cell->setParam(ID::A_WIDTH, cell->getParam(ID::B_WIDTH)); + cell->setParam(ID(A_SIGNED), cell->getParam(ID(B_SIGNED))); + cell->setParam(ID(A_WIDTH), cell->getParam(ID(B_WIDTH))); } cell->unsetPort(ID::B); - cell->unsetParam(ID::B_SIGNED); - cell->unsetParam(ID::B_WIDTH); + cell->unsetParam(ID(B_SIGNED)); + cell->unsetParam(ID(B_WIDTH)); did_something = true; goto next_cell; } if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && assign_map(cell->getPort(ID::B)).is_fully_const()) { - bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID::A_SIGNED).as_bool(); - int shift_bits = assign_map(cell->getPort(ID::B)).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID::B_SIGNED).as_bool()); + bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID(A_SIGNED)).as_bool(); + int shift_bits = assign_map(cell->getPort(ID::B)).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID(B_SIGNED)).as_bool()); if (cell->type.in(ID($shl), ID($sshl))) shift_bits *= -1; RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); - RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID::Y_WIDTH).as_int()); + RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID(Y_WIDTH)).as_int()); if (GetSize(sig_a) < GetSize(sig_y)) - sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID::A_SIGNED).as_bool()); + sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID(A_SIGNED)).as_bool()); for (int i = 0; i < GetSize(sig_y); i++) { int idx = i + shift_bits; @@ -1202,32 +1026,18 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } - if (consume_x) + if (!keepdc) { bool identity_wrt_a = false; bool identity_wrt_b = false; bool arith_inverse = false; - if (cell->type.in(ID($add), ID($sub), ID($alu), ID($or), ID($xor))) + if (cell->type.in(ID($add), ID($sub), ID($or), ID($xor))) { RTLIL::SigSpec a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec b = assign_map(cell->getPort(ID::B)); - bool sub = cell->type == ID($sub); - - if (cell->type == ID($alu)) { - RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID::CI)); - RTLIL::SigBit sig_bi = assign_map(cell->getPort(ID::BI)); - - sub = (sig_ci == State::S1 && sig_bi == State::S1); - - // If not a subtraction, yet there is a carry or B is inverted - // then no optimisation is possible as carry will not be constant - if (!sub && (sig_ci != State::S0 || sig_bi != State::S0)) - goto skip_identity; - } - - if (!sub && a.is_fully_const() && a.as_bool() == false) + if (cell->type != ID($sub) && a.is_fully_const() && a.as_bool() == false) identity_wrt_b = true; if (b.is_fully_const() && b.as_bool() == false) @@ -1247,10 +1057,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons RTLIL::SigSpec a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec b = assign_map(cell->getPort(ID::B)); - if (a.is_fully_const() && is_one_or_minus_one(a.as_const(), cell->getParam(ID::A_SIGNED).as_bool(), arith_inverse)) + if (a.is_fully_const() && is_one_or_minus_one(a.as_const(), cell->getParam(ID(A_SIGNED)).as_bool(), arith_inverse)) identity_wrt_b = true; else - if (b.is_fully_const() && is_one_or_minus_one(b.as_const(), cell->getParam(ID::B_SIGNED).as_bool(), arith_inverse)) + if (b.is_fully_const() && is_one_or_minus_one(b.as_const(), cell->getParam(ID(B_SIGNED)).as_bool(), arith_inverse)) identity_wrt_a = true; } @@ -1265,60 +1075,34 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (identity_wrt_a || identity_wrt_b) { if (identity_wrt_a) - cover_list("opt.opt_expr.identwrt.a", "$add", "$sub", "$alu", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str()); + cover_list("opt.opt_expr.identwrt.a", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str()); if (identity_wrt_b) - cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$alu", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str()); + cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with identity for port %c.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B'); - if (cell->type == ID($alu)) { - bool a_signed = cell->parameters[ID::A_SIGNED].as_bool(); - bool b_signed = cell->parameters[ID::B_SIGNED].as_bool(); - bool is_signed = a_signed && b_signed; - RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID::CI)); - int y_width = GetSize(cell->getPort(ID::Y)); - if (sig_ci == State::S1) { - /* sub, b is 0 */ - RTLIL::SigSpec a = cell->getPort(ID::A); - a.extend_u0(y_width, is_signed); - module->connect(cell->getPort(ID::X), module->Not(NEW_ID, a)); - module->connect(cell->getPort(ID::CO), RTLIL::Const(State::S1, y_width)); - } else { - /* add */ - RTLIL::SigSpec ab = cell->getPort(identity_wrt_a ? ID::A : ID::B); - ab.extend_u0(y_width, is_signed); - module->connect(cell->getPort(ID::X), ab); - module->connect(cell->getPort(ID::CO), RTLIL::Const(State::S0, y_width)); - } - cell->unsetPort(ID::BI); - cell->unsetPort(ID::CI); - cell->unsetPort(ID::X); - cell->unsetPort(ID::CO); - } - if (!identity_wrt_a) { cell->setPort(ID::A, cell->getPort(ID::B)); - cell->setParam(ID::A_WIDTH, cell->getParam(ID::B_WIDTH)); - cell->setParam(ID::A_SIGNED, cell->getParam(ID::B_SIGNED)); + cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH)); + cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED)); } cell->type = arith_inverse ? ID($neg) : ID($pos); cell->unsetPort(ID::B); - cell->parameters.erase(ID::B_WIDTH); - cell->parameters.erase(ID::B_SIGNED); + cell->parameters.erase(ID(B_WIDTH)); + cell->parameters.erase(ID(B_SIGNED)); cell->check(); did_something = true; goto next_cell; } } -skip_identity: if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == State::S0 && cell->getPort(ID::B) == State::S1) { cover_list("opt.opt_expr.mux_bool", "$mux", "$_MUX_", cell->type.str()); - replace_cell(assign_map, module, cell, "mux_bool", ID::Y, cell->getPort(ID::S)); + replace_cell(assign_map, module, cell, "mux_bool", ID::Y, cell->getPort(ID(S))); goto next_cell; } @@ -1326,15 +1110,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->getPort(ID::A) == State::S1 && cell->getPort(ID::B) == State::S0) { cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort(ID::A, cell->getPort(ID::S)); + cell->setPort(ID::A, cell->getPort(ID(S))); cell->unsetPort(ID::B); - cell->unsetPort(ID::S); + cell->unsetPort(ID(S)); if (cell->type == ID($mux)) { - Const width = cell->parameters[ID::WIDTH]; - cell->parameters[ID::A_WIDTH] = width; - cell->parameters[ID::Y_WIDTH] = width; - cell->parameters[ID::A_SIGNED] = 0; - cell->parameters.erase(ID::WIDTH); + Const width = cell->parameters[ID(WIDTH)]; + cell->parameters[ID(A_WIDTH)] = width; + cell->parameters[ID(Y_WIDTH)] = width; + cell->parameters[ID(A_SIGNED)] = 0; + cell->parameters.erase(ID(WIDTH)); cell->type = ID($not); } else cell->type = ID($_NOT_); @@ -1345,16 +1129,16 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == State::S0) { cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort(ID::A, cell->getPort(ID::S)); - cell->unsetPort(ID::S); + cell->setPort(ID::A, cell->getPort(ID(S))); + cell->unsetPort(ID(S)); if (cell->type == ID($mux)) { - Const width = cell->parameters[ID::WIDTH]; - cell->parameters[ID::A_WIDTH] = width; - cell->parameters[ID::B_WIDTH] = width; - cell->parameters[ID::Y_WIDTH] = width; - cell->parameters[ID::A_SIGNED] = 0; - cell->parameters[ID::B_SIGNED] = 0; - cell->parameters.erase(ID::WIDTH); + Const width = cell->parameters[ID(WIDTH)]; + cell->parameters[ID(A_WIDTH)] = width; + cell->parameters[ID(B_WIDTH)] = width; + cell->parameters[ID(Y_WIDTH)] = width; + cell->parameters[ID(A_SIGNED)] = 0; + cell->parameters[ID(B_SIGNED)] = 0; + cell->parameters.erase(ID(WIDTH)); cell->type = ID($and); } else cell->type = ID($_AND_); @@ -1365,16 +1149,16 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::B) == State::S1) { cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort(ID::B, cell->getPort(ID::S)); - cell->unsetPort(ID::S); + cell->setPort(ID::B, cell->getPort(ID(S))); + cell->unsetPort(ID(S)); if (cell->type == ID($mux)) { - Const width = cell->parameters[ID::WIDTH]; - cell->parameters[ID::A_WIDTH] = width; - cell->parameters[ID::B_WIDTH] = width; - cell->parameters[ID::Y_WIDTH] = width; - cell->parameters[ID::A_SIGNED] = 0; - cell->parameters[ID::B_SIGNED] = 0; - cell->parameters.erase(ID::WIDTH); + Const width = cell->parameters[ID(WIDTH)]; + cell->parameters[ID(A_WIDTH)] = width; + cell->parameters[ID(B_WIDTH)] = width; + cell->parameters[ID(Y_WIDTH)] = width; + cell->parameters[ID(A_SIGNED)] = 0; + cell->parameters[ID(B_SIGNED)] = 0; + cell->parameters.erase(ID(WIDTH)); cell->type = ID($or); } else cell->type = ID($_OR_); @@ -1386,14 +1170,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons RTLIL::SigSpec new_a, new_b, new_s; int width = GetSize(cell->getPort(ID::A)); if ((cell->getPort(ID::A).is_fully_undef() && cell->getPort(ID::B).is_fully_undef()) || - cell->getPort(ID::S).is_fully_undef()) { + cell->getPort(ID(S)).is_fully_undef()) { cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str()); replace_cell(assign_map, module, cell, "mux_undef", ID::Y, cell->getPort(ID::A)); goto next_cell; } - for (int i = 0; i < cell->getPort(ID::S).size(); i++) { + for (int i = 0; i < cell->getPort(ID(S)).size(); i++) { RTLIL::SigSpec old_b = cell->getPort(ID::B).extract(i*width, width); - RTLIL::SigSpec old_s = cell->getPort(ID::S).extract(i, 1); + RTLIL::SigSpec old_s = cell->getPort(ID(S)).extract(i, 1); if (old_b.is_fully_undef() || old_s.is_fully_undef()) continue; new_b.append(old_b); @@ -1415,48 +1199,48 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons replace_cell(assign_map, module, cell, "mux_sel01", ID::Y, new_s); goto next_cell; } - if (cell->getPort(ID::S).size() != new_s.size()) { + if (cell->getPort(ID(S)).size() != new_s.size()) { cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str()); log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n", - GetSize(cell->getPort(ID::S)) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module)); + GetSize(cell->getPort(ID(S))) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module)); cell->setPort(ID::A, new_a); cell->setPort(ID::B, new_b); - cell->setPort(ID::S, new_s); + cell->setPort(ID(S), new_s); if (new_s.size() > 1) { cell->type = ID($pmux); - cell->parameters[ID::S_WIDTH] = new_s.size(); + cell->parameters[ID(S_WIDTH)] = new_s.size(); } else { cell->type = ID($mux); - cell->parameters.erase(ID::S_WIDTH); + cell->parameters.erase(ID(S_WIDTH)); } did_something = true; } } #define FOLD_1ARG_CELL(_t) \ - if (cell->type == ID($##_t)) { \ + if (cell->type == "$" #_t) { \ RTLIL::SigSpec a = cell->getPort(ID::A); \ assign_map.apply(a); \ if (a.is_fully_const()) { \ RTLIL::Const dummy_arg(RTLIL::State::S0, 1); \ RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), dummy_arg, \ - cell->parameters[ID::A_SIGNED].as_bool(), false, \ - cell->parameters[ID::Y_WIDTH].as_int())); \ + cell->parameters[ID(A_SIGNED)].as_bool(), false, \ + cell->parameters[ID(Y_WIDTH)].as_int())); \ cover("opt.opt_expr.const.$" #_t); \ replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), ID::Y, y); \ goto next_cell; \ } \ } #define FOLD_2ARG_CELL(_t) \ - if (cell->type == ID($##_t)) { \ + if (cell->type == "$" #_t) { \ RTLIL::SigSpec a = cell->getPort(ID::A); \ RTLIL::SigSpec b = cell->getPort(ID::B); \ assign_map.apply(a), assign_map.apply(b); \ if (a.is_fully_const() && b.is_fully_const()) { \ RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const(), \ - cell->parameters[ID::A_SIGNED].as_bool(), \ - cell->parameters[ID::B_SIGNED].as_bool(), \ - cell->parameters[ID::Y_WIDTH].as_int())); \ + cell->parameters[ID(A_SIGNED)].as_bool(), \ + cell->parameters[ID(B_SIGNED)].as_bool(), \ + cell->parameters[ID(Y_WIDTH)].as_int())); \ cover("opt.opt_expr.const.$" #_t); \ replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID::Y, y); \ goto next_cell; \ @@ -1498,8 +1282,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons FOLD_2ARG_CELL(mul) FOLD_2ARG_CELL(div) FOLD_2ARG_CELL(mod) - FOLD_2ARG_CELL(divfloor) - FOLD_2ARG_CELL(modfloor) FOLD_2ARG_CELL(pow) FOLD_1ARG_CELL(pos) @@ -1507,7 +1289,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons // be very conservative with optimizing $mux cells as we do not want to break mux trees if (cell->type == ID($mux)) { - RTLIL::SigSpec input = assign_map(cell->getPort(ID::S)); + RTLIL::SigSpec input = assign_map(cell->getPort(ID(S))); RTLIL::SigSpec inA = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec inB = assign_map(cell->getPort(ID::B)); if (input.is_fully_const()) @@ -1518,8 +1300,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (!keepdc && cell->type == ID($mul)) { - bool a_signed = cell->parameters[ID::A_SIGNED].as_bool(); - bool b_signed = cell->parameters[ID::B_SIGNED].as_bool(); + bool a_signed = cell->parameters[ID(A_SIGNED)].as_bool(); + bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool(); bool swapped_ab = false; RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); @@ -1560,8 +1342,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (!swapped_ab) { cell->setPort(ID::A, cell->getPort(ID::B)); - cell->parameters.at(ID::A_WIDTH) = cell->parameters.at(ID::B_WIDTH); - cell->parameters.at(ID::A_SIGNED) = cell->parameters.at(ID::B_SIGNED); + cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH)); + cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED)); } std::vector new_b = RTLIL::SigSpec(i, 6); @@ -1570,8 +1352,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons new_b.pop_back(); cell->type = ID($shl); - cell->parameters[ID::B_WIDTH] = GetSize(new_b); - cell->parameters[ID::B_SIGNED] = false; + cell->parameters[ID(B_WIDTH)] = GetSize(new_b); + cell->parameters[ID(B_SIGNED)] = false; cell->setPort(ID::B, new_b); cell->check(); @@ -1579,46 +1361,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } } - - sig_a = assign_map(cell->getPort(ID::A)); - sig_b = assign_map(cell->getPort(ID::B)); - int a_zeros, b_zeros; - for (a_zeros = 0; a_zeros < GetSize(sig_a); a_zeros++) - if (sig_a[a_zeros] != RTLIL::State::S0) - break; - for (b_zeros = 0; b_zeros < GetSize(sig_b); b_zeros++) - if (sig_b[b_zeros] != RTLIL::State::S0) - break; - if (a_zeros || b_zeros) { - int y_zeros = a_zeros + b_zeros; - cover("opt.opt_expr.mul_low_zeros"); - - log_debug("Removing low %d A and %d B bits from cell `%s' in module `%s'.\n", - a_zeros, b_zeros, cell->name.c_str(), module->name.c_str()); - - if (a_zeros) { - cell->setPort(ID::A, sig_a.extract_end(a_zeros)); - cell->parameters[ID::A_WIDTH] = GetSize(sig_a) - a_zeros; - } - if (b_zeros) { - cell->setPort(ID::B, sig_b.extract_end(b_zeros)); - cell->parameters[ID::B_WIDTH] = GetSize(sig_b) - b_zeros; - } - cell->setPort(ID::Y, sig_y.extract_end(y_zeros)); - cell->parameters[ID::Y_WIDTH] = GetSize(sig_y) - y_zeros; - module->connect(RTLIL::SigSig(sig_y.extract(0, y_zeros), RTLIL::SigSpec(0, y_zeros))); - cell->check(); - - did_something = true; - goto next_cell; - } } - if (!keepdc && cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) + if (!keepdc && cell->type.in(ID($div), ID($mod))) { - bool a_signed = cell->parameters[ID::A_SIGNED].as_bool(); - bool b_signed = cell->parameters[ID::B_SIGNED].as_bool(); - SigSpec sig_a = assign_map(cell->getPort(ID::A)); + bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool(); SigSpec sig_b = assign_map(cell->getPort(ID::B)); SigSpec sig_y = assign_map(cell->getPort(ID::Y)); @@ -1643,13 +1390,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (int i = 1; i < (b_signed ? sig_b.size()-1 : sig_b.size()); i++) if (b_val == (1 << i)) { - if (cell->type.in(ID($div), ID($divfloor))) + if (cell->type == ID($div)) { cover("opt.opt_expr.div_shift"); - bool is_truncating = cell->type == ID($div); - log_debug("Replacing %s-divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n", - is_truncating ? "truncating" : "flooring", + log_debug("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n", b_val, cell->name.c_str(), module->name.c_str(), i); std::vector new_b = RTLIL::SigSpec(i, 6); @@ -1657,35 +1402,17 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0) new_b.pop_back(); - cell->type = ID($sshr); - cell->parameters[ID::B_WIDTH] = GetSize(new_b); - cell->parameters[ID::B_SIGNED] = false; + cell->type = ID($shr); + cell->parameters[ID(B_WIDTH)] = GetSize(new_b); + cell->parameters[ID(B_SIGNED)] = false; cell->setPort(ID::B, new_b); - - // Truncating division is the same as flooring division, except when - // the result is negative and there is a remainder - then trunc = floor + 1 - if (is_truncating && a_signed) { - Wire *flooring = module->addWire(NEW_ID, sig_y.size()); - cell->setPort(ID::Y, flooring); - - Wire *result_neg = module->addWire(NEW_ID); - module->addXor(NEW_ID, sig_a[sig_a.size()-1], sig_b[sig_b.size()-1], result_neg); - Wire *rem_nonzero = module->addWire(NEW_ID); - module->addReduceOr(NEW_ID, sig_a.extract(0, i), rem_nonzero); - Wire *should_add = module->addWire(NEW_ID); - module->addAnd(NEW_ID, result_neg, rem_nonzero, should_add); - module->addAdd(NEW_ID, flooring, should_add, sig_y); - } - cell->check(); } - else if (cell->type.in(ID($mod), ID($modfloor))) + else { cover("opt.opt_expr.mod_mask"); - bool is_truncating = cell->type == ID($mod); - log_debug("Replacing %s-modulo-by-%d cell `%s' in module `%s' with bitmask.\n", - is_truncating ? "truncating" : "flooring", + log_debug("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n", b_val, cell->name.c_str(), module->name.c_str()); std::vector new_b = RTLIL::SigSpec(State::S1, i); @@ -1694,26 +1421,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons new_b.push_back(State::S0); cell->type = ID($and); - cell->parameters[ID::B_WIDTH] = GetSize(new_b); + cell->parameters[ID(B_WIDTH)] = GetSize(new_b); cell->setPort(ID::B, new_b); - - // truncating modulo has the same masked bits as flooring modulo, but - // the sign bits are those of A (except when R=0) - if (is_truncating && a_signed) { - Wire *flooring = module->addWire(NEW_ID, sig_y.size()); - cell->setPort(ID::Y, flooring); - SigSpec truncating = SigSpec(flooring).extract(0, i); - - Wire *rem_nonzero = module->addWire(NEW_ID); - module->addReduceOr(NEW_ID, truncating, rem_nonzero); - SigSpec a_sign = sig_a[sig_a.size()-1]; - Wire *extend_bit = module->addWire(NEW_ID); - module->addAnd(NEW_ID, a_sign, rem_nonzero, extend_bit); - - truncating.append(extend_bit); - module->addPos(NEW_ID, truncating, sig_y, true); - } - cell->check(); } @@ -1723,99 +1432,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - // Find places in $alu cell where the carry is constant, and split it at these points. - if (do_fine && !keepdc && cell->type == ID($alu)) - { - bool a_signed = cell->parameters[ID::A_SIGNED].as_bool(); - bool b_signed = cell->parameters[ID::B_SIGNED].as_bool(); - bool is_signed = a_signed && b_signed; - - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); - RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); - RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y)); - RTLIL::SigSpec sig_bi = assign_map(cell->getPort(ID::BI)); - if (GetSize(sig_a) == 0) - sig_a = State::S0; - if (GetSize(sig_b) == 0) - sig_b = State::S0; - sig_a.extend_u0(GetSize(sig_y), is_signed); - sig_b.extend_u0(GetSize(sig_y), is_signed); - - if (sig_bi != State::S0 && sig_bi != State::S1) - goto skip_alu_split; - - std::vector> split_points; - - for (int i = 0; i < GetSize(sig_y); i++) { - SigBit bit_a = sig_a[i]; - SigBit bit_b = sig_b[i]; - if (bit_a != State::S0 && bit_a != State::S1) - continue; - if (bit_b != State::S0 && bit_b != State::S1) - continue; - if (sig_bi == State::S1) { - if (bit_b == State::S0) - bit_b = State::S1; - else - bit_b = State::S0; - } - if (bit_a != bit_b) - continue; - split_points.push_back(std::make_pair(i + 1, bit_a.data)); - } - - if (split_points.empty() || split_points[0].first == GetSize(sig_y)) - goto skip_alu_split; - - for (auto &p : split_points) - log_debug("Splitting $alu cell `%s' in module `%s' at const-carry point %d.\n", - cell->name.c_str(), module->name.c_str(), p.first); - - if (split_points.back().first != GetSize(sig_y)) - split_points.push_back(std::make_pair(GetSize(sig_y), State::Sx)); - - RTLIL::SigSpec sig_ci = assign_map(cell->getPort(ID::CI)); - int prev = 0; - RTLIL::SigSpec sig_x = assign_map(cell->getPort(ID::X)); - RTLIL::SigSpec sig_co = assign_map(cell->getPort(ID::CO)); - - for (auto &p : split_points) { - int cur = p.first; - int sz = cur - prev; - bool last = cur == GetSize(sig_y); - - RTLIL::Cell *c = module->addCell(NEW_ID, cell->type); - c->setPort(ID::A, sig_a.extract(prev, sz)); - c->setPort(ID::B, sig_b.extract(prev, sz)); - c->setPort(ID::BI, sig_bi); - c->setPort(ID::CI, sig_ci); - c->setPort(ID::Y, sig_y.extract(prev, sz)); - c->setPort(ID::X, sig_x.extract(prev, sz)); - RTLIL::SigSpec new_co = sig_co.extract(prev, sz); - if (p.second != State::Sx) { - module->connect(new_co[sz-1], p.second); - RTLIL::Wire *dummy = module->addWire(NEW_ID); - new_co[sz-1] = dummy; - } - c->setPort(ID::CO, new_co); - c->parameters[ID::A_WIDTH] = sz; - c->parameters[ID::B_WIDTH] = sz; - c->parameters[ID::Y_WIDTH] = sz; - c->parameters[ID::A_SIGNED] = last ? a_signed : false; - c->parameters[ID::B_SIGNED] = last ? b_signed : false; - - prev = p.first; - sig_ci = p.second; - } - - cover("opt.opt_expr.alu_split"); - module->remove(cell); - - did_something = true; - goto next_cell; - } -skip_alu_split: - // remove redundant pairs of bits in ==, ===, !=, and !== // replace cell with const driver if inputs can't be equal if (do_fine && cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex))) @@ -1826,10 +1442,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons contradiction_cache.promote(State::S0); contradiction_cache.promote(State::S1); - int a_width = cell->getParam(ID::A_WIDTH).as_int(); - int b_width = cell->getParam(ID::B_WIDTH).as_int(); + int a_width = cell->getParam(ID(A_WIDTH)).as_int(); + int b_width = cell->getParam(ID(B_WIDTH)).as_int(); - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); int width = is_signed ? std::min(a_width, b_width) : std::max(a_width, b_width); SigSpec sig_a = cell->getPort(ID::A); @@ -1883,8 +1499,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->setPort(ID::A, sig_a); cell->setPort(ID::B, sig_b); - cell->setParam(ID::A_WIDTH, GetSize(sig_a)); - cell->setParam(ID::B_WIDTH, GetSize(sig_b)); + cell->setParam(ID(A_WIDTH), GetSize(sig_a)); + cell->setParam(ID(B_WIDTH), GetSize(sig_b)); did_something = true; goto next_cell; @@ -1897,9 +1513,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons IdString cmp_type = cell->type; SigSpec var_sig = cell->getPort(ID::A); SigSpec const_sig = cell->getPort(ID::B); - int var_width = cell->parameters[ID::A_WIDTH].as_int(); - int const_width = cell->parameters[ID::B_WIDTH].as_int(); - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); + int var_width = cell->parameters[ID(A_WIDTH)].as_int(); + int const_width = cell->parameters[ID(B_WIDTH)].as_int(); + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); if (!const_sig.is_fully_const()) { @@ -1974,7 +1590,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } int const_bit_set = get_highest_hot_index(const_sig); - if (const_bit_set >= var_width) + if(const_bit_set >= var_width) { string cmp_name; if (cmp_type == ID($lt) || cmp_type == ID($le)) @@ -2038,7 +1654,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons struct OptExprPass : public Pass { OptExprPass() : Pass("opt_expr", "perform const folding and simple expression rewriting") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -2072,7 +1688,7 @@ struct OptExprPass : public Pass { log(" replaced by 'a'. the -keepdc option disables all such optimizations.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool mux_undef = false; bool mux_bool = false; @@ -2121,14 +1737,13 @@ struct OptExprPass : public Pass { } extra_args(args, argidx, design); - CellTypes ct(design); for (auto module : design->selected_modules()) { log("Optimizing module %s.\n", log_id(module)); if (undriven) { did_something = false; - replace_undriven(module, ct); + replace_undriven(design, module); if (did_something) design->scratchpad_set_bool("opt.did_something", true); } @@ -2136,12 +1751,11 @@ struct OptExprPass : public Pass { do { do { did_something = false; - replace_const_cells(design, module, false /* consume_x */, mux_undef, mux_bool, do_fine, keepdc, clkinv); + replace_const_cells(design, module, false, mux_undef, mux_bool, do_fine, keepdc, clkinv); if (did_something) design->scratchpad_set_bool("opt.did_something", true); } while (did_something); - if (!keepdc) - replace_const_cells(design, module, true /* consume_x */, mux_undef, mux_bool, do_fine, keepdc, clkinv); + replace_const_cells(design, module, true, mux_undef, mux_bool, do_fine, keepdc, clkinv); if (did_something) design->scratchpad_set_bool("opt.did_something", true); } while (did_something); diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 07a91af8a11..c4f2787061a 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -41,8 +41,8 @@ struct OptLutWorker bool evaluate_lut(RTLIL::Cell *lut, dict inputs) { SigSpec lut_input = sigmap(lut->getPort(ID::A)); - int lut_width = lut->getParam(ID::WIDTH).as_int(); - Const lut_table = lut->getParam(ID::LUT); + int lut_width = lut->getParam(ID(WIDTH)).as_int(); + Const lut_table = lut->getParam(ID(LUT)); int lut_index = 0; for (int i = 0; i < lut_width; i++) @@ -107,7 +107,7 @@ struct OptLutWorker if (lut_output.wire->get_bool_attribute(ID::keep)) continue; - int lut_width = cell->getParam(ID::WIDTH).as_int(); + int lut_width = cell->getParam(ID(WIDTH)).as_int(); SigSpec lut_input = cell->getPort(ID::A); int lut_arity = 0; @@ -305,7 +305,7 @@ struct OptLutWorker auto lutA = worklist.pop(); SigSpec lutA_input = sigmap(lutA->getPort(ID::A)); SigSpec lutA_output = sigmap(lutA->getPort(ID::Y)[0]); - int lutA_width = lutA->getParam(ID::WIDTH).as_int(); + int lutA_width = lutA->getParam(ID(WIDTH)).as_int(); int lutA_arity = luts_arity[lutA]; pool &lutA_dlogic_inputs = luts_dlogic_inputs[lutA]; @@ -323,7 +323,7 @@ struct OptLutWorker auto lutB = port.cell; SigSpec lutB_input = sigmap(lutB->getPort(ID::A)); SigSpec lutB_output = sigmap(lutB->getPort(ID::Y)[0]); - int lutB_width = lutB->getParam(ID::WIDTH).as_int(); + int lutB_width = lutB->getParam(ID(WIDTH)).as_int(); int lutB_arity = luts_arity[lutB]; pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; @@ -372,7 +372,7 @@ struct OptLutWorker log_debug(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); else if (lutB_dlogic_inputs.size() > 0) log_debug(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); - else if (lutB->get_bool_attribute(ID::lut_keep)) + else if (lutB->get_bool_attribute(ID(lut_keep))) log_debug(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); else combine_mask |= COMBINE_A; @@ -380,7 +380,7 @@ struct OptLutWorker log_debug(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); else if (lutA_dlogic_inputs.size() > 0) log_debug(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); - else if (lutA->get_bool_attribute(ID::lut_keep)) + else if (lutA->get_bool_attribute(ID(lut_keep))) log_debug(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); else combine_mask |= COMBINE_B; @@ -440,7 +440,7 @@ struct OptLutWorker lutR_unique.insert(bit); } - int lutM_width = lutM->getParam(ID::WIDTH).as_int(); + int lutM_width = lutM->getParam(ID(WIDTH)).as_int(); SigSpec lutM_input = sigmap(lutM->getPort(ID::A)); std::vector lutM_new_inputs; for (int i = 0; i < lutM_width; i++) @@ -482,11 +482,11 @@ struct OptLutWorker lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); } - log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID::LUT).as_string().c_str()); - log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID::LUT).as_string().c_str()); + log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID(LUT)).as_string().c_str()); + log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID(LUT)).as_string().c_str()); log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); - lutM->setParam(ID::LUT, lutM_new_table); + lutM->setParam(ID(LUT), lutM_new_table); lutM->setPort(ID::A, lutM_new_inputs); lutM->setPort(ID::Y, lutB_output); @@ -520,7 +520,7 @@ static void split(std::vector &tokens, const std::string &text, cha struct OptLutPass : public Pass { OptLutPass() : Pass("opt_lut", "optimize LUT cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -538,7 +538,7 @@ struct OptLutPass : public Pass { log(" only perform the first N combines, then stop. useful for debugging.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n"); diff --git a/passes/opt/opt_lut_ins.cc b/passes/opt/opt_lut_ins.cc deleted file mode 100644 index bb40e1e552c..00000000000 --- a/passes/opt/opt_lut_ins.cc +++ /dev/null @@ -1,278 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * 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 - -struct OptLutInsPass : public Pass { - OptLutInsPass() : Pass("opt_lut_ins", "discard unused LUT inputs") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" opt_lut_ins [options] [selection]\n"); - log("\n"); - log("This pass removes unused inputs from LUT cells (that is, inputs that can not\n"); - log("influence the output signal given this LUT's value). While such LUTs cannot\n"); - log("be directly emitted by ABC, they can be a result of various post-ABC\n"); - log("transformations, such as mapping wide LUTs (not all sub-LUTs will use the\n"); - log("full set of inputs) or optimizations such as xilinx_dffopt.\n"); - log("\n"); - log(" -tech \n"); - log(" Instead of generic $lut cells, operate on LUT cells specific\n"); - log(" to the given technology. Valid values are: xilinx, ecp5, gowin.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - log_header(design, "Executing OPT_LUT_INS pass (discard unused LUT inputs).\n"); - string techname; - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-tech" && argidx+1 < args.size()) { - techname = args[++argidx]; - continue; - } - break; - } - extra_args(args, argidx, design); - - if (techname != "" && techname != "xilinx" && techname != "ecp5" && techname != "gowin") - log_cmd_error("Unsupported technology: '%s'\n", techname.c_str()); - - for (auto module : design->selected_modules()) - { - log("Optimizing LUTs in %s.\n", log_id(module)); - - std::vector remove_cells; - // Gather LUTs. - for (auto cell : module->selected_cells()) - { - if (cell->get_bool_attribute(ID::keep)) - continue; - Const lut; - std::vector inputs; - std::vector output; - bool ignore_const = false; - if (techname == "") { - if (cell->type != ID($lut)) - continue; - inputs = cell->getPort(ID::A).bits(); - output = cell->getPort(ID::Y); - lut = cell->getParam(ID::LUT); - } else if (techname == "xilinx" || techname == "gowin") { - if (cell->type == ID(LUT1)) { - inputs = { - cell->getPort(ID(I0)), - }; - } else if (cell->type == ID(LUT2)) { - inputs = { - cell->getPort(ID(I0)), - cell->getPort(ID(I1)), - }; - } else if (cell->type == ID(LUT3)) { - inputs = { - cell->getPort(ID(I0)), - cell->getPort(ID(I1)), - cell->getPort(ID(I2)), - }; - } else if (cell->type == ID(LUT4)) { - inputs = { - cell->getPort(ID(I0)), - cell->getPort(ID(I1)), - cell->getPort(ID(I2)), - cell->getPort(ID(I3)), - }; - } else if (cell->type == ID(LUT5)) { - inputs = { - cell->getPort(ID(I0)), - cell->getPort(ID(I1)), - cell->getPort(ID(I2)), - cell->getPort(ID(I3)), - cell->getPort(ID(I4)), - }; - } else if (cell->type == ID(LUT6)) { - inputs = { - cell->getPort(ID(I0)), - cell->getPort(ID(I1)), - cell->getPort(ID(I2)), - cell->getPort(ID(I3)), - cell->getPort(ID(I4)), - cell->getPort(ID(I5)), - }; - } else { - // Not a LUT. - continue; - } - lut = cell->getParam(ID::INIT); - if (techname == "xilinx") - output = cell->getPort(ID::O); - else - output = cell->getPort(ID::F); - } else if (techname == "ecp5") { - if (cell->type == ID(LUT4)) { - inputs = { - cell->getPort(ID::A), - cell->getPort(ID::B), - cell->getPort(ID::C), - cell->getPort(ID::D), - }; - lut = cell->getParam(ID::INIT); - output = cell->getPort(ID(Z)); - ignore_const = true; - } else { - // Not a LUT. - continue; - } - } - std::vector swizzle; - std::vector new_inputs; - bool doit = false; - for (int i = 0; i < GetSize(inputs); i++) { - SigBit input = inputs[i]; - if (!input.wire) { - if (input.data == State::S1) - swizzle.push_back(-2); - else - swizzle.push_back(-1); - // For ECP5, smaller LUTs are - // implemented as LUT4s with - // extra const inputs. Do not - // consider that to be a reason - // to redo a LUT. - if (!ignore_const) - doit = true; - } else { - bool redundant = true; - for (int j = 0; j < GetSize(lut); j++) { - if (lut[j] != lut[j ^ 1 << i]) - redundant = false; - } - if (redundant) { - swizzle.push_back(-1); - doit = true; - } else { - swizzle.push_back(GetSize(new_inputs)); - new_inputs.push_back(input); - } - } - } - if (!doit) - continue; - log(" Optimizing lut %s (%d -> %d)\n", log_id(cell), GetSize(inputs), GetSize(new_inputs)); - if (techname == "ecp5") { - // Pad the LUT to 4 inputs, adding consts from the front. - int extra = 4 - GetSize(new_inputs); - log_assert(extra >= 0); - if (extra) { - for (int i = 0; i < extra; i++) - new_inputs.insert(new_inputs.begin(), State::S0); - for (auto &swz : swizzle) - if (swz >= 0) - swz += extra; - } - } - Const new_lut(0, 1 << GetSize(new_inputs)); - for (int i = 0; i < GetSize(new_lut); i++) { - int lidx = 0; - for (int j = 0; j < GetSize(inputs); j++) { - int val; - if (swizzle[j] == -2) { - val = 1; - } else if (swizzle[j] == -1) { - val = 0; - } else { - val = (i >> swizzle[j]) & 1; - } - lidx |= val << j; - } - new_lut[i] = lut[lidx]; - } - // For ecp5, do not replace with a const driver — the nextpnr - // packer requires a complete set of LUTs for wide LUT muxes. - if (new_inputs.empty() && techname != "ecp5") { - // const driver. - remove_cells.push_back(cell); - module->connect(output, new_lut[0]); - } else { - if (techname == "") { - cell->setParam(ID::LUT, new_lut); - cell->setParam(ID::WIDTH, GetSize(new_inputs)); - cell->setPort(ID::A, new_inputs); - } else if (techname == "ecp5") { - log_assert(GetSize(new_inputs) == 4); - cell->setParam(ID::INIT, new_lut); - cell->setPort(ID::A, new_inputs[0]); - cell->setPort(ID::B, new_inputs[1]); - cell->setPort(ID::C, new_inputs[2]); - cell->setPort(ID::D, new_inputs[3]); - } else { - // xilinx, gowin - cell->setParam(ID::INIT, new_lut); - if (techname == "xilinx") - log_assert(GetSize(new_inputs) <= 6); - else - log_assert(GetSize(new_inputs) <= 4); - if (GetSize(new_inputs) == 1) - cell->type = ID(LUT1); - else if (GetSize(new_inputs) == 2) - cell->type = ID(LUT2); - else if (GetSize(new_inputs) == 3) - cell->type = ID(LUT3); - else if (GetSize(new_inputs) == 4) - cell->type = ID(LUT4); - else if (GetSize(new_inputs) == 5) - cell->type = ID(LUT5); - else if (GetSize(new_inputs) == 6) - cell->type = ID(LUT6); - else - log_assert(0); - cell->unsetPort(ID(I0)); - cell->unsetPort(ID(I1)); - cell->unsetPort(ID(I2)); - cell->unsetPort(ID(I3)); - cell->unsetPort(ID(I4)); - cell->unsetPort(ID(I5)); - cell->setPort(ID(I0), new_inputs[0]); - if (GetSize(new_inputs) >= 2) - cell->setPort(ID(I1), new_inputs[1]); - if (GetSize(new_inputs) >= 3) - cell->setPort(ID(I2), new_inputs[2]); - if (GetSize(new_inputs) >= 4) - cell->setPort(ID(I3), new_inputs[3]); - if (GetSize(new_inputs) >= 5) - cell->setPort(ID(I4), new_inputs[4]); - if (GetSize(new_inputs) >= 6) - cell->setPort(ID(I5), new_inputs[5]); - } - } - } - for (auto cell : remove_cells) - module->remove(cell); - } - } -} XilinxDffOptPass; - -PRIVATE_NAMESPACE_END - diff --git a/passes/opt/opt_mem.cc b/passes/opt/opt_mem.cc index 24df1356b35..98d3551ebe5 100644 --- a/passes/opt/opt_mem.cc +++ b/passes/opt/opt_mem.cc @@ -45,17 +45,17 @@ struct OptMemWorker for (auto cell : module->cells()) { if (cell->type == ID($memrd)) { - IdString id = cell->getParam(ID::MEMID).decode_string(); + IdString id = cell->getParam(ID(MEMID)).decode_string(); memrd.at(id).push_back(cell->name); } if (cell->type == ID($memwr)) { - IdString id = cell->getParam(ID::MEMID).decode_string(); + IdString id = cell->getParam(ID(MEMID)).decode_string(); memwr.at(id).push_back(cell->name); } if (cell->type == ID($meminit)) { - IdString id = cell->getParam(ID::MEMID).decode_string(); + IdString id = cell->getParam(ID(MEMID)).decode_string(); meminit.at(id).push_back(cell->name); } } @@ -97,7 +97,7 @@ struct OptMemWorker struct OptMemPass : public Pass { OptMemPass() : Pass("opt_mem", "optimize memories") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -106,7 +106,7 @@ struct OptMemPass : public Pass { log("This pass performs various optimizations on memories in the design.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_MEM pass (optimize memories).\n"); diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index a95aa74c19b..aaea6159eb3 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -26,6 +26,7 @@ #include #include +#define USE_CELL_HASH_CACHE USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -40,11 +41,13 @@ struct OptMergeWorker CellTypes ct; int total_count; - SHA1 checksum; +#ifdef USE_CELL_HASH_CACHE + dict cell_hash_cache; +#endif static void sort_pmux_conn(dict &conn) { - SigSpec sig_s = conn.at(ID::S); + SigSpec sig_s = conn.at(ID(S)); SigSpec sig_b = conn.at(ID::B); int s_width = GetSize(sig_s); @@ -56,15 +59,16 @@ struct OptMergeWorker std::sort(sb_pairs.begin(), sb_pairs.end()); - conn[ID::S] = SigSpec(); + conn[ID(S)] = SigSpec(); conn[ID::B] = SigSpec(); for (auto &it : sb_pairs) { - conn[ID::S].append(it.first); + conn[ID(S)].append(it.first); conn[ID::B].append(it.second); } } +#ifdef USE_CELL_HASH_CACHE std::string int_to_hash_string(unsigned int v) { if (v == 0) @@ -79,9 +83,14 @@ struct OptMergeWorker std::string hash_cell_parameters_and_connections(const RTLIL::Cell *cell) { - vector hash_conn_strings; + if (cell_hash_cache.count(cell) > 0) + return cell_hash_cache[cell]; + std::string hash_string = cell->type.str() + "\n"; + for (auto &it : cell->parameters) + hash_string += "P " + it.first.str() + "=" + it.second.as_string() + "\n"; + const dict *conn = &cell->connections(); dict alt_conn; @@ -110,25 +119,18 @@ struct OptMergeWorker alt_conn = *conn; assign_map.apply(alt_conn.at(ID::A)); assign_map.apply(alt_conn.at(ID::B)); - assign_map.apply(alt_conn.at(ID::S)); + assign_map.apply(alt_conn.at(ID(S))); sort_pmux_conn(alt_conn); conn = &alt_conn; } + vector hash_conn_strings; + for (auto &it : *conn) { - RTLIL::SigSpec sig; - if (cell->output(it.first)) { - if (it.first == ID::Q && RTLIL::builtin_ff_cell_types().count(cell->type)) { - // For the 'Q' output of state elements, - // use its (* init *) attribute value - for (const auto &b : dff_init_map(it.second)) - sig.append(b.wire ? State::Sx : b); - } - else - continue; - } - else - sig = assign_map(it.second); + if (cell->output(it.first)) + continue; + RTLIL::SigSpec sig = it.second; + assign_map.apply(sig); string s = "C " + it.first.str() + "="; for (auto &chunk : sig.chunks()) { if (chunk.wire) @@ -141,59 +143,50 @@ struct OptMergeWorker hash_conn_strings.push_back(s + "\n"); } - for (auto &it : cell->parameters) - hash_conn_strings.push_back("P " + it.first.str() + "=" + it.second.as_string() + "\n"); - std::sort(hash_conn_strings.begin(), hash_conn_strings.end()); for (auto it : hash_conn_strings) hash_string += it; - checksum.update(hash_string); - return checksum.final(); + cell_hash_cache[cell] = sha1(hash_string); + return cell_hash_cache[cell]; } +#endif - bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) + bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2, bool <) { - log_assert(cell1 != cell2); - if (cell1->type != cell2->type) return false; - - if (cell1->parameters != cell2->parameters) - return false; - - if (cell1->connections_.size() != cell2->connections_.size()) - return false; - for (const auto &it : cell1->connections_) - if (!cell2->connections_.count(it.first)) - return false; - - decltype(Cell::connections_) conn1, conn2; - conn1.reserve(cell1->connections_.size()); - conn2.reserve(cell1->connections_.size()); - - for (const auto &it : cell1->connections_) { - if (cell1->output(it.first)) { - if (it.first == ID::Q && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") || - cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH") || cell1->type.begins_with("$_SR_") || - cell1->type.in(ID($adff), ID($sr), ID($ff), ID($_FF_)))) { - // For the 'Q' output of state elements, - // use the (* init *) attribute value - auto &sig1 = conn1[it.first]; - for (const auto &b : dff_init_map(it.second)) - sig1.append(b.wire ? State::Sx : b); - auto &sig2 = conn2[it.first]; - for (const auto &b : dff_init_map(cell2->getPort(it.first))) - sig2.append(b.wire ? State::Sx : b); - } - else { - conn1[it.first] = RTLIL::SigSpec(); - conn2[it.first] = RTLIL::SigSpec(); - } - } - else { - conn1[it.first] = assign_map(it.second); - conn2[it.first] = assign_map(cell2->getPort(it.first)); - } +#ifdef USE_CELL_HASH_CACHE + std::string hash1 = hash_cell_parameters_and_connections(cell1); + std::string hash2 = hash_cell_parameters_and_connections(cell2); + + if (hash1 != hash2) { + lt = hash1 < hash2; + return true; + } +#endif + + if (cell1->parameters != cell2->parameters) { + std::map p1(cell1->parameters.begin(), cell1->parameters.end()); + std::map p2(cell2->parameters.begin(), cell2->parameters.end()); + lt = p1 < p2; + return true; + } + + dict conn1 = cell1->connections(); + dict conn2 = cell2->connections(); + + for (auto &it : conn1) { + if (cell1->output(it.first)) + it.second = RTLIL::SigSpec(); + else + assign_map.apply(it.second); + } + + for (auto &it : conn2) { + if (cell2->output(it.first)) + it.second = RTLIL::SigSpec(); + else + assign_map.apply(it.second); } 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) || @@ -222,9 +215,52 @@ struct OptMergeWorker sort_pmux_conn(conn2); } - return conn1 == conn2; + if (conn1 != conn2) { + std::map c1(conn1.begin(), conn1.end()); + std::map c2(conn2.begin(), conn2.end()); + lt = c1 < c2; + return true; + } + + if (cell1->type.begins_with("$") && conn1.count(ID(Q)) != 0) { + std::vector q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector(); + std::vector q2 = dff_init_map(cell2->getPort(ID(Q))).to_sigbit_vector(); + for (size_t i = 0; i < q1.size(); i++) + if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) { + lt = q1.at(i) < q2.at(i); + return true; + } + } + + return false; } + bool compare_cells(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) + { + if (cell1->type != cell2->type) + return cell1->type < cell2->type; + + if ((!mode_share_all && !ct.cell_known(cell1->type)) || !cell1->known()) + return cell1 < cell2; + + if (cell1->has_keep_attr() || cell2->has_keep_attr()) + return cell1 < cell2; + + bool lt; + if (compare_cell_parameters_and_connections(cell1, cell2, lt)) + return lt; + + return false; + } + + struct CompareCells { + OptMergeWorker *that; + CompareCells(OptMergeWorker *that) : that(that) {} + bool operator()(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) const { + return that->compare_cells(cell1, cell2); + } + }; + OptMergeWorker(RTLIL::Design *design, RTLIL::Module *module, bool mode_nomux, bool mode_share_all) : design(design), module(module), assign_map(module), mode_share_all(mode_share_all) { @@ -251,8 +287,8 @@ struct OptMergeWorker dff_init_map.set(module); for (auto &it : module->wires_) - if (it.second->attributes.count(ID::init) != 0) { - Const initval = it.second->attributes.at(ID::init); + if (it.second->attributes.count(ID(init)) != 0) { + Const initval = it.second->attributes.at(ID(init)); for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++) if (initval[i] == State::S0 || initval[i] == State::S1) dff_init_map.add(SigBit(it.second, i), initval[i]); @@ -261,6 +297,9 @@ struct OptMergeWorker bool did_something = true; while (did_something) { +#ifdef USE_CELL_HASH_CACHE + cell_hash_cache.clear(); +#endif std::vector cells; cells.reserve(module->cells_.size()); for (auto &it : module->cells_) { @@ -271,51 +310,29 @@ struct OptMergeWorker } did_something = false; - dict sharemap; + std::map sharemap(CompareCells(this)); for (auto cell : cells) { - if ((!mode_share_all && !ct.cell_known(cell->type)) || !cell->known()) - continue; - - auto hash = hash_cell_parameters_and_connections(cell); - auto r = sharemap.insert(std::make_pair(hash, cell)); - if (!r.second) { - if (compare_cell_parameters_and_connections(cell, r.first->second)) { - if (cell->has_keep_attr()) { - if (r.first->second->has_keep_attr()) - continue; - std::swap(r.first->second, cell); - } - - - did_something = true; - log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), r.first->second->name.c_str()); - for (auto &it : cell->connections()) { - if (cell->output(it.first)) { - RTLIL::SigSpec other_sig = r.first->second->getPort(it.first); - log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(), - log_signal(it.second), log_signal(other_sig)); - module->connect(RTLIL::SigSig(it.second, other_sig)); - assign_map.add(it.second, other_sig); - - if (it.first == ID::Q && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") || - cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") || - cell->type.in(ID($adff), ID($sr), ID($ff), ID($_FF_)))) { - for (auto c : it.second.chunks()) { - auto jt = c.wire->attributes.find(ID::init); - if (jt == c.wire->attributes.end()) - continue; - for (int i = c.offset; i < c.offset + c.width; i++) - jt->second[i] = State::Sx; - } - dff_init_map.add(it.second, Const(State::Sx, GetSize(it.second))); - } - } + if (sharemap.count(cell) > 0) { + did_something = true; + log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str()); + for (auto &it : cell->connections()) { + if (cell->output(it.first)) { + RTLIL::SigSpec other_sig = sharemap[cell]->getPort(it.first); + log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(), + log_signal(it.second), log_signal(other_sig)); + module->connect(RTLIL::SigSig(it.second, other_sig)); + assign_map.add(it.second, other_sig); } - log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); - module->remove(cell); - total_count++; } + log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); +#ifdef USE_CELL_HASH_CACHE + cell_hash_cache.erase(cell); +#endif + module->remove(cell); + total_count++; + } else { + sharemap[cell] = cell; } } } @@ -326,7 +343,7 @@ struct OptMergeWorker struct OptMergePass : public Pass { OptMergePass() : Pass("opt_merge", "consolidate identical cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -342,7 +359,7 @@ struct OptMergePass : public Pass { log(" Operate on all cell types, not just built-in types.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_MERGE pass (detect identical cells).\n"); diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 67b283e11e4..3c486bbccd9 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -88,7 +88,7 @@ struct OptMuxtreeWorker { RTLIL::SigSpec sig_a = cell->getPort(ID::A); RTLIL::SigSpec sig_b = cell->getPort(ID::B); - RTLIL::SigSpec sig_s = cell->getPort(ID::S); + RTLIL::SigSpec sig_s = cell->getPort(ID(S)); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); muxinfo_t muxinfo; @@ -229,7 +229,7 @@ struct OptMuxtreeWorker RTLIL::SigSpec sig_a = mi.cell->getPort(ID::A); RTLIL::SigSpec sig_b = mi.cell->getPort(ID::B); - RTLIL::SigSpec sig_s = mi.cell->getPort(ID::S); + RTLIL::SigSpec sig_s = mi.cell->getPort(ID(S)); RTLIL::SigSpec sig_y = mi.cell->getPort(ID::Y); RTLIL::SigSpec sig_ports = sig_b; @@ -257,12 +257,12 @@ struct OptMuxtreeWorker mi.cell->setPort(ID::A, new_sig_a); mi.cell->setPort(ID::B, new_sig_b); - mi.cell->setPort(ID::S, new_sig_s); + mi.cell->setPort(ID(S), new_sig_s); if (GetSize(new_sig_s) == 1) { mi.cell->type = ID($mux); - mi.cell->parameters.erase(ID::S_WIDTH); + mi.cell->parameters.erase(ID(S_WIDTH)); } else { - mi.cell->parameters[ID::S_WIDTH] = RTLIL::Const(GetSize(new_sig_s)); + mi.cell->parameters[ID(S_WIDTH)] = RTLIL::Const(GetSize(new_sig_s)); } } } @@ -366,7 +366,7 @@ struct OptMuxtreeWorker idict ctrl_bits; if (portname == ID::B) width = GetSize(muxinfo.cell->getPort(ID::A)); - for (int bit : sig2bits(muxinfo.cell->getPort(ID::S), false)) + for (int bit : sig2bits(muxinfo.cell->getPort(ID(S)), false)) ctrl_bits(bit); int port_idx = 0, port_off = 0; @@ -473,7 +473,7 @@ struct OptMuxtreeWorker struct OptMuxtreePass : public Pass { OptMuxtreePass() : Pass("opt_muxtree", "eliminate dead trees in multiplexer trees") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -486,7 +486,7 @@ struct OptMuxtreePass : public Pass { log("This pass only operates on completely selected modules without processes.\n"); log("\n"); } - void execute(vector args, RTLIL::Design *design) override + void execute(vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_MUXTREE pass (detect dead branches in mux trees).\n"); extra_args(args, 1, design); diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc index 28de9ceb6e8..6a8d8cabdf5 100644 --- a/passes/opt/opt_reduce.cc +++ b/passes/opt/opt_reduce.cc @@ -44,10 +44,9 @@ struct OptReduceWorker cells.erase(cell); RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); - sig_a.sort_and_unify(); pool new_sig_a_bits; - for (auto &bit : sig_a) + for (auto &bit : sig_a.to_sigbit_set()) { if (bit == RTLIL::State::S0) { if (cell->type == ID($reduce_and)) { @@ -87,7 +86,6 @@ struct OptReduceWorker } RTLIL::SigSpec new_sig_a(new_sig_a_bits); - new_sig_a.sort_and_unify(); 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)); @@ -96,7 +94,7 @@ struct OptReduceWorker } cell->setPort(ID::A, new_sig_a); - cell->parameters[ID::A_WIDTH] = RTLIL::Const(new_sig_a.size()); + cell->parameters[ID(A_WIDTH)] = RTLIL::Const(new_sig_a.size()); return; } @@ -104,7 +102,7 @@ struct OptReduceWorker { RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); - RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S)); + RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID(S))); RTLIL::SigSpec new_sig_b, new_sig_s; pool handled_sig; @@ -127,9 +125,9 @@ struct OptReduceWorker { RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or)); reduce_or_cell->setPort(ID::A, this_s); - reduce_or_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0); - reduce_or_cell->parameters[ID::A_WIDTH] = RTLIL::Const(this_s.size()); - reduce_or_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); + reduce_or_cell->parameters[ID(A_SIGNED)] = RTLIL::Const(0); + reduce_or_cell->parameters[ID(A_WIDTH)] = RTLIL::Const(this_s.size()); + reduce_or_cell->parameters[ID(Y_WIDTH)] = RTLIL::Const(1); RTLIL::Wire *reduce_or_wire = module->addWire(NEW_ID); this_s = RTLIL::SigSpec(reduce_or_wire); @@ -156,12 +154,12 @@ struct OptReduceWorker else { cell->setPort(ID::B, new_sig_b); - cell->setPort(ID::S, new_sig_s); + cell->setPort(ID(S), new_sig_s); if (new_sig_s.size() > 1) { - cell->parameters[ID::S_WIDTH] = RTLIL::Const(new_sig_s.size()); + cell->parameters[ID(S_WIDTH)] = RTLIL::Const(new_sig_s.size()); } else { cell->type = ID($mux); - cell->parameters.erase(ID::S_WIDTH); + cell->parameters.erase(ID(S_WIDTH)); } } } @@ -192,13 +190,13 @@ struct OptReduceWorker if (all_tuple_bits_same) { - old_sig_conn.first.append(sig_y.at(i)); - old_sig_conn.second.append(sig_a.at(i)); + old_sig_conn.first.append_bit(sig_y.at(i)); + old_sig_conn.second.append_bit(sig_a.at(i)); } else if (consolidated_in_tuples_map.count(in_tuple)) { - old_sig_conn.first.append(sig_y.at(i)); - old_sig_conn.second.append(consolidated_in_tuples_map.at(in_tuple)); + old_sig_conn.first.append_bit(sig_y.at(i)); + old_sig_conn.second.append_bit(consolidated_in_tuples_map.at(in_tuple)); } else { @@ -222,14 +220,14 @@ struct OptReduceWorker } cell->setPort(ID::B, RTLIL::SigSpec()); - for (int i = 1; i <= cell->getPort(ID::S).size(); i++) + for (int i = 1; i <= cell->getPort(ID(S)).size(); i++) for (auto &in_tuple : consolidated_in_tuples) { RTLIL::SigSpec new_b = cell->getPort(ID::B); new_b.append(in_tuple.at(i)); cell->setPort(ID::B, new_b); } - cell->parameters[ID::WIDTH] = RTLIL::Const(new_sig_y.size()); + cell->parameters[ID(WIDTH)] = RTLIL::Const(new_sig_y.size()); cell->setPort(ID::Y, new_sig_y); log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)), @@ -237,6 +235,7 @@ struct OptReduceWorker log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second)); module->connect(old_sig_conn); + module->check(); did_something = true; total_count++; @@ -255,14 +254,14 @@ struct OptReduceWorker for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; if (cell->type == ID($mem)) - mem_wren_sigs.add(assign_map(cell->getPort(ID::WR_EN))); + mem_wren_sigs.add(assign_map(cell->getPort(ID(WR_EN)))); if (cell->type == ID($memwr)) - mem_wren_sigs.add(assign_map(cell->getPort(ID::EN))); + mem_wren_sigs.add(assign_map(cell->getPort(ID(EN)))); } for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - if (cell->type == ID($dff) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Q)))) - mem_wren_sigs.add(assign_map(cell->getPort(ID::D))); + if (cell->type == ID($dff) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Q))))) + mem_wren_sigs.add(assign_map(cell->getPort(ID(D)))); } bool keep_expanding_mem_wren_sigs = true; @@ -325,14 +324,12 @@ struct OptReduceWorker opt_mux(cell); } } - - module->check(); } }; struct OptReducePass : public Pass { OptReducePass() : Pass("opt_reduce", "simplify large MUXes and AND/OR gates") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -353,7 +350,7 @@ struct OptReducePass : public Pass { log(" alias for -fine\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool do_fine = false; diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 8f7628a4a42..0bf74098aef 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -41,7 +41,7 @@ void remove_init_attr(SigSpec sig) for (auto bit : assign_map(sig)) if (init_attributes.count(bit)) for (auto wbit : init_attributes.at(bit)) - wbit.wire->attributes.at(ID::init)[wbit.offset] = State::Sx; + wbit.wire->attributes.at(ID(init))[wbit.offset] = State::Sx; } bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) @@ -49,17 +49,17 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) SigSpec sig_set, sig_clr; State pol_set, pol_clr; - if (cell->hasPort(ID::S)) - sig_set = cell->getPort(ID::S); + if (cell->hasPort(ID(S))) + sig_set = cell->getPort(ID(S)); - if (cell->hasPort(ID::R)) - sig_clr = cell->getPort(ID::R); + if (cell->hasPort(ID(R))) + sig_clr = cell->getPort(ID(R)); - if (cell->hasPort(ID::SET)) - sig_set = cell->getPort(ID::SET); + if (cell->hasPort(ID(SET))) + sig_set = cell->getPort(ID(SET)); - if (cell->hasPort(ID::CLR)) - sig_clr = cell->getPort(ID::CLR); + if (cell->hasPort(ID(CLR))) + sig_clr = cell->getPort(ID(CLR)); log_assert(GetSize(sig_set) == GetSize(sig_clr)); @@ -72,16 +72,16 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0; } else if (cell->type.in(ID($dffsr), ID($dlatchsr))) { - pol_set = cell->parameters[ID::SET_POLARITY].as_bool() ? State::S1 : State::S0; - pol_clr = cell->parameters[ID::CLR_POLARITY].as_bool() ? State::S1 : State::S0; + pol_set = cell->parameters[ID(SET_POLARITY)].as_bool() ? State::S1 : State::S0; + pol_clr = cell->parameters[ID(CLR_POLARITY)].as_bool() ? State::S1 : State::S0; } else log_abort(); State npol_set = pol_set == State::S0 ? State::S1 : State::S0; State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0; - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); + SigSpec sig_d = cell->getPort(ID(D)); + SigSpec sig_q = cell->getPort(ID(Q)); bool did_something = false; bool proper_sr = false; @@ -139,18 +139,18 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) if (cell->type.in(ID($dffsr), ID($dlatchsr))) { - cell->setParam(ID::WIDTH, GetSize(sig_d)); - cell->setPort(ID::SET, sig_set); - cell->setPort(ID::CLR, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setParam(ID(WIDTH), GetSize(sig_d)); + cell->setPort(ID(SET), sig_set); + cell->setPort(ID(CLR), sig_clr); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); } else { - cell->setPort(ID::S, sig_set); - cell->setPort(ID::R, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setPort(ID(S), sig_set); + cell->setPort(ID(R), sig_clr); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); } if (proper_sr) @@ -171,24 +171,24 @@ 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), "$adff", log_id(mod)); cell->type = ID($adff); - cell->setParam(ID::ARST_POLARITY, unified_pol); - cell->setParam(ID::ARST_VALUE, reset_val); - cell->setPort(ID::ARST, sig_reset); - - cell->unsetParam(ID::SET_POLARITY); - cell->unsetParam(ID::CLR_POLARITY); - cell->unsetPort(ID::SET); - cell->unsetPort(ID::CLR); + cell->setParam(ID(ARST_POLARITY), unified_pol); + cell->setParam(ID(ARST_VALUE), reset_val); + cell->setPort(ID(ARST), sig_reset); + + cell->unsetParam(ID(SET_POLARITY)); + cell->unsetParam(ID(CLR_POLARITY)); + cell->unsetPort(ID(SET)); + cell->unsetPort(ID(CLR)); } else { log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod)); cell->type = ID($dff); - cell->unsetParam(ID::SET_POLARITY); - cell->unsetParam(ID::CLR_POLARITY); - cell->unsetPort(ID::SET); - cell->unsetPort(ID::CLR); + cell->unsetParam(ID(SET_POLARITY)); + cell->unsetParam(ID(CLR_POLARITY)); + cell->unsetPort(ID(SET)); + cell->unsetPort(ID(CLR)); } return true; @@ -208,8 +208,8 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod)); cell->type = new_type; - cell->unsetPort(ID::S); - cell->unsetPort(ID::R); + cell->unsetPort(ID(S)); + cell->unsetPort(ID(R)); return true; } @@ -223,17 +223,17 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) State on_state, off_state; if (dlatch->type == ID($dlatch)) { - sig_e = assign_map(dlatch->getPort(ID::EN)); - on_state = dlatch->getParam(ID::EN_POLARITY).as_bool() ? State::S1 : State::S0; - off_state = dlatch->getParam(ID::EN_POLARITY).as_bool() ? State::S0 : State::S1; + sig_e = assign_map(dlatch->getPort(ID(EN))); + on_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S1 : State::S0; + off_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S0 : State::S1; } else if (dlatch->type == ID($_DLATCH_P_)) { - sig_e = assign_map(dlatch->getPort(ID::E)); + sig_e = assign_map(dlatch->getPort(ID(E))); on_state = State::S1; off_state = State::S0; } else if (dlatch->type == ID($_DLATCH_N_)) { - sig_e = assign_map(dlatch->getPort(ID::E)); + sig_e = assign_map(dlatch->getPort(ID(E))); on_state = State::S0; off_state = State::S1; } else @@ -242,15 +242,15 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) if (sig_e == off_state) { RTLIL::Const val_init; - for (auto bit : dff_init_map(dlatch->getPort(ID::Q))) + for (auto bit : dff_init_map(dlatch->getPort(ID(Q)))) val_init.bits.push_back(bit.wire == NULL ? bit.data : State::Sx); - mod->connect(dlatch->getPort(ID::Q), val_init); + mod->connect(dlatch->getPort(ID(Q)), val_init); goto delete_dlatch; } if (sig_e == on_state) { - mod->connect(dlatch->getPort(ID::Q), dlatch->getPort(ID::D)); + mod->connect(dlatch->getPort(ID(Q)), dlatch->getPort(ID(D))); goto delete_dlatch; } @@ -258,7 +258,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) delete_dlatch: log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod)); - remove_init_attr(dlatch->getPort(ID::Q)); + remove_init_attr(dlatch->getPort(ID(Q))); mod->remove(dlatch); return true; } @@ -269,23 +269,23 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) RTLIL::Const val_cp, val_rp, val_rv, val_ep; if (dff->type == ID($_FF_)) { - sig_d = dff->getPort(ID::D); - sig_q = dff->getPort(ID::Q); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); } else if (dff->type == ID($_DFF_N_) || dff->type == ID($_DFF_P_)) { - sig_d = dff->getPort(ID::D); - sig_q = dff->getPort(ID::Q); - sig_c = dff->getPort(ID::C); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(C)); val_cp = RTLIL::Const(dff->type == ID($_DFF_P_), 1); } else if (dff->type.begins_with("$_DFF_") && dff->type.compare(9, 1, "_") == 0 && (dff->type[6] == 'N' || dff->type[6] == 'P') && (dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[8] == '0' || dff->type[8] == '1')) { - sig_d = dff->getPort(ID::D); - sig_q = dff->getPort(ID::Q); - sig_c = dff->getPort(ID::C); - sig_r = dff->getPort(ID::R); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(C)); + sig_r = dff->getPort(ID(R)); val_cp = RTLIL::Const(dff->type[6] == 'P', 1); val_rp = RTLIL::Const(dff->type[7] == 'P', 1); val_rv = RTLIL::Const(dff->type[8] == '1', 1); @@ -293,39 +293,39 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) else if (dff->type.begins_with("$_DFFE_") && dff->type.compare(9, 1, "_") == 0 && (dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[8] == 'N' || dff->type[8] == 'P')) { - sig_d = dff->getPort(ID::D); - sig_q = dff->getPort(ID::Q); - sig_c = dff->getPort(ID::C); - sig_e = dff->getPort(ID::E); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(C)); + sig_e = dff->getPort(ID(E)); val_cp = RTLIL::Const(dff->type[7] == 'P', 1); val_ep = RTLIL::Const(dff->type[8] == 'P', 1); } else if (dff->type == ID($ff)) { - sig_d = dff->getPort(ID::D); - sig_q = dff->getPort(ID::Q); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); } else if (dff->type == ID($dff)) { - sig_d = dff->getPort(ID::D); - sig_q = dff->getPort(ID::Q); - sig_c = dff->getPort(ID::CLK); - val_cp = RTLIL::Const(dff->parameters[ID::CLK_POLARITY].as_bool(), 1); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(CLK)); + val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1); } else if (dff->type == ID($dffe)) { - sig_e = dff->getPort(ID::EN); - sig_d = dff->getPort(ID::D); - sig_q = dff->getPort(ID::Q); - sig_c = dff->getPort(ID::CLK); - val_cp = RTLIL::Const(dff->parameters[ID::CLK_POLARITY].as_bool(), 1); - val_ep = RTLIL::Const(dff->parameters[ID::EN_POLARITY].as_bool(), 1); + sig_e = dff->getPort(ID(EN)); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(CLK)); + val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1); + val_ep = RTLIL::Const(dff->parameters[ID(EN_POLARITY)].as_bool(), 1); } else if (dff->type == ID($adff)) { - sig_d = dff->getPort(ID::D); - sig_q = dff->getPort(ID::Q); - sig_c = dff->getPort(ID::CLK); - sig_r = dff->getPort(ID::ARST); - val_cp = RTLIL::Const(dff->parameters[ID::CLK_POLARITY].as_bool(), 1); - val_rp = RTLIL::Const(dff->parameters[ID::ARST_POLARITY].as_bool(), 1); - val_rv = dff->parameters[ID::ARST_VALUE]; + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(CLK)); + sig_r = dff->getPort(ID(ARST)); + val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1); + val_rp = RTLIL::Const(dff->parameters[ID(ARST_POLARITY)].as_bool(), 1); + val_rv = dff->parameters[ID(ARST_VALUE)]; } else log_abort(); @@ -422,15 +422,15 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) if (dff->type == ID($adff)) { dff->type = ID($dff); - dff->unsetPort(ID::ARST); - dff->unsetParam(ID::ARST_POLARITY); - dff->unsetParam(ID::ARST_VALUE); + dff->unsetPort(ID(ARST)); + dff->unsetParam(ID(ARST_POLARITY)); + dff->unsetParam(ID(ARST_VALUE)); return true; } log_assert(dff->type.begins_with("$_DFF_")); dff->type = stringf("$_DFF_%c_", + dff->type[6]); - dff->unsetPort(ID::R); + dff->unsetPort(ID(R)); } // If enable signal is present, and is fully constant @@ -447,14 +447,14 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) if (dff->type == ID($dffe)) { dff->type = ID($dff); - dff->unsetPort(ID::EN); - dff->unsetParam(ID::EN_POLARITY); + dff->unsetPort(ID(EN)); + dff->unsetParam(ID(EN_POLARITY)); return true; } log_assert(dff->type.begins_with("$_DFFE_")); dff->type = stringf("$_DFF_%c_", + dff->type[7]); - dff->unsetPort(ID::E); + dff->unsetPort(ID(E)); } if (sat && has_init && (!sig_r.size() || val_init == val_rv)) @@ -509,9 +509,9 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0, position, log_id(dff), log_id(dff->type), log_id(mod)); - SigSpec tmp = dff->getPort(ID::D); + SigSpec tmp = dff->getPort(ID(D)); tmp[position] = sigbit_init_val; - dff->setPort(ID::D, tmp); + dff->setPort(ID(D), tmp); removed_sigbits = true; } @@ -528,7 +528,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) delete_dff: log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); - remove_init_attr(dff->getPort(ID::Q)); + remove_init_attr(dff->getPort(ID(Q))); mod->remove(dff); for (auto &entry : bit2driver) @@ -540,7 +540,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) struct OptRmdffPass : public Pass { OptRmdffPass() : Pass("opt_rmdff", "remove DFFs with constant inputs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -554,7 +554,7 @@ struct OptRmdffPass : public Pass { log(" non-constant inputs) that can also be replaced with a constant driver\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { int total_count = 0, total_initdrv = 0; log_header(design, "Executing OPT_RMDFF pass (remove dff with constant values).\n"); @@ -588,8 +588,8 @@ struct OptRmdffPass : public Pass { for (auto wire : module->wires()) { - if (wire->attributes.count(ID::init) != 0) { - Const initval = wire->attributes.at(ID::init); + if (wire->attributes.count(ID(init)) != 0) { + Const initval = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) if (initval[i] == State::S0 || initval[i] == State::S1) dff_init_map.add(SigBit(wire, i), initval[i]); diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index db21cef2855..f59f978a6d9 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -98,12 +98,12 @@ struct ExtSigSpec { 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); + 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($divfloor), ID($modfloor), ID($concat))) { + } 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; } @@ -130,7 +130,7 @@ bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b) 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($divfloor), ID($modfloor), ID($concat), SHIFT_OPS) && port_name == ID::B) + 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 ""; @@ -139,7 +139,7 @@ RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_na 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); + return cell->getPort(ID(BI)); else if (cell->type == ID($sub) && port_name == ID::B) return RTLIL::Const(1, 1); @@ -190,7 +190,7 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< 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()); + max_width = std::max(max_width, shared_op->getParam(ID(Y_WIDTH)).as_int()); for (auto &operand : muxed_operands) @@ -210,7 +210,7 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< 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 mux_s = mux->getPort(ID(S)); RTLIL::SigSpec shared_pmux_a = RTLIL::Const(RTLIL::State::Sx, max_width); RTLIL::SigSpec shared_pmux_b; @@ -237,7 +237,7 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< mux->setPort(ID::A, mux_a); mux->setPort(ID::B, mux_b); mux->setPort(ID::Y, mux_y); - mux->setPort(ID::S, mux_s); + mux->setPort(ID(S), mux_s); for (const auto &op : muxed_operands) shared_pmux_b.append(op.sig); @@ -245,26 +245,26 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< 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); + 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->setPort(ID(X), alu_x.extract(0, conn_width)); + shared_op->setPort(ID(CO), alu_co.extract(0, conn_width)); } bool is_fine = shared_op->type.in(FINE_BITWISE_OPS); if (!is_fine) - shared_op->setParam(ID::Y_WIDTH, 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); if (!is_fine) - shared_op->setParam(ID::B_WIDTH, max_width); + shared_op->setParam(ID(B_WIDTH), max_width); } else { shared_op->setPort(ID::A, mux_to_oper); if (!is_fine) - shared_op->setParam(ID::A_WIDTH, max_width); + shared_op->setParam(ID(A_WIDTH), max_width); } } @@ -452,7 +452,7 @@ dict find_valid_op_mux_conns(RTLIL::Module *module, d for (auto cell : module->cells()) { if (cell->type.in(ID($mux), ID($_MUX_), ID($pmux))) { - remove_connected_ops(cell->getPort(ID::S)); + remove_connected_ops(cell->getPort(ID(S))); find_op_mux_conns(cell); } else { for (auto &conn : cell->connections()) @@ -473,7 +473,7 @@ dict find_valid_op_mux_conns(RTLIL::Module *module, d struct OptSharePass : public Pass { OptSharePass() : Pass("opt_share", "merge mutually exclusive cells of the same type that share an input signal") {} - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -488,7 +488,7 @@ struct OptSharePass : public Pass { log("multiplexing its output to multiplexing the non-shared input signals.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_SHARE pass.\n"); @@ -510,7 +510,7 @@ struct OptSharePass : public Pass { continue; if (cell->type == ID($alu)) { - for (RTLIL::IdString port_name : {ID::X, ID::CO}) { + 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) @@ -552,7 +552,7 @@ struct OptSharePass : public Pass { 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_num = p.mux->getPort(ID(S)).size(); mux_port_conns.resize(mux_port_num); } diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 9f226e12dbc..92b5794acc9 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -46,7 +46,7 @@ struct OnehotDatabase for (auto wire : module->wires()) { - auto it = wire->attributes.find(ID::init); + auto it = wire->attributes.find(ID(init)); if (it == wire->attributes.end()) continue; @@ -63,14 +63,12 @@ struct OnehotDatabase vector inputs; SigSpec output; - if (cell->type.in(ID($adff), ID($adffe), ID($dff), ID($dffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($ff))) + if (cell->type.in(ID($adff), ID($dff), ID($dffe), ID($dlatch), ID($ff))) { - output = cell->getPort(ID::Q); - if (cell->type.in(ID($adff), ID($adffe), ID($adlatch))) - inputs.push_back(cell->getParam(ID::ARST_VALUE)); - if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) - inputs.push_back(cell->getParam(ID::SRST_VALUE)); - inputs.push_back(cell->getPort(ID::D)); + output = cell->getPort(ID(Q)); + if (cell->type == ID($adff)) + inputs.push_back(cell->getParam(ID(ARST_VALUE))); + inputs.push_back(cell->getPort(ID(D))); } if (cell->type.in(ID($mux), ID($pmux))) @@ -200,7 +198,7 @@ struct OnehotDatabase struct Pmux2ShiftxPass : public Pass { Pmux2ShiftxPass() : Pass("pmux2shiftx", "transform $pmux cells to $shiftx cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -227,7 +225,7 @@ struct Pmux2ShiftxPass : public Pass { log(" disable $sub inference for \"range decoders\"\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { int min_density = 50; int min_choices = 3; @@ -301,16 +299,16 @@ struct Pmux2ShiftxPass : public Pass { SigSpec A = sigmap(cell->getPort(ID::A)); SigSpec B = sigmap(cell->getPort(ID::B)); - int a_width = cell->getParam(ID::A_WIDTH).as_int(); - int b_width = cell->getParam(ID::B_WIDTH).as_int(); + int a_width = cell->getParam(ID(A_WIDTH)).as_int(); + int b_width = cell->getParam(ID(B_WIDTH)).as_int(); if (a_width < b_width) { - bool a_signed = cell->getParam(ID::A_SIGNED).as_int(); + bool a_signed = cell->getParam(ID(A_SIGNED)).as_int(); A.extend_u0(b_width, a_signed); } if (b_width < a_width) { - bool b_signed = cell->getParam(ID::B_SIGNED).as_int(); + bool b_signed = cell->getParam(ID(B_SIGNED)).as_int(); B.extend_u0(a_width, b_signed); } @@ -333,7 +331,7 @@ struct Pmux2ShiftxPass : public Pass { pair entry; for (auto it : bits) { - entry.first.append(it.first); + entry.first.append_bit(it.first); entry.second.bits.push_back(it.second); } @@ -354,7 +352,7 @@ struct Pmux2ShiftxPass : public Pass { pair entry; for (auto it : bits) { - entry.first.append(it.first); + entry.first.append_bit(it.first); entry.second.bits.push_back(it.second); } @@ -370,7 +368,7 @@ struct Pmux2ShiftxPass : public Pass { continue; string src = cell->get_src_attribute(); - int width = cell->getParam(ID::WIDTH).as_int(); + int width = cell->getParam(ID(WIDTH)).as_int(); int width_bits = ceil_log2(width); int extwidth = width; @@ -381,7 +379,7 @@ struct Pmux2ShiftxPass : public Pass { SigSpec A = cell->getPort(ID::A); SigSpec B = cell->getPort(ID::B); - SigSpec S = sigmap(cell->getPort(ID::S)); + SigSpec S = sigmap(cell->getPort(ID(S))); for (int i = 0; i < GetSize(S); i++) { if (!eqdb.count(S[i])) @@ -402,7 +400,7 @@ struct Pmux2ShiftxPass : public Pass { log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); } - SigSpec updated_S = cell->getPort(ID::S); + SigSpec updated_S = cell->getPort(ID(S)); SigSpec updated_B = cell->getPort(ID::B); while (!seldb.empty()) @@ -729,9 +727,9 @@ struct Pmux2ShiftxPass : public Pass { } // update $pmux cell - cell->setPort(ID::S, updated_S); + cell->setPort(ID(S), updated_S); cell->setPort(ID::B, updated_B); - cell->setParam(ID::S_WIDTH, GetSize(updated_S)); + cell->setParam(ID(S_WIDTH), GetSize(updated_S)); } } } @@ -739,7 +737,7 @@ struct Pmux2ShiftxPass : public Pass { struct OnehotPass : public Pass { OnehotPass() : Pass("onehot", "optimize $eq cells for onehot signals") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -751,7 +749,7 @@ struct OnehotPass : public Pass { log(" verbose output\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool verbose = false; bool verbose_onehot = false; @@ -787,16 +785,16 @@ struct OnehotPass : public Pass { SigSpec A = sigmap(cell->getPort(ID::A)); SigSpec B = sigmap(cell->getPort(ID::B)); - int a_width = cell->getParam(ID::A_WIDTH).as_int(); - int b_width = cell->getParam(ID::B_WIDTH).as_int(); + int a_width = cell->getParam(ID(A_WIDTH)).as_int(); + int b_width = cell->getParam(ID(B_WIDTH)).as_int(); if (a_width < b_width) { - bool a_signed = cell->getParam(ID::A_SIGNED).as_int(); + bool a_signed = cell->getParam(ID(A_SIGNED)).as_int(); A.extend_u0(b_width, a_signed); } if (b_width < a_width) { - bool b_signed = cell->getParam(ID::B_SIGNED).as_int(); + bool b_signed = cell->getParam(ID(B_SIGNED)).as_int(); B.extend_u0(a_width, b_signed); } diff --git a/passes/opt/rmports.cc b/passes/opt/rmports.cc index 99a2a61c826..32363dd681e 100644 --- a/passes/opt/rmports.cc +++ b/passes/opt/rmports.cc @@ -28,7 +28,7 @@ PRIVATE_NAMESPACE_BEGIN struct RmportsPassPass : public Pass { RmportsPassPass() : Pass("rmports", "remove module ports with no connections") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -39,7 +39,7 @@ struct RmportsPassPass : public Pass { log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing RMPORTS pass (remove ports with no connections).\n"); diff --git a/passes/opt/share.cc b/passes/opt/share.cc index f7848e01d78..92ce3fd11d8 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -41,8 +41,7 @@ struct ShareWorkerConfig struct ShareWorker { - const ShareWorkerConfig config; - int limit; + ShareWorkerConfig config; pool generic_ops; RTLIL::Design *design; @@ -50,6 +49,7 @@ struct ShareWorker CellTypes fwd_ct, cone_ct; ModWalker modwalker; + ModIndex mi; pool cells_to_remove; pool recursion_state; @@ -90,7 +90,7 @@ struct ShareWorker for (auto &pbit : portbits) { if (pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) { - pool bits = modwalker.sigmap(pbit.cell->getPort(ID::S)).to_sigbit_pool(); + pool bits = modwalker.sigmap(pbit.cell->getPort(ID(S))).to_sigbit_pool(); terminal_bits.insert(bits.begin(), bits.end()); queue_bits.insert(bits.begin(), bits.end()); visited_cells.insert(pbit.cell); @@ -331,7 +331,7 @@ struct ShareWorker supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort(ID::Y))); supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID::Y))); - supercell->setParam(ID::Y_WIDTH, width); + supercell->setParam(ID(Y_WIDTH), width); supercell->setPort(ID::Y, sig_y); supermacc.optimize(width); @@ -369,21 +369,21 @@ struct ShareWorker } if (cell->type == ID($memrd)) { - if (cell->parameters.at(ID::CLK_ENABLE).as_bool()) + if (cell->parameters.at(ID(CLK_ENABLE)).as_bool()) continue; - if (config.opt_aggressive || !modwalker.sigmap(cell->getPort(ID::ADDR)).is_fully_const()) + if (config.opt_aggressive || !modwalker.sigmap(cell->getPort(ID(ADDR))).is_fully_const()) shareable_cells.insert(cell); continue; } - if (cell->type.in(ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor))) { - if (config.opt_aggressive || cell->parameters.at(ID::Y_WIDTH).as_int() >= 4) + if (cell->type.in(ID($mul), ID($div), ID($mod))) { + if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 4) shareable_cells.insert(cell); continue; } if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) { - if (config.opt_aggressive || cell->parameters.at(ID::Y_WIDTH).as_int() >= 8) + if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 8) shareable_cells.insert(cell); continue; } @@ -403,7 +403,7 @@ struct ShareWorker if (c1->type == ID($memrd)) { - if (c1->parameters.at(ID::MEMID).decode_string() != c2->parameters.at(ID::MEMID).decode_string()) + if (c1->parameters.at(ID(MEMID)).decode_string() != c2->parameters.at(ID(MEMID)).decode_string()) return false; return true; @@ -413,11 +413,11 @@ struct ShareWorker { if (!config.opt_aggressive) { - int a1_width = c1->parameters.at(ID::A_WIDTH).as_int(); - int y1_width = c1->parameters.at(ID::Y_WIDTH).as_int(); + int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int(); + int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int(); - int a2_width = c2->parameters.at(ID::A_WIDTH).as_int(); - int y2_width = c2->parameters.at(ID::Y_WIDTH).as_int(); + int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int(); + int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int(); if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false; if (max(y1_width, y2_width) > 2 * min(y1_width, y2_width)) return false; @@ -430,13 +430,13 @@ struct ShareWorker { if (!config.opt_aggressive) { - int a1_width = c1->parameters.at(ID::A_WIDTH).as_int(); - int b1_width = c1->parameters.at(ID::B_WIDTH).as_int(); - int y1_width = c1->parameters.at(ID::Y_WIDTH).as_int(); + int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int(); + int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int(); + int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int(); - int a2_width = c2->parameters.at(ID::A_WIDTH).as_int(); - int b2_width = c2->parameters.at(ID::B_WIDTH).as_int(); - int y2_width = c2->parameters.at(ID::Y_WIDTH).as_int(); + int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int(); + int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int(); + int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int(); if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false; if (max(b1_width, b2_width) > 2 * min(b1_width, b2_width)) return false; @@ -450,13 +450,13 @@ struct ShareWorker { if (!config.opt_aggressive) { - int a1_width = c1->parameters.at(ID::A_WIDTH).as_int(); - int b1_width = c1->parameters.at(ID::B_WIDTH).as_int(); - int y1_width = c1->parameters.at(ID::Y_WIDTH).as_int(); + int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int(); + int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int(); + int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int(); - int a2_width = c2->parameters.at(ID::A_WIDTH).as_int(); - int b2_width = c2->parameters.at(ID::B_WIDTH).as_int(); - int y2_width = c2->parameters.at(ID::Y_WIDTH).as_int(); + int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int(); + int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int(); + int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int(); int min1_width = min(a1_width, b1_width); int max1_width = max(a1_width, b1_width); @@ -510,21 +510,21 @@ struct ShareWorker if (config.generic_uni_ops.count(c1->type)) { - if (c1->parameters.at(ID::A_SIGNED).as_bool() != c2->parameters.at(ID::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(ID::A_SIGNED).as_bool() ? c2 : c1; + RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1; if (unsigned_cell->getPort(ID::A).to_sigbit_vector().back() != RTLIL::State::S0) { - unsigned_cell->parameters.at(ID::A_WIDTH) = unsigned_cell->parameters.at(ID::A_WIDTH).as_int() + 1; + unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1; RTLIL::SigSpec new_a = unsigned_cell->getPort(ID::A); - new_a.append(RTLIL::State::S0); + new_a.append_bit(RTLIL::State::S0); unsigned_cell->setPort(ID::A, new_a); } - unsigned_cell->parameters.at(ID::A_SIGNED) = true; + unsigned_cell->parameters.at(ID(A_SIGNED)) = true; unsigned_cell->check(); } - bool a_signed = c1->parameters.at(ID::A_SIGNED).as_bool(); - log_assert(a_signed == c2->parameters.at(ID::A_SIGNED).as_bool()); + bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool(); + log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool()); RTLIL::SigSpec a1 = c1->getPort(ID::A); RTLIL::SigSpec y1 = c1->getPort(ID::Y); @@ -544,9 +544,9 @@ struct ShareWorker RTLIL::Wire *y = module->addWire(NEW_ID, y_width); RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); - supercell->parameters[ID::A_SIGNED] = a_signed; - supercell->parameters[ID::A_WIDTH] = a_width; - supercell->parameters[ID::Y_WIDTH] = y_width; + supercell->parameters[ID(A_SIGNED)] = a_signed; + supercell->parameters[ID(A_WIDTH)] = a_width; + supercell->parameters[ID(Y_WIDTH)] = y_width; supercell->setPort(ID::A, a); supercell->setPort(ID::Y, y); @@ -563,11 +563,11 @@ struct ShareWorker if (config.generic_cbin_ops.count(c1->type)) { - int score_unflipped = max(c1->parameters.at(ID::A_WIDTH).as_int(), c2->parameters.at(ID::A_WIDTH).as_int()) + - max(c1->parameters.at(ID::B_WIDTH).as_int(), c2->parameters.at(ID::B_WIDTH).as_int()); + int score_unflipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int()) + + max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int()); - int score_flipped = max(c1->parameters.at(ID::A_WIDTH).as_int(), c2->parameters.at(ID::B_WIDTH).as_int()) + - max(c1->parameters.at(ID::B_WIDTH).as_int(), c2->parameters.at(ID::A_WIDTH).as_int()); + int score_flipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int()) + + max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int()); if (score_flipped < score_unflipped) { @@ -575,36 +575,36 @@ struct ShareWorker c2->setPort(ID::A, c2->getPort(ID::B)); c2->setPort(ID::B, tmp); - std::swap(c2->parameters.at(ID::A_WIDTH), c2->parameters.at(ID::B_WIDTH)); - std::swap(c2->parameters.at(ID::A_SIGNED), c2->parameters.at(ID::B_SIGNED)); + std::swap(c2->parameters.at(ID(A_WIDTH)), c2->parameters.at(ID(B_WIDTH))); + std::swap(c2->parameters.at(ID(A_SIGNED)), c2->parameters.at(ID(B_SIGNED))); modified_src_cells = true; } } - if (c1->parameters.at(ID::A_SIGNED).as_bool() != c2->parameters.at(ID::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(ID::A_SIGNED).as_bool() ? c2 : c1; + RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1; if (unsigned_cell->getPort(ID::A).to_sigbit_vector().back() != RTLIL::State::S0) { - unsigned_cell->parameters.at(ID::A_WIDTH) = unsigned_cell->parameters.at(ID::A_WIDTH).as_int() + 1; + unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1; RTLIL::SigSpec new_a = unsigned_cell->getPort(ID::A); - new_a.append(RTLIL::State::S0); + new_a.append_bit(RTLIL::State::S0); unsigned_cell->setPort(ID::A, new_a); } - unsigned_cell->parameters.at(ID::A_SIGNED) = true; + unsigned_cell->parameters.at(ID(A_SIGNED)) = true; modified_src_cells = true; } - if (c1->parameters.at(ID::B_SIGNED).as_bool() != c2->parameters.at(ID::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(ID::B_SIGNED).as_bool() ? c2 : c1; + RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(B_SIGNED)).as_bool() ? c2 : c1; if (unsigned_cell->getPort(ID::B).to_sigbit_vector().back() != RTLIL::State::S0) { - unsigned_cell->parameters.at(ID::B_WIDTH) = unsigned_cell->parameters.at(ID::B_WIDTH).as_int() + 1; + unsigned_cell->parameters.at(ID(B_WIDTH)) = unsigned_cell->parameters.at(ID(B_WIDTH)).as_int() + 1; RTLIL::SigSpec new_b = unsigned_cell->getPort(ID::B); - new_b.append(RTLIL::State::S0); + new_b.append_bit(RTLIL::State::S0); unsigned_cell->setPort(ID::B, new_b); } - unsigned_cell->parameters.at(ID::B_SIGNED) = true; + unsigned_cell->parameters.at(ID(B_SIGNED)) = true; modified_src_cells = true; } @@ -613,11 +613,11 @@ struct ShareWorker c2->check(); } - bool a_signed = c1->parameters.at(ID::A_SIGNED).as_bool(); - bool b_signed = c1->parameters.at(ID::B_SIGNED).as_bool(); + bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool(); + bool b_signed = c1->parameters.at(ID(B_SIGNED)).as_bool(); - log_assert(a_signed == c2->parameters.at(ID::A_SIGNED).as_bool()); - log_assert(b_signed == c2->parameters.at(ID::B_SIGNED).as_bool()); + log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool()); + log_assert(b_signed == c2->parameters.at(ID(B_SIGNED)).as_bool()); if (c1->type == ID($shl) || c1->type == ID($shr) || c1->type == ID($sshl) || c1->type == ID($sshr)) b_signed = false; @@ -664,32 +664,32 @@ struct ShareWorker RTLIL::Wire *co = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr; RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); - supercell->parameters[ID::A_SIGNED] = a_signed; - supercell->parameters[ID::B_SIGNED] = b_signed; - supercell->parameters[ID::A_WIDTH] = a_width; - supercell->parameters[ID::B_WIDTH] = b_width; - supercell->parameters[ID::Y_WIDTH] = y_width; + supercell->parameters[ID(A_SIGNED)] = a_signed; + supercell->parameters[ID(B_SIGNED)] = b_signed; + supercell->parameters[ID(A_WIDTH)] = a_width; + supercell->parameters[ID(B_WIDTH)] = b_width; + supercell->parameters[ID(Y_WIDTH)] = y_width; supercell->setPort(ID::A, a); supercell->setPort(ID::B, b); supercell->setPort(ID::Y, y); if (c1->type == ID($alu)) { RTLIL::Wire *ci = module->addWire(NEW_ID), *bi = module->addWire(NEW_ID); - supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID::CI), c1->getPort(ID::CI), act, ci)); - supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID::BI), c1->getPort(ID::BI), act, bi)); - supercell->setPort(ID::CI, ci); - supercell->setPort(ID::BI, bi); - supercell->setPort(ID::CO, co); - supercell->setPort(ID::X, x); + supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(CI)), c1->getPort(ID(CI)), act, ci)); + supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(BI)), c1->getPort(ID(BI)), act, bi)); + supercell->setPort(ID(CI), ci); + supercell->setPort(ID(BI), bi); + supercell->setPort(ID(CO), co); + supercell->setPort(ID(X), x); } supercell->check(); supercell_aux.insert(module->addPos(NEW_ID, y, y1)); supercell_aux.insert(module->addPos(NEW_ID, y, y2)); if (c1->type == ID($alu)) { - supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort(ID::CO))); - supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort(ID::CO))); - supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort(ID::X))); - supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort(ID::X))); + supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort(ID(CO)))); + supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort(ID(CO)))); + supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort(ID(X)))); + supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort(ID(X)))); } supercell_aux.insert(supercell); @@ -708,15 +708,15 @@ struct ShareWorker if (c1->type == ID($memrd)) { RTLIL::Cell *supercell = module->addCell(NEW_ID, c1); - RTLIL::SigSpec addr1 = c1->getPort(ID::ADDR); - RTLIL::SigSpec addr2 = c2->getPort(ID::ADDR); + RTLIL::SigSpec addr1 = c1->getPort(ID(ADDR)); + RTLIL::SigSpec addr2 = c2->getPort(ID(ADDR)); if (GetSize(addr1) < GetSize(addr2)) addr1.extend_u0(GetSize(addr2)); else addr2.extend_u0(GetSize(addr1)); - supercell->setPort(ID::ADDR, addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1); - supercell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr1)); - supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort(ID::DATA), c2->getPort(ID::DATA))); + supercell->setPort(ID(ADDR), addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1); + supercell->parameters[ID(ABITS)] = RTLIL::Const(GetSize(addr1)); + supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort(ID(DATA)), c2->getPort(ID(DATA)))); supercell_aux.insert(supercell); return supercell; } @@ -747,8 +747,8 @@ struct ShareWorker modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]); for (auto &bit : pbits) { - if ((bit.cell->type == ID($mux) || bit.cell->type == ID($pmux)) && bit.port == ID::S) - forbidden_controls_cache[cell].insert(bit.cell->getPort(ID::S).extract(bit.offset, 1)); + if ((bit.cell->type == ID($mux) || bit.cell->type == ID($pmux)) && bit.port == ID(S)) + forbidden_controls_cache[cell].insert(bit.cell->getPort(ID(S)).extract(bit.offset, 1)); consumer_cells.insert(bit.cell); } @@ -790,7 +790,7 @@ struct ShareWorker p.second.bits.clear(); for (auto &it : p_bits) { - p.first.append(it.first); + p.first.append_bit(it.first); p.second.bits.push_back(it.second); } @@ -890,10 +890,10 @@ struct ShareWorker bool used_in_a = false; std::set used_in_b_parts; - int width = c->parameters.at(ID::WIDTH).as_int(); + int width = c->parameters.at(ID(WIDTH)).as_int(); std::vector sig_a = modwalker.sigmap(c->getPort(ID::A)); std::vector sig_b = modwalker.sigmap(c->getPort(ID::B)); - std::vector sig_s = modwalker.sigmap(c->getPort(ID::S)); + std::vector sig_s = modwalker.sigmap(c->getPort(ID(S))); for (auto &bit : sig_a) if (cell_out_bits.count(bit)) @@ -906,14 +906,14 @@ struct ShareWorker if (used_in_a) for (auto p : c_patterns) { for (int i = 0; i < GetSize(sig_s); i++) - p.first.append(sig_s[i]), p.second.bits.push_back(RTLIL::State::S0); + p.first.append_bit(sig_s[i]), p.second.bits.push_back(RTLIL::State::S0); if (sort_check_activation_pattern(p)) activation_patterns_cache[cell].insert(p); } for (int idx : used_in_b_parts) for (auto p : c_patterns) { - p.first.append(sig_s[idx]), p.second.bits.push_back(RTLIL::State::S1); + p.first.append_bit(sig_s[idx]), p.second.bits.push_back(RTLIL::State::S1); if (sort_check_activation_pattern(p)) activation_patterns_cache[cell].insert(p); } @@ -948,7 +948,7 @@ struct ShareWorker RTLIL::SigSpec signal; for (auto &bit : all_bits) - signal.append(bit); + signal.append_bit(bit); return signal; } @@ -963,7 +963,7 @@ struct ShareWorker for (int i = 0; i < GetSize(p_first); i++) if (filter_bits.count(p_first[i]) == 0) { - new_p.first.append(p_first[i]); + new_p.first.append_bit(p_first[i]); new_p.second.bits.push_back(p.second.bits.at(i)); } @@ -1071,8 +1071,6 @@ struct ShareWorker ct.setup_internals(); ct.setup_stdcells(); - ModIndex mi(module); - pool queue, covered; queue.insert(cell); @@ -1119,9 +1117,13 @@ struct ShareWorker module->remove(cell); } - ShareWorker(ShareWorkerConfig config, RTLIL::Design* design) : - config(config), design(design), modwalker(design) + ShareWorker(ShareWorkerConfig config, RTLIL::Design *design, RTLIL::Module *module) : + config(config), design(design), module(module), mi(module) { + #ifndef NDEBUG + bool before_scc = module_has_scc(); + #endif + generic_ops.insert(config.generic_uni_ops.begin(), config.generic_uni_ops.end()); generic_ops.insert(config.generic_bin_ops.begin(), config.generic_bin_ops.end()); generic_ops.insert(config.generic_cbin_ops.begin(), config.generic_cbin_ops.end()); @@ -1133,34 +1135,13 @@ struct ShareWorker cone_ct.cell_types.erase(ID($mul)); cone_ct.cell_types.erase(ID($mod)); cone_ct.cell_types.erase(ID($div)); - cone_ct.cell_types.erase(ID($modfloor)); - cone_ct.cell_types.erase(ID($divfloor)); cone_ct.cell_types.erase(ID($pow)); cone_ct.cell_types.erase(ID($shl)); cone_ct.cell_types.erase(ID($shr)); cone_ct.cell_types.erase(ID($sshl)); cone_ct.cell_types.erase(ID($sshr)); - } - void operator()(RTLIL::Module *module) { - this->module = module; - - #ifndef NDEBUG - bool before_scc = module_has_scc(); - #endif - - limit = config.limit; - modwalker.setup(module); - - cells_to_remove.clear(); - recursion_state.clear(); - topo_cell_drivers.clear(); - topo_bit_drivers.clear(); - exclusive_ctrls.clear(); - terminal_bits.clear(); - shareable_cells.clear(); - forbidden_controls_cache.clear(); - activation_patterns_cache.clear(); + modwalker.setup(design, module); find_terminal_bits(); find_shareable_cells(); @@ -1173,8 +1154,8 @@ struct ShareWorker for (auto cell : module->cells()) if (cell->type == ID($pmux)) - for (auto bit : cell->getPort(ID::S)) - for (auto other_bit : cell->getPort(ID::S)) + for (auto bit : cell->getPort(ID(S))) + for (auto other_bit : cell->getPort(ID(S))) if (bit < other_bit) exclusive_ctrls.push_back(std::pair(bit, other_bit)); @@ -1418,8 +1399,8 @@ struct ShareWorker topo_cell_drivers[cell] = { supercell }; topo_cell_drivers[other_cell] = { supercell }; - if (limit > 0) - limit--; + if (config.limit > 0) + config.limit--; break; } @@ -1444,7 +1425,7 @@ struct ShareWorker struct SharePass : public Pass { SharePass() : Pass("share", "perform sat-based resource sharing") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1476,7 +1457,7 @@ struct SharePass : public Pass { log(" Only perform the first N merges, then stop. This is useful for debugging.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { ShareWorkerConfig config; @@ -1514,8 +1495,6 @@ struct SharePass : public Pass { config.generic_bin_ops.insert(ID($sub)); config.generic_bin_ops.insert(ID($div)); config.generic_bin_ops.insert(ID($mod)); - config.generic_bin_ops.insert(ID($divfloor)); - config.generic_bin_ops.insert(ID($modfloor)); // config.generic_bin_ops.insert(ID($pow)); config.generic_uni_ops.insert(ID($logic_not)); @@ -1549,10 +1528,9 @@ struct SharePass : public Pass { } extra_args(args, argidx, design); - ShareWorker sw(config, design); - - for (auto module : design->selected_modules()) - sw(module); + for (auto &mod_it : design->modules_) + if (design->selected(mod_it.second)) + ShareWorker(config, design, mod_it.second); } } SharePass; diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 78e2bcbea6d..04b882db921 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -37,10 +37,9 @@ struct WreduceConfig ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), - ID($add), ID($sub), ID($mul), // ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow), + ID($add), ID($sub), ID($mul), // ID($div), ID($mod), ID($pow), ID($mux), ID($pmux), - ID($dff), ID($dffe), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), - ID($dlatch), ID($adlatch), + ID($dff), ID($adff) }); } }; @@ -66,7 +65,7 @@ struct WreduceWorker SigSpec sig_a = mi.sigmap(cell->getPort(ID::A)); SigSpec sig_b = mi.sigmap(cell->getPort(ID::B)); - SigSpec sig_s = mi.sigmap(cell->getPort(ID::S)); + SigSpec sig_s = mi.sigmap(cell->getPort(ID(S))); SigSpec sig_y = mi.sigmap(cell->getPort(ID::Y)); std::vector bits_removed; @@ -99,7 +98,7 @@ struct WreduceWorker SigSpec sig_removed; for (int i = GetSize(bits_removed)-1; i >= 0; i--) - sig_removed.append(bits_removed[i]); + sig_removed.append_bit(bits_removed[i]); if (GetSize(bits_removed) == GetSize(sig_y)) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); @@ -142,22 +141,18 @@ struct WreduceWorker { // Reduce size of FF if inputs are just sign/zero extended or output bit is not used - SigSpec sig_d = mi.sigmap(cell->getPort(ID::D)); - SigSpec sig_q = mi.sigmap(cell->getPort(ID::Q)); - bool has_reset = false; - Const initval, rst_value; + SigSpec sig_d = mi.sigmap(cell->getPort(ID(D))); + SigSpec sig_q = mi.sigmap(cell->getPort(ID(Q))); + bool is_adff = (cell->type == ID($adff)); + Const initval, arst_value; int width_before = GetSize(sig_q); if (width_before == 0) return; - if (cell->parameters.count(ID::ARST_VALUE)) { - rst_value = cell->parameters[ID::ARST_VALUE]; - has_reset = true; - } else if (cell->parameters.count(ID::SRST_VALUE)) { - rst_value = cell->parameters[ID::SRST_VALUE]; - has_reset = true; + if (cell->parameters.count(ID(ARST_VALUE))) { + arst_value = cell->parameters[ID(ARST_VALUE)]; } bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0; @@ -174,7 +169,7 @@ struct WreduceWorker for (int i = GetSize(sig_q)-1; i >= 0; i--) { if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx) && - (!has_reset || i >= GetSize(rst_value) || rst_value[i] == State::S0 || rst_value[i] == State::Sx)) { + (!is_adff || i >= GetSize(arst_value) || arst_value[i] == State::S0 || arst_value[i] == State::Sx)) { module->connect(sig_q[i], State::S0); remove_init_bits.insert(sig_q[i]); sig_d.remove(i); @@ -183,7 +178,7 @@ struct WreduceWorker } if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1] && - (!has_reset || i >= GetSize(rst_value) || rst_value[i] == rst_value[i-1])) { + (!is_adff || i >= GetSize(arst_value) || arst_value[i] == arst_value[i-1])) { module->connect(sig_q[i], sig_q[i-1]); remove_init_bits.insert(sig_q[i]); sig_d.remove(i); @@ -225,16 +220,13 @@ struct WreduceWorker work_queue_bits.insert(bit); // Narrow ARST_VALUE parameter to new size. - if (cell->parameters.count(ID::ARST_VALUE)) { - rst_value.bits.resize(GetSize(sig_q)); - cell->setParam(ID::ARST_VALUE, rst_value); - } else if (cell->parameters.count(ID::SRST_VALUE)) { - rst_value.bits.resize(GetSize(sig_q)); - cell->setParam(ID::SRST_VALUE, rst_value); + if (cell->parameters.count(ID(ARST_VALUE))) { + arst_value.bits.resize(GetSize(sig_q)); + cell->setParam(ID(ARST_VALUE), arst_value); } - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->fixup_parameters(); } @@ -280,7 +272,7 @@ struct WreduceWorker if (cell->type.in(ID($mux), ID($pmux))) return run_cell_mux(cell); - if (cell->type.in(ID($dff), ID($dffe), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch))) + if (cell->type.in(ID($dff), ID($adff))) return run_cell_dff(cell); SigSpec sig = mi.sigmap(cell->getPort(ID::Y)); @@ -314,8 +306,8 @@ struct WreduceWorker GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", log_id(module), log_id(cell), log_id(cell->type)); - cell->setParam(ID::A_SIGNED, 0); - cell->setParam(ID::B_SIGNED, 0); + cell->setParam(ID(A_SIGNED), 0); + cell->setParam(ID(B_SIGNED), 0); port_a_signed = false; port_b_signed = false; did_something = true; @@ -327,7 +319,7 @@ struct WreduceWorker if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", log_id(module), log_id(cell), log_id(cell->type)); - cell->setParam(ID::A_SIGNED, 0); + cell->setParam(ID(A_SIGNED), 0); port_a_signed = false; did_something = true; } @@ -357,7 +349,7 @@ struct WreduceWorker if (cell->type.in(ID($pos), ID($add), ID($mul), ID($and), ID($or), ID($xor), ID($sub))) { - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool() || cell->type == ID($sub); + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool() || cell->type == ID($sub); int a_size = 0, b_size = 0; if (cell->hasPort(ID::A)) a_size = GetSize(cell->getPort(ID::A)); @@ -400,8 +392,8 @@ struct WreduceWorker static int count_nontrivial_wire_attrs(RTLIL::Wire *w) { int count = w->attributes.size(); - count -= w->attributes.count(ID::src); - count -= w->attributes.count(ID::unused_bits); + count -= w->attributes.count(ID(src)); + count -= w->attributes.count(ID(unused_bits)); return count; } @@ -414,8 +406,8 @@ struct WreduceWorker if (w->get_bool_attribute(ID::keep)) for (auto bit : mi.sigmap(w)) keep_bits.insert(bit); - if (w->attributes.count(ID::init)) { - Const initval = w->attributes.at(ID::init); + if (w->attributes.count(ID(init))) { + Const initval = w->attributes.at(ID(init)); SigSpec initsig = init_attr_sigmap(w); int width = std::min(GetSize(initval), GetSize(initsig)); for (int i = 0; i < width; i++) @@ -472,8 +464,8 @@ struct WreduceWorker if (!remove_init_bits.empty()) { for (auto w : module->wires()) { - if (w->attributes.count(ID::init)) { - Const initval = w->attributes.at(ID::init); + if (w->attributes.count(ID(init))) { + Const initval = w->attributes.at(ID(init)); Const new_initval(State::Sx, GetSize(w)); SigSpec initsig = init_attr_sigmap(w); int width = std::min(GetSize(initval), GetSize(initsig)); @@ -481,7 +473,7 @@ struct WreduceWorker if (!remove_init_bits.count(initsig[i])) new_initval[i] = initval[i]; } - w->attributes.at(ID::init) = new_initval; + w->attributes.at(ID(init)) = new_initval; } } } @@ -490,7 +482,7 @@ struct WreduceWorker struct WreducePass : public Pass { WreducePass() : Pass("wreduce", "reduce the word size of operations if possible") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -513,7 +505,7 @@ struct WreducePass : public Pass { log(" Do not optimize explicit don't-care values.\n"); log("\n"); } - void execute(std::vector args, Design *design) override + void execute(std::vector args, Design *design) YS_OVERRIDE { WreduceConfig config; bool opt_memx = false; @@ -547,17 +539,17 @@ struct WreducePass : public Pass { SigSpec sig = c->getPort(ID::Y); if (!sig.has_const()) { c->setPort(ID::Y, sig[0]); - c->setParam(ID::Y_WIDTH, 1); + c->setParam(ID(Y_WIDTH), 1); sig.remove(0); module->connect(sig, Const(0, GetSize(sig))); } } - if (c->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow))) + if (c->type.in(ID($div), ID($mod), ID($pow))) { SigSpec A = c->getPort(ID::A); int original_a_width = GetSize(A); - if (c->getParam(ID::A_SIGNED).as_bool()) { + if (c->getParam(ID(A_SIGNED)).as_bool()) { while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0) A.remove(GetSize(A)-1, 1); } else { @@ -568,12 +560,12 @@ struct WreducePass : public Pass { log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n", original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type)); c->setPort(ID::A, A); - c->setParam(ID::A_WIDTH, GetSize(A)); + c->setParam(ID(A_WIDTH), GetSize(A)); } SigSpec B = c->getPort(ID::B); int original_b_width = GetSize(B); - if (c->getParam(ID::B_SIGNED).as_bool()) { + if (c->getParam(ID(B_SIGNED)).as_bool()) { while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0) B.remove(GetSize(B)-1, 1); } else { @@ -584,23 +576,23 @@ struct WreducePass : public Pass { log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n", original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type)); c->setPort(ID::B, B); - c->setParam(ID::B_WIDTH, GetSize(B)); + c->setParam(ID(B_WIDTH), GetSize(B)); } } if (!opt_memx && c->type.in(ID($memrd), ID($memwr), ID($meminit))) { - IdString memid = c->getParam(ID::MEMID).decode_string(); + IdString memid = c->getParam(ID(MEMID)).decode_string(); RTLIL::Memory *mem = module->memories.at(memid); if (mem->start_offset >= 0) { - int cur_addrbits = c->getParam(ID::ABITS).as_int(); + int cur_addrbits = c->getParam(ID(ABITS)).as_int(); int max_addrbits = ceil_log2(mem->start_offset + mem->size); if (cur_addrbits > max_addrbits) { log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n", cur_addrbits-max_addrbits, cur_addrbits, c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init", log_id(module), log_id(c), log_id(memid)); - c->setParam(ID::ABITS, max_addrbits); - c->setPort(ID::ADDR, c->getPort(ID::ADDR).extract(0, max_addrbits)); + c->setParam(ID(ABITS), max_addrbits); + c->setPort(ID(ADDR), c->getPort(ID(ADDR)).extract(0, max_addrbits)); } } } diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 1a57bef7d94..145d2ebf989 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -22,9 +22,8 @@ $(eval $(call add_extra_objs,passes/pmgen/ice40_wrapcarry_pm.h)) # -------------------------------------- OBJS += passes/pmgen/xilinx_dsp.o -passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h passes/pmgen/xilinx_dsp48a_pm.h passes/pmgen/xilinx_dsp_CREG_pm.h passes/pmgen/xilinx_dsp_cascade_pm.h +passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h passes/pmgen/xilinx_dsp_CREG_pm.h passes/pmgen/xilinx_dsp_cascade_pm.h $(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_pm.h)) -$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp48a_pm.h)) $(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_CREG_pm.h)) $(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_cascade_pm.h)) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index fff04074bba..f60e6715812 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -73,11 +73,11 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Input Interface SigSpec A = st.sigA; - A.extend_u0(16, st.mul->getParam(ID::A_SIGNED).as_bool()); + A.extend_u0(16, st.mul->getParam(ID(A_SIGNED)).as_bool()); log_assert(GetSize(A) == 16); SigSpec B = st.sigB; - B.extend_u0(16, st.mul->getParam(ID::B_SIGNED).as_bool()); + B.extend_u0(16, st.mul->getParam(ID(B_SIGNED)).as_bool()); log_assert(GetSize(B) == 16); SigSpec CD = st.sigCD; @@ -88,8 +88,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort(ID::A, A); cell->setPort(ID::B, B); - cell->setPort(ID::C, CD.extract(16, 16)); - cell->setPort(ID::D, CD.extract(0, 16)); + cell->setPort(ID(C), CD.extract(16, 16)); + cell->setPort(ID(D), CD.extract(0, 16)); cell->setParam(ID(A_REG), st.ffA ? State::S1 : State::S0); cell->setParam(ID(B_REG), st.ffB ? State::S1 : State::S0); @@ -98,15 +98,15 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec AHOLD, BHOLD, CDHOLD; if (st.ffAholdmux) - AHOLD = st.ffAholdpol ? st.ffAholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffAholdmux->getPort(ID::S)); + AHOLD = st.ffAholdpol ? st.ffAholdmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffAholdmux->getPort(ID(S))); else AHOLD = State::S0; if (st.ffBholdmux) - BHOLD = st.ffBholdpol ? st.ffBholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffBholdmux->getPort(ID::S)); + BHOLD = st.ffBholdpol ? st.ffBholdmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffBholdmux->getPort(ID(S))); else BHOLD = State::S0; if (st.ffCDholdmux) - CDHOLD = st.ffCDholdpol ? st.ffCDholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffCDholdmux->getPort(ID::S)); + CDHOLD = st.ffCDholdpol ? st.ffCDholdmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffCDholdmux->getPort(ID(S))); else CDHOLD = State::S0; cell->setPort(ID(AHOLD), AHOLD); @@ -116,11 +116,11 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec IRSTTOP, IRSTBOT; if (st.ffArstmux) - IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffArstmux->getPort(ID::S)); + IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffArstmux->getPort(ID(S))); else IRSTTOP = State::S0; if (st.ffBrstmux) - IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffBrstmux->getPort(ID::S)); + IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffBrstmux->getPort(ID(S))); else IRSTBOT = State::S0; cell->setPort(ID(IRSTTOP), IRSTTOP); @@ -128,7 +128,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.clock != SigBit()) { - cell->setPort(ID::CLK, st.clock); + cell->setPort(ID(CLK), st.clock); cell->setPort(ID(CE), State::S1); cell->setParam(ID(NEG_TRIGGER), st.clock_pol ? State::S0 : State::S1); @@ -156,7 +156,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) } else { - cell->setPort(ID::CLK, State::S0); + cell->setPort(ID(CLK), State::S0); cell->setPort(ID(CE), State::S0); cell->setParam(ID(NEG_TRIGGER), State::S0); } @@ -166,7 +166,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort(ID(SIGNEXTIN), State::Sx); cell->setPort(ID(SIGNEXTOUT), pm.module->addWire(NEW_ID)); - cell->setPort(ID::CI, State::Sx); + cell->setPort(ID(CI), State::Sx); cell->setPort(ID(ACCUMCI), State::Sx); cell->setPort(ID(ACCUMCO), pm.module->addWire(NEW_ID)); @@ -178,19 +178,19 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (O_width == 33) { log_assert(st.add); // If we have a signed multiply-add, then perform sign extension - if (st.add->getParam(ID::A_SIGNED).as_bool() && st.add->getParam(ID::B_SIGNED).as_bool()) + if (st.add->getParam(ID(A_SIGNED)).as_bool() && st.add->getParam(ID(B_SIGNED)).as_bool()) pm.module->connect(O[32], O[31]); else - cell->setPort(ID::CO, O[32]); + cell->setPort(ID(CO), O[32]); O.remove(O_width-1); } else - cell->setPort(ID::CO, pm.module->addWire(NEW_ID)); + cell->setPort(ID(CO), pm.module->addWire(NEW_ID)); log_assert(GetSize(O) <= 32); if (GetSize(O) < 32) O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); - cell->setPort(ID::O, O); + cell->setPort(ID(O), O); bool accum = false; if (st.add) { @@ -208,7 +208,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec OHOLD; if (st.ffOholdmux) - OHOLD = st.ffOholdpol ? st.ffOholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffOholdmux->getPort(ID::S)); + OHOLD = st.ffOholdpol ? st.ffOholdmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffOholdmux->getPort(ID(S))); else OHOLD = State::S0; cell->setPort(ID(OHOLDTOP), OHOLD); @@ -216,7 +216,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec ORST; if (st.ffOrstmux) - ORST = st.ffOrstpol ? st.ffOrstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffOrstmux->getPort(ID::S)); + ORST = st.ffOrstpol ? st.ffOrstmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffOrstmux->getPort(ID(S))); else ORST = State::S0; cell->setPort(ID(ORSTTOP), ORST); @@ -225,9 +225,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec acc_reset = State::S0; if (st.mux) { if (st.muxAB == ID::A) - acc_reset = st.mux->getPort(ID::S); + acc_reset = st.mux->getPort(ID(S)); else - acc_reset = pm.module->Not(NEW_ID, st.mux->getPort(ID::S)); + acc_reset = pm.module->Not(NEW_ID, st.mux->getPort(ID(S))); } cell->setPort(ID(OLOADTOP), acc_reset); cell->setPort(ID(OLOADBOT), acc_reset); @@ -248,8 +248,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam(ID(BOTADDSUB_CARRYSELECT), Const(0, 2)); cell->setParam(ID(MODE_8x8), State::S0); - cell->setParam(ID::A_SIGNED, st.mul->getParam(ID::A_SIGNED).as_bool()); - cell->setParam(ID::B_SIGNED, st.mul->getParam(ID::B_SIGNED).as_bool()); + cell->setParam(ID(A_SIGNED), st.mul->getParam(ID(A_SIGNED)).as_bool()); + cell->setParam(ID(B_SIGNED), st.mul->getParam(ID(B_SIGNED)).as_bool()); if (st.ffO) { if (st.o_lo) @@ -257,7 +257,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) else cell->setParam(ID(TOPOUTPUT_SELECT), Const(1, 2)); - st.ffO->connections_.at(ID::Q).replace(O, pm.module->addWire(NEW_ID, GetSize(O))); + st.ffO->connections_.at(ID(Q)).replace(O, pm.module->addWire(NEW_ID, GetSize(O))); cell->setParam(ID(BOTOUTPUT_SELECT), Const(1, 2)); } else { @@ -275,7 +275,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) struct Ice40DspPass : public Pass { Ice40DspPass() : Pass("ice40_dsp", "iCE40: map multipliers") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -294,7 +294,7 @@ struct Ice40DspPass : public Pass { log("the accumulator to an arbitrary value can be inferred to use the {C,D} input.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ICE40_DSP pass (map multipliers).\n"); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 2456a49dc74..6b6d2b56fc7 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -56,11 +56,6 @@ code sigA sigB sigH break; sigH.append(O[i]); } - // This sigM could have no users if downstream sinks (e.g. $add) is - // narrower than $mul result, for example - if (i == 0) - reject; - log_assert(nusers(O.extract_end(i)) <= 1); endcode @@ -229,7 +224,7 @@ endcode code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo if (mul->type != \SB_MAC16 || // Ensure that register is not already used - ((param(mul, \TOPOUTPUT_SELECT).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT).as_int() != 1) && + ((param(mul, \TOPOUTPUT_SELECT, 0).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT, 0).as_int() != 1) && // Ensure that OLOADTOP/OLOADBOT is unused or zero (port(mul, \OLOADTOP, State::S0).is_fully_zero() && port(mul, \OLOADBOT, State::S0).is_fully_zero()))) { @@ -333,8 +328,6 @@ arg argD argQ clock clock_pol code dff = nullptr; - if (argQ.empty()) - reject; for (auto c : argQ.chunks()) { if (!c.wire) reject; @@ -532,7 +525,7 @@ endcode match ff select ff->type.in($dff) - // SB_MAC16 does not support clock inversion + // DSP48E1 does not support clock inversion select param(ff, \CLK_POLARITY).as_bool() slice offset GetSize(port(ff, \D)) diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc index e234906ad03..69ef3cd8253 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -37,34 +37,18 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) log(" replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n"); - Cell *cell = pm.module->addCell(NEW_ID, ID($__ICE40_CARRY_WRAPPER)); + Cell *cell = pm.module->addCell(NEW_ID, "$__ICE40_CARRY_WRAPPER"); pm.module->swap_names(cell, st.carry); - cell->setPort(ID::A, st.carry->getPort(ID(I0))); - cell->setPort(ID::B, st.carry->getPort(ID(I1))); - auto CI = st.carry->getPort(ID::CI); - cell->setPort(ID::CI, CI); - cell->setPort(ID::CO, st.carry->getPort(ID::CO)); + 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(ID(I0), st.lut->getPort(ID(I0))); - auto I3 = st.lut->getPort(ID(I3)); - if (pm.sigmap(CI) == pm.sigmap(I3)) { - cell->setParam(ID(I3_IS_CI), State::S1); - I3 = State::Sx; - } - else - cell->setParam(ID(I3_IS_CI), State::S0); - cell->setPort(ID(I3), I3); - cell->setPort(ID::O, st.lut->getPort(ID::O)); - cell->setParam(ID::LUT, st.lut->getParam(ID(LUT_INIT))); - - for (const auto &a : st.carry->attributes) - cell->attributes[stringf("\\SB_CARRY.%s", a.first.c_str())] = a.second; - for (const auto &a : st.lut->attributes) - cell->attributes[stringf("\\SB_LUT4.%s", a.first.c_str())] = a.second; - cell->attributes[ID(SB_LUT4.name)] = Const(st.lut->name.str()); - if (st.carry->get_bool_attribute(ID::keep) || st.lut->get_bool_attribute(ID::keep)) - cell->attributes[ID::keep] = true; + 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); @@ -72,86 +56,34 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) struct Ice40WrapCarryPass : public Pass { Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { } - void help() override + 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_LUT4s,\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.\n"); - log("\n"); - log("Attributes on both cells will have their names prefixed with 'SB_CARRY.' or\n"); - log("'SB_LUT4.' and attached to the wrapping cell.\n"); - log("A (* keep *) attribute on either cell will be logically OR-ed together.\n"); - log("\n"); - log(" -unwrap\n"); - log(" unwrap $__ICE40_CARRY_WRAPPER cells back into SB_CARRYs and SB_LUT4s,\n"); - log(" including restoring their attributes.\n"); + log("mapping."); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - bool unwrap = false; - log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-unwrap") { - unwrap = true; - continue; - } + // if (args[argidx] == "-singleton") { + // singleton_mode = true; + // continue; + // } break; } extra_args(args, argidx, design); - for (auto module : design->selected_modules()) { - if (!unwrap) - ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry); - else { - for (auto cell : module->selected_cells()) { - if (cell->type != ID($__ICE40_CARRY_WRAPPER)) - continue; - - auto carry = module->addCell(NEW_ID, ID(SB_CARRY)); - carry->setPort(ID(I0), cell->getPort(ID::A)); - carry->setPort(ID(I1), cell->getPort(ID::B)); - carry->setPort(ID::CI, cell->getPort(ID::CI)); - carry->setPort(ID::CO, cell->getPort(ID::CO)); - module->swap_names(carry, cell); - auto lut_name = cell->attributes.at(ID(SB_LUT4.name), Const(NEW_ID.str())).decode_string(); - auto lut = module->addCell(lut_name, ID($lut)); - lut->setParam(ID::WIDTH, 4); - lut->setParam(ID::LUT, cell->getParam(ID::LUT)); - auto I3 = cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID::CI : ID(I3)); - lut->setPort(ID::A, { I3, cell->getPort(ID::B), cell->getPort(ID::A), cell->getPort(ID(I0)) }); - lut->setPort(ID::Y, cell->getPort(ID::O)); - - Const src; - for (const auto &a : cell->attributes) - if (a.first.begins_with("\\SB_CARRY.\\")) - carry->attributes[a.first.c_str() + strlen("\\SB_CARRY.")] = a.second; - else if (a.first.begins_with("\\SB_LUT4.\\")) - lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; - else if (a.first == ID::src) - src = a.second; - else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID::module_not_derived)) - continue; - else - log_abort(); - - if (!src.empty()) { - carry->attributes.insert(std::make_pair(ID::src, src)); - lut->attributes.insert(std::make_pair(ID::src, src)); - } - - module->remove(cell); - } - } - } + for (auto module : design->selected_modules()) + ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry); } } Ice40WrapCarryPass; diff --git a/passes/pmgen/peepopt.cc b/passes/pmgen/peepopt.cc index c16b4486dca..2230145df94 100644 --- a/passes/pmgen/peepopt.cc +++ b/passes/pmgen/peepopt.cc @@ -32,7 +32,7 @@ pool rminitbits; struct PeepoptPass : public Pass { PeepoptPass() : Pass("peepopt", "collection of peephole optimizers") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -41,7 +41,7 @@ struct PeepoptPass : public Pass { log("This pass applies a collection of peephole optimizers to the current design.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string genmode; @@ -87,7 +87,7 @@ struct PeepoptPass : public Pass { peepopt_pm pm(module); for (auto w : module->wires()) { - auto it = w->attributes.find(ID::init); + auto it = w->attributes.find(ID(init)); if (it != w->attributes.end()) { SigSpec sig = pm.sigmap(w); Const val = it->second; @@ -109,7 +109,7 @@ struct PeepoptPass : public Pass { pm.run_dffmux(); for (auto w : module->wires()) { - auto it = w->attributes.find(ID::init); + auto it = w->attributes.find(ID(init)); if (it != w->attributes.end()) { SigSpec sig = pm.sigmap(w); Const &val = it->second; diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 592a26fa67f..df0ffaff287 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -589,7 +589,7 @@ def process_pmgfile(f, filename): if block["type"] in ("match", "code"): print(" // {}".format(block["src"]), file=f) - print(" void block_{}(int recursion YS_MAYBE_UNUSED) {{".format(index), file=f) + print(" void block_{}(int recursion YS_ATTRIBUTE(unused)) {{".format(index), file=f) current_pattern, current_subpattern = block["pattern"] if block["type"] == "final": @@ -636,17 +636,17 @@ def process_pmgfile(f, filename): for s in sorted(const_st): t = state_types[current_pattern][s] if t.endswith("*"): - print(" {} const &{} YS_MAYBE_UNUSED = st_{}.{};".format(t, s, current_pattern, s), file=f) + print(" {} const &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f) else: - print(" const {} &{} YS_MAYBE_UNUSED = st_{}.{};".format(t, s, current_pattern, s), file=f) + print(" const {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f) for s in sorted(nonconst_st): t = state_types[current_pattern][s] - print(" {} &{} YS_MAYBE_UNUSED = st_{}.{};".format(t, s, current_pattern, s), file=f) + print(" {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f) for u in sorted(udata_types[current_pattern].keys()): t = udata_types[current_pattern][u] - print(" {} &{} YS_MAYBE_UNUSED = ud_{}.{};".format(t, u, current_pattern, u), file=f) + print(" {} &{} YS_ATTRIBUTE(unused) = ud_{}.{};".format(t, u, current_pattern, u), file=f) if len(restore_st): print("", file=f) @@ -676,7 +676,7 @@ def process_pmgfile(f, filename): print("", file=f) print("rollback_label:", file=f) - print(" YS_MAYBE_UNUSED;", file=f) + print(" YS_ATTRIBUTE(unused);", file=f) if len(block["fcode"]): print("#define accept do { accept_cnt++; on_accept(); } while(0)", file=f) @@ -684,7 +684,7 @@ def process_pmgfile(f, filename): for line in block["fcode"]: print(" " + line, file=f) print("finish_label:", file=f) - print(" YS_MAYBE_UNUSED;", file=f) + print(" YS_ATTRIBUTE(unused);", file=f) print("#undef accept", file=f) print("#undef finish", file=f) @@ -733,13 +733,13 @@ def process_pmgfile(f, filename): valueidx = 1 for item in block["setup"]: if item[0] == "slice": - print(" const int &{} YS_MAYBE_UNUSED = std::get<{}>(cells[_pmg_idx]);".format(item[1], valueidx), file=f) + print(" const int &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], valueidx), file=f) valueidx += 1 if item[0] == "choice": - print(" const {} &{} YS_MAYBE_UNUSED = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f) + print(" const {} &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f) valueidx += 1 if item[0] == "define": - print(" const {} &{} YS_MAYBE_UNUSED = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f) + print(" const {} &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f) valueidx += 1 print(" if (blacklist_cells.count({})) continue;".format(block["cell"]), file=f) for expr in block["filter"]: diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc index 7b2938ddffc..72dc18dcce0 100644 --- a/passes/pmgen/test_pmgen.cc +++ b/passes/pmgen/test_pmgen.cc @@ -40,16 +40,16 @@ void reduce_chain(test_pmgen_pm &pm) log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); SigSpec A; - SigSpec Y = ud.longest_chain.front().first->getPort(ID::Y); + SigSpec Y = ud.longest_chain.front().first->getPort(ID(Y)); auto last_cell = ud.longest_chain.back().first; for (auto it : ud.longest_chain) { auto cell = it.first; if (cell == last_cell) { - A.append(cell->getPort(ID::A)); - A.append(cell->getPort(ID::B)); + A.append(cell->getPort(ID(A))); + A.append(cell->getPort(ID(B))); } else { - A.append(cell->getPort(it.second == ID::A ? ID::B : ID::A)); + A.append(cell->getPort(it.second == ID(A) ? ID(B) : ID(A))); } log(" %s\n", log_id(cell)); pm.autoremove(cell); @@ -78,7 +78,7 @@ void reduce_tree(test_pmgen_pm &pm) return; SigSpec A = ud.leaves; - SigSpec Y = st.first->getPort(ID::Y); + SigSpec Y = st.first->getPort(ID(Y)); pm.autoremove(st.first); log("Found %s tree with %d leaves for %s (%s).\n", log_id(st.first->type), @@ -118,7 +118,7 @@ void opt_eqpmux(test_pmgen_pm &pm) struct TestPmgenPass : public Pass { TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -239,7 +239,7 @@ struct TestPmgenPass : public Pass { log_cmd_error("Unknown pattern: %s\n", pattern.c_str()); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { if (GetSize(args) > 1) { diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index d0515727073..054e123e49a 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -26,7 +26,6 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN #include "passes/pmgen/xilinx_dsp_pm.h" -#include "passes/pmgen/xilinx_dsp48a_pm.h" #include "passes/pmgen/xilinx_dsp_CREG_pm.h" #include "passes/pmgen/xilinx_dsp_cascade_pm.h" @@ -52,7 +51,7 @@ static Cell* addDsp(Module *module) { cell->setParam(ID(USE_SIMD), Const("ONE48")); cell->setParam(ID(USE_DPORT), Const("FALSE")); - cell->setPort(ID::D, Const(0, 25)); + cell->setPort(ID(D), Const(0, 25)); cell->setPort(ID(INMODE), Const(0, 5)); cell->setPort(ID(ALUMODE), Const(0, 4)); cell->setPort(ID(OPMODE), Const(0, 7)); @@ -72,15 +71,15 @@ void xilinx_simd_pack(Module *module, const std::vector &selected_cells) for (auto cell : selected_cells) { if (!cell->type.in(ID($add), ID($sub))) continue; - SigSpec Y = cell->getPort(ID::Y); + SigSpec Y = cell->getPort(ID(Y)); if (!Y.is_chunk()) continue; if (!Y.as_chunk().wire->get_strpool_attribute(ID(use_dsp)).count("simd")) continue; if (GetSize(Y) > 25) continue; - SigSpec A = cell->getPort(ID::A); - SigSpec B = cell->getPort(ID::B); + SigSpec A = cell->getPort(ID(A)); + SigSpec B = cell->getPort(ID(B)); if (GetSize(Y) <= 13) { if (GetSize(A) > 12) continue; @@ -106,11 +105,11 @@ void xilinx_simd_pack(Module *module, const std::vector &selected_cells) } auto f12 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) { - SigSpec A = lane->getPort(ID::A); - SigSpec B = lane->getPort(ID::B); - SigSpec Y = lane->getPort(ID::Y); - A.extend_u0(12, lane->getParam(ID::A_SIGNED).as_bool()); - B.extend_u0(12, lane->getParam(ID::B_SIGNED).as_bool()); + SigSpec A = lane->getPort(ID(A)); + SigSpec B = lane->getPort(ID(B)); + SigSpec Y = lane->getPort(ID(Y)); + A.extend_u0(12, lane->getParam(ID(A_SIGNED)).as_bool()); + B.extend_u0(12, lane->getParam(ID(B_SIGNED)).as_bool()); AB.append(A); C.append(B); if (GetSize(Y) < 13) @@ -174,10 +173,10 @@ void xilinx_simd_pack(Module *module, const std::vector &selected_cells) log_assert(GetSize(C) == 48); log_assert(GetSize(P) == 48); log_assert(GetSize(CARRYOUT) == 4); - cell->setPort(ID::A, AB.extract(18, 30)); - cell->setPort(ID::B, AB.extract(0, 18)); - cell->setPort(ID::C, C); - cell->setPort(ID::P, P); + cell->setPort(ID(A), AB.extract(18, 30)); + cell->setPort(ID(B), AB.extract(0, 18)); + cell->setPort(ID(C), C); + cell->setPort(ID(P), P); cell->setPort(ID(CARRYOUT), CARRYOUT); if (lane1->type == ID($sub)) cell->setPort(ID(ALUMODE), Const::from_string("0011")); @@ -194,11 +193,11 @@ void xilinx_simd_pack(Module *module, const std::vector &selected_cells) g12(simd12_sub); auto f24 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) { - SigSpec A = lane->getPort(ID::A); - SigSpec B = lane->getPort(ID::B); - SigSpec Y = lane->getPort(ID::Y); - A.extend_u0(24, lane->getParam(ID::A_SIGNED).as_bool()); - B.extend_u0(24, lane->getParam(ID::B_SIGNED).as_bool()); + SigSpec A = lane->getPort(ID(A)); + SigSpec B = lane->getPort(ID(B)); + SigSpec Y = lane->getPort(ID(Y)); + A.extend_u0(24, lane->getParam(ID(A_SIGNED)).as_bool()); + B.extend_u0(24, lane->getParam(ID(B_SIGNED)).as_bool()); C.append(A); AB.append(B); if (GetSize(Y) < 25) @@ -238,10 +237,10 @@ void xilinx_simd_pack(Module *module, const std::vector &selected_cells) log_assert(GetSize(C) == 48); log_assert(GetSize(P) == 48); log_assert(GetSize(CARRYOUT) == 4); - cell->setPort(ID::A, AB.extract(18, 30)); - cell->setPort(ID::B, AB.extract(0, 18)); - cell->setPort(ID::C, C); - cell->setPort(ID::P, P); + cell->setPort(ID(A), AB.extract(18, 30)); + cell->setPort(ID(B), AB.extract(0, 18)); + cell->setPort(ID(C), C); + cell->setPort(ID(P), P); cell->setPort(ID(CARRYOUT), CARRYOUT); if (lane1->type == ID($sub)) cell->setPort(ID(ALUMODE), Const::from_string("0011")); @@ -280,19 +279,19 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) if (st.preAdd) { log(" preadder %s (%s)\n", log_id(st.preAdd), log_id(st.preAdd->type)); - bool A_SIGNED = st.preAdd->getParam(ID::A_SIGNED).as_bool(); - bool D_SIGNED = st.preAdd->getParam(ID::B_SIGNED).as_bool(); - if (st.sigA == st.preAdd->getPort(ID::B)) + bool A_SIGNED = st.preAdd->getParam(ID(A_SIGNED)).as_bool(); + bool D_SIGNED = st.preAdd->getParam(ID(B_SIGNED)).as_bool(); + if (st.sigA == st.preAdd->getPort(ID(B))) std::swap(A_SIGNED, D_SIGNED); st.sigA.extend_u0(30, A_SIGNED); st.sigD.extend_u0(25, D_SIGNED); - cell->setPort(ID::A, st.sigA); - cell->setPort(ID::D, st.sigD); + cell->setPort(ID(A), st.sigA); + cell->setPort(ID(D), st.sigD); cell->setPort(ID(INMODE), Const::from_string("00100")); if (st.ffAD) { if (st.ffADcemux) { - SigSpec S = st.ffADcemux->getPort(ID::S); + SigSpec S = st.ffADcemux->getPort(ID(S)); cell->setPort(ID(CEAD), st.ffADcepol ? S : pm.module->Not(NEW_ID, S)); } else @@ -310,7 +309,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) SigSpec &opmode = cell->connections_.at(ID(OPMODE)); if (st.postAddMux) { log_assert(st.ffP); - opmode[4] = st.postAddMux->getPort(ID::S); + opmode[4] = st.postAddMux->getPort(ID(S)); pm.autoremove(st.postAddMux); } else if (st.ffP && st.sigC == st.sigP) @@ -321,11 +320,11 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) opmode[5] = State::S1; if (opmode[4] != State::S0) { - if (st.postAddMuxAB == ID::A) - st.sigC.extend_u0(48, st.postAdd->getParam(ID::B_SIGNED).as_bool()); + if (st.postAddMuxAB == ID(A)) + st.sigC.extend_u0(48, st.postAdd->getParam(ID(B_SIGNED)).as_bool()); else - st.sigC.extend_u0(48, st.postAdd->getParam(ID::A_SIGNED).as_bool()); - cell->setPort(ID::C, st.sigC); + st.sigC.extend_u0(48, st.postAdd->getParam(ID(A_SIGNED)).as_bool()); + cell->setPort(ID(C), st.sigC); } pm.autoremove(st.postAdd); @@ -337,7 +336,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) cell->setParam(ID(SEL_MASK), Const("MASK")); if (st.overflow->type == ID($ge)) { - Const B = st.overflow->getPort(ID::B).as_const(); + Const B = st.overflow->getPort(ID(B)).as_const(); log_assert(std::count(B.bits.begin(), B.bits.end(), State::S1) == 1); // Since B is an exact power of 2, subtract 1 // by inverting all bits up until hitting @@ -352,7 +351,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) cell->setParam(ID(MASK), B); cell->setParam(ID(PATTERN), Const(0, 48)); - cell->setPort(ID(OVERFLOW), st.overflow->getPort(ID::Y)); + cell->setPort(ID(OVERFLOW), st.overflow->getPort(ID(Y))); } else log_abort(); @@ -361,29 +360,29 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) if (st.clock != SigBit()) { - cell->setPort(ID::CLK, st.clock); + cell->setPort(ID(CLK), st.clock); auto f = [&pm,cell](SigSpec &A, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) { - SigSpec D = ff->getPort(ID::D); - SigSpec Q = pm.sigmap(ff->getPort(ID::Q)); + SigSpec D = ff->getPort(ID(D)); + SigSpec Q = pm.sigmap(ff->getPort(ID(Q))); if (!A.empty()) A.replace(Q, D); if (rstmux) { - SigSpec Y = rstmux->getPort(ID::Y); - SigSpec AB = rstmux->getPort(rstpol ? ID::A : ID::B); + SigSpec Y = rstmux->getPort(ID(Y)); + SigSpec AB = rstmux->getPort(rstpol ? ID(A) : ID(B)); if (!A.empty()) A.replace(Y, AB); if (rstport != IdString()) { - SigSpec S = rstmux->getPort(ID::S); + SigSpec S = rstmux->getPort(ID(S)); cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S)); } } else if (rstport != IdString()) cell->setPort(rstport, State::S0); if (cemux) { - SigSpec Y = cemux->getPort(ID::Y); - SigSpec BA = cemux->getPort(cepol ? ID::B : ID::A); - SigSpec S = cemux->getPort(ID::S); + SigSpec Y = cemux->getPort(ID(Y)); + SigSpec BA = cemux->getPort(cepol ? ID(B) : ID(A)); + SigSpec S = cemux->getPort(ID(S)); if (!A.empty()) A.replace(Y, BA); cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S)); @@ -392,7 +391,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) cell->setPort(ceport, State::S1); for (auto c : Q.chunks()) { - auto it = c.wire->attributes.find(ID::init); + auto it = c.wire->attributes.find(ID(init)); if (it == c.wire->attributes.end()) continue; for (int i = c.offset; i < c.offset+c.width; i++) { @@ -403,7 +402,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) }; if (st.ffA2) { - SigSpec A = cell->getPort(ID::A); + SigSpec A = cell->getPort(ID(A)); f(A, st.ffA2, st.ffA2cemux, st.ffA2cepol, ID(CEA2), st.ffA2rstmux, st.ffArstpol, ID(RSTA)); if (st.ffA1) { f(A, st.ffA1, st.ffA1cemux, st.ffA1cepol, ID(CEA1), st.ffA1rstmux, st.ffArstpol, IdString()); @@ -415,10 +414,10 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) cell->setParam(ID(ACASCREG), 1); } pm.add_siguser(A, cell); - cell->setPort(ID::A, A); + cell->setPort(ID(A), A); } if (st.ffB2) { - SigSpec B = cell->getPort(ID::B); + SigSpec B = cell->getPort(ID(B)); f(B, st.ffB2, st.ffB2cemux, st.ffB2cepol, ID(CEB2), st.ffB2rstmux, st.ffBrstpol, ID(RSTB)); if (st.ffB1) { f(B, st.ffB1, st.ffB1cemux, st.ffB1cepol, ID(CEB1), st.ffB1rstmux, st.ffBrstpol, IdString()); @@ -430,25 +429,25 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) cell->setParam(ID(BCASCREG), 1); } pm.add_siguser(B, cell); - cell->setPort(ID::B, B); + cell->setPort(ID(B), B); } if (st.ffD) { - SigSpec D = cell->getPort(ID::D); + SigSpec D = cell->getPort(ID(D)); f(D, st.ffD, st.ffDcemux, st.ffDcepol, ID(CED), st.ffDrstmux, st.ffDrstpol, ID(RSTD)); pm.add_siguser(D, cell); - cell->setPort(ID::D, D); + cell->setPort(ID(D), D); cell->setParam(ID(DREG), 1); } if (st.ffM) { SigSpec M; // unused f(M, st.ffM, st.ffMcemux, st.ffMcepol, ID(CEM), st.ffMrstmux, st.ffMrstpol, ID(RSTM)); - st.ffM->connections_.at(ID::Q).replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM))); + st.ffM->connections_.at(ID(Q)).replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM))); cell->setParam(ID(MREG), State::S1); } if (st.ffP) { SigSpec P; // unused f(P, st.ffP, st.ffPcemux, st.ffPcepol, ID(CEP), st.ffPrstmux, st.ffPrstpol, ID(RSTP)); - st.ffP->connections_.at(ID::Q).replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP))); + st.ffP->connections_.at(ID(Q)).replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP))); cell->setParam(ID(PREG), State::S1); } @@ -483,191 +482,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) SigSpec P = st.sigP; if (GetSize(P) < 48) P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); - cell->setPort(ID::P, P); - - pm.blacklist(cell); -} - -void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) -{ - auto &st = pm.st_xilinx_dsp48a_pack; - - log("Analysing %s.%s for Xilinx DSP48A/DSP48A1 packing.\n", log_id(pm.module), log_id(st.dsp)); - - log_debug("preAdd: %s\n", log_id(st.preAdd, "--")); - log_debug("ffA1: %s %s %s\n", log_id(st.ffA1, "--"), log_id(st.ffA1cemux, "--"), log_id(st.ffA1rstmux, "--")); - log_debug("ffA0: %s %s %s\n", log_id(st.ffA0, "--"), log_id(st.ffA0cemux, "--"), log_id(st.ffA0rstmux, "--")); - log_debug("ffB1: %s %s %s\n", log_id(st.ffB1, "--"), log_id(st.ffB1cemux, "--"), log_id(st.ffB1rstmux, "--")); - log_debug("ffB0: %s %s %s\n", log_id(st.ffB0, "--"), log_id(st.ffB0cemux, "--"), log_id(st.ffB0rstmux, "--")); - log_debug("ffD: %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--")); - log_debug("dsp: %s\n", log_id(st.dsp, "--")); - log_debug("ffM: %s %s %s\n", log_id(st.ffM, "--"), log_id(st.ffMcemux, "--"), log_id(st.ffMrstmux, "--")); - log_debug("postAdd: %s\n", log_id(st.postAdd, "--")); - log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--")); - log_debug("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--")); - - Cell *cell = st.dsp; - SigSpec &opmode = cell->connections_.at(ID(OPMODE)); - - if (st.preAdd) { - log(" preadder %s (%s)\n", log_id(st.preAdd), log_id(st.preAdd->type)); - bool D_SIGNED = st.preAdd->getParam(ID::A_SIGNED).as_bool(); - bool B_SIGNED = st.preAdd->getParam(ID::B_SIGNED).as_bool(); - st.sigB.extend_u0(18, B_SIGNED); - st.sigD.extend_u0(18, D_SIGNED); - cell->setPort(ID::B, st.sigB); - cell->setPort(ID::D, st.sigD); - opmode[4] = State::S1; - if (st.preAdd->type == ID($add)) - opmode[6] = State::S0; - else if (st.preAdd->type == ID($sub)) - opmode[6] = State::S1; - else - log_assert(!"strange pre-adder type"); - - pm.autoremove(st.preAdd); - } - if (st.postAdd) { - log(" postadder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); - - if (st.postAddMux) { - log_assert(st.ffP); - opmode[2] = st.postAddMux->getPort(ID::S); - pm.autoremove(st.postAddMux); - } - else if (st.ffP && st.sigC == st.sigP) - opmode[2] = State::S0; - else - opmode[2] = State::S1; - opmode[3] = State::S1; - - if (opmode[2] != State::S0) { - if (st.postAddMuxAB == ID::A) - st.sigC.extend_u0(48, st.postAdd->getParam(ID::B_SIGNED).as_bool()); - else - st.sigC.extend_u0(48, st.postAdd->getParam(ID::A_SIGNED).as_bool()); - cell->setPort(ID::C, st.sigC); - } - - pm.autoremove(st.postAdd); - } - - if (st.clock != SigBit()) - { - cell->setPort(ID::CLK, st.clock); - - auto f = [&pm,cell](SigSpec &A, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) { - SigSpec D = ff->getPort(ID::D); - SigSpec Q = pm.sigmap(ff->getPort(ID::Q)); - if (!A.empty()) - A.replace(Q, D); - if (rstmux) { - SigSpec Y = rstmux->getPort(ID::Y); - SigSpec AB = rstmux->getPort(rstpol ? ID::A : ID::B); - if (!A.empty()) - A.replace(Y, AB); - if (rstport != IdString()) { - SigSpec S = rstmux->getPort(ID::S); - cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S)); - } - } - else if (rstport != IdString()) - cell->setPort(rstport, State::S0); - if (cemux) { - SigSpec Y = cemux->getPort(ID::Y); - SigSpec BA = cemux->getPort(cepol ? ID::B : ID::A); - SigSpec S = cemux->getPort(ID::S); - if (!A.empty()) - A.replace(Y, BA); - cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S)); - } - else - cell->setPort(ceport, State::S1); - - for (auto c : Q.chunks()) { - auto it = c.wire->attributes.find(ID::init); - if (it == c.wire->attributes.end()) - continue; - for (int i = c.offset; i < c.offset+c.width; i++) { - log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); - it->second[i] = State::Sx; - } - } - }; - - if (st.ffA0 || st.ffA1) { - SigSpec A = cell->getPort(ID::A); - if (st.ffA1) { - f(A, st.ffA1, st.ffA1cemux, st.ffAcepol, ID(CEA), st.ffA1rstmux, st.ffArstpol, ID(RSTA)); - cell->setParam(ID(A1REG), 1); - } - if (st.ffA0) { - f(A, st.ffA0, st.ffA0cemux, st.ffAcepol, ID(CEA), st.ffA0rstmux, st.ffArstpol, ID(RSTA)); - cell->setParam(ID(A0REG), 1); - } - pm.add_siguser(A, cell); - cell->setPort(ID::A, A); - } - if (st.ffB0 || st.ffB1) { - SigSpec B = cell->getPort(ID::B); - if (st.ffB1) { - f(B, st.ffB1, st.ffB1cemux, st.ffBcepol, ID(CEB), st.ffB1rstmux, st.ffBrstpol, ID(RSTB)); - cell->setParam(ID(B1REG), 1); - } - if (st.ffB0) { - f(B, st.ffB0, st.ffB0cemux, st.ffBcepol, ID(CEB), st.ffB0rstmux, st.ffBrstpol, ID(RSTB)); - cell->setParam(ID(B0REG), 1); - } - pm.add_siguser(B, cell); - cell->setPort(ID::B, B); - } - if (st.ffD) { - SigSpec D = cell->getPort(ID::D); - f(D, st.ffD, st.ffDcemux, st.ffDcepol, ID(CED), st.ffDrstmux, st.ffDrstpol, ID(RSTD)); - pm.add_siguser(D, cell); - cell->setPort(ID::D, D); - cell->setParam(ID(DREG), 1); - } - if (st.ffM) { - SigSpec M; // unused - f(M, st.ffM, st.ffMcemux, st.ffMcepol, ID(CEM), st.ffMrstmux, st.ffMrstpol, ID(RSTM)); - st.ffM->connections_.at(ID::Q).replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM))); - cell->setParam(ID(MREG), State::S1); - } - if (st.ffP) { - SigSpec P; // unused - f(P, st.ffP, st.ffPcemux, st.ffPcepol, ID(CEP), st.ffPrstmux, st.ffPrstpol, ID(RSTP)); - st.ffP->connections_.at(ID::Q).replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP))); - cell->setParam(ID(PREG), State::S1); - } - - log(" clock: %s (%s)", log_signal(st.clock), "posedge"); - - if (st.ffA0) - log(" ffA0:%s", log_id(st.ffA0)); - if (st.ffA1) - log(" ffA1:%s", log_id(st.ffA1)); - - if (st.ffB0) - log(" ffB0:%s", log_id(st.ffB0)); - if (st.ffB1) - log(" ffB1:%s", log_id(st.ffB1)); - - if (st.ffD) - log(" ffD:%s", log_id(st.ffD)); - - if (st.ffM) - log(" ffM:%s", log_id(st.ffM)); - - if (st.ffP) - log(" ffP:%s", log_id(st.ffP)); - } - log("\n"); - - SigSpec P = st.sigP; - if (GetSize(P) < 48) - P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); - cell->setPort(ID::P, P); + cell->setPort(ID(P), P); pm.blacklist(cell); } @@ -683,29 +498,29 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) if (st.clock != SigBit()) { - cell->setPort(ID::CLK, st.clock); + cell->setPort(ID(CLK), st.clock); auto f = [&pm,cell](SigSpec &A, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) { - SigSpec D = ff->getPort(ID::D); - SigSpec Q = pm.sigmap(ff->getPort(ID::Q)); + SigSpec D = ff->getPort(ID(D)); + SigSpec Q = pm.sigmap(ff->getPort(ID(Q))); if (!A.empty()) A.replace(Q, D); if (rstmux) { - SigSpec Y = rstmux->getPort(ID::Y); - SigSpec AB = rstmux->getPort(rstpol ? ID::A : ID::B); + SigSpec Y = rstmux->getPort(ID(Y)); + SigSpec AB = rstmux->getPort(rstpol ? ID(A) : ID(B)); if (!A.empty()) A.replace(Y, AB); if (rstport != IdString()) { - SigSpec S = rstmux->getPort(ID::S); + SigSpec S = rstmux->getPort(ID(S)); cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S)); } } else if (rstport != IdString()) cell->setPort(rstport, State::S0); if (cemux) { - SigSpec Y = cemux->getPort(ID::Y); - SigSpec BA = cemux->getPort(cepol ? ID::B : ID::A); - SigSpec S = cemux->getPort(ID::S); + SigSpec Y = cemux->getPort(ID(Y)); + SigSpec BA = cemux->getPort(cepol ? ID(B) : ID(A)); + SigSpec S = cemux->getPort(ID(S)); if (!A.empty()) A.replace(Y, BA); cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S)); @@ -714,7 +529,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) cell->setPort(ceport, State::S1); for (auto c : Q.chunks()) { - auto it = c.wire->attributes.find(ID::init); + auto it = c.wire->attributes.find(ID(init)); if (it == c.wire->attributes.end()) continue; for (int i = c.offset; i < c.offset+c.width; i++) { @@ -725,10 +540,10 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) }; if (st.ffC) { - SigSpec C = cell->getPort(ID::C); + SigSpec C = cell->getPort(ID(C)); f(C, st.ffC, st.ffCcemux, st.ffCcepol, ID(CEC), st.ffCrstmux, st.ffCrstpol, ID(RSTC)); pm.add_siguser(C, cell); - cell->setPort(ID::C, C); + cell->setPort(ID(C), C); cell->setParam(ID(CREG), 1); } @@ -744,7 +559,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) struct XilinxDspPass : public Pass { XilinxDspPass() : Pass("xilinx_dsp", "Xilinx: pack resources into DSPs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -767,9 +582,6 @@ struct XilinxDspPass : public Pass { log("to a maximum length of 20 cells, corresponding to the smallest Xilinx 7 Series\n"); log("device.\n"); log("\n"); - log("This pass is a no-op if the scratchpad variable 'xilinx_dsp.multonly' is set\n"); - log("to 1.\n"); - log("\n"); log("\n"); log("Experimental feature: addition/subtractions less than 12 or 24 bits with the\n"); log("'(* use_dsp=\"simd\" *)' attribute attached to the output wire or attached to\n"); @@ -780,52 +592,33 @@ struct XilinxDspPass : public Pass { log("P output implementing the operation \"(P >= )\" will be transformed\n"); log("into using the DSP48E1's pattern detector feature for overflow detection.\n"); log("\n"); - log(" -family {xcup|xcu|xc7|xc6v|xc5v|xc4v|xc6s|xc3sda}\n"); - log(" select the family to target\n"); - log(" default: xc7\n"); - log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing XILINX_DSP pass (pack resources into DSPs).\n"); - std::string family = "xc7"; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if ((args[argidx] == "-family" || args[argidx] == "-arch") && argidx+1 < args.size()) { - family = args[++argidx]; - continue; - } + // if (args[argidx] == "-singleton") { + // singleton_mode = true; + // continue; + // } break; } extra_args(args, argidx, design); - // Don't bother distinguishing between those. - if (family == "xc6v") - family = "xc7"; - if (family == "xcup") - family = "xcu"; - for (auto module : design->selected_modules()) { - - if (design->scratchpad_get_bool("xilinx_dsp.multonly")) - continue; - // Experimental feature: pack $add/$sub cells with // (* use_dsp48="simd" *) into DSP48E1's using its // SIMD feature - if (family == "xc7") - xilinx_simd_pack(module, module->selected_cells()); + xilinx_simd_pack(module, module->selected_cells()); // Match for all features ([ABDMP][12]?REG, pre-adder, // post-adder, pattern detector, etc.) except for CREG - if (family == "xc7") { + { xilinx_dsp_pm pm(module, module->selected_cells()); pm.run_xilinx_dsp_pack(xilinx_dsp_pack); - } else if (family == "xc6s" || family == "xc3sda") { - xilinx_dsp48a_pm pm(module, module->selected_cells()); - pm.run_xilinx_dsp48a_pack(xilinx_dsp48a_pack); } // Separating out CREG packing is necessary since there // is no guarantee that the cell ordering corresponds diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index d40f073c982..5d3b9c2eb1f 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -95,7 +95,7 @@ code sigA sigB sigC sigD sigM clock sigD = port(dsp, \D, SigSpec()); SigSpec P = port(dsp, \P); - if (param(dsp, \USE_MULT).decode_string() == "MULTIPLY") { + if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") { // Only care about those bits that are used int i; for (i = GetSize(P)-1; i >= 0; i--) @@ -144,7 +144,7 @@ endcode match preAdd if sigD.empty() || sigD.is_fully_zero() // Ensure that preAdder not already used - if param(dsp, \USE_DPORT).decode_string() == "FALSE" + if param(dsp, \USE_DPORT, Const("FALSE")).decode_string() == "FALSE" if port(dsp, \INMODE, Const(0, 5)).is_fully_zero() select preAdd->type.in($add) @@ -335,7 +335,7 @@ endcode // recognised in xilinx_dsp.cc). match postAdd // Ensure that Z mux is not already used - if port(dsp, \OPMODE, SigSpec(0, 7)).extract(4,3).is_fully_zero() + if port(dsp, \OPMODE, SigSpec()).extract(4,3).is_fully_zero() select postAdd->type.in($add) select GetSize(port(postAdd, \Y)) <= 48 @@ -424,7 +424,7 @@ endcode // to implement this function match overflow if ffP - if param(dsp, \USE_PATTERN_DETECT).decode_string() == "NO_PATDET" + if param(dsp, \USE_PATTERN_DETECT, Const("NO_PATDET")).decode_string() == "NO_PATDET" select overflow->type.in($ge) select GetSize(port(overflow, \Y)) <= 48 select port(overflow, \B).is_fully_const() @@ -460,7 +460,7 @@ arg argD argQ clock code dff = nullptr; - if (argQ.empty()) + if (GetSize(argQ) == 0) reject; for (const auto &c : argQ.chunks()) { // Abandon matches when 'Q' is a constant diff --git a/passes/pmgen/xilinx_dsp48a.pmg b/passes/pmgen/xilinx_dsp48a.pmg deleted file mode 100644 index 16f5e598ddf..00000000000 --- a/passes/pmgen/xilinx_dsp48a.pmg +++ /dev/null @@ -1,673 +0,0 @@ -// This file describes the main pattern matcher setup (of three total) that -// forms the `xilinx_dsp` pass described in xilinx_dsp.cc - version for -// DSP48A/DSP48A1 (Spartan 3A DSP, Spartan 6). -// At a high level, it works as follows: -// ( 1) Starting from a DSP48A/DSP48A1 cell -// ( 2) Match the driver of the 'B' input to a possible $dff cell (B1REG) -// (attached to at most two $mux cells that implement clock-enable or -// reset functionality, using a subpattern discussed below) -// If B1REG matched, treat 'B' input as input of B1REG -// ( 3) Match the driver of the 'B' and 'D' inputs for a possible $add cell -// (pre-adder) -// ( 4) Match 'B' input for B0REG -// ( 5) Match 'A' input for A1REG -// If A1REG, then match 'A' input for A0REG -// ( 6) Match 'D' input for DREG -// ( 7) Match 'P' output that exclusively drives an MREG -// ( 8) Match 'P' output that exclusively drives one of two inputs to an $add -// cell (post-adder). -// The other input to the adder is assumed to come in from the 'C' input -// (note: 'P' -> 'C' connections that exist for accumulators are -// recognised in xilinx_dsp.cc). -// ( 9) Match 'P' output that exclusively drives a PREG -// (10) If post-adder and PREG both present, match for a $mux cell driving -// the 'C' input, where one of the $mux's inputs is the PREG output. -// This indicates an accumulator situation, and one where a $mux exists -// to override the accumulated value: -// +--------------------------------+ -// | ____ | -// +--| \ | -// |$mux|-+ | -// 'C' ---|____/ | | -// | /-------\ +----+ | -// +----+ +-| post- |___|PREG|---+ 'P' -// |MREG|------ | adder | +----+ -// +----+ \-------/ -// Notes: see the notes in xilinx_dsp.pmg - -pattern xilinx_dsp48a_pack - -state clock -state sigA sigB sigC sigD sigM sigP -state postAddAB postAddMuxAB -state ffAcepol ffBcepol ffDcepol ffMcepol ffPcepol -state ffArstpol ffBrstpol ffDrstpol ffMrstpol ffPrstpol -state ffA0 ffA0cemux ffA0rstmux ffA1 ffA1cemux ffA1rstmux -state ffB0 ffB0cemux ffB0rstmux ffB1 ffB1cemux ffB1rstmux -state ffD ffDcemux ffDrstmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux - -// Variables used for subpatterns -state argQ argD -state ffcepol ffrstpol -state ffoffset -udata dffD dffQ -udata dffclock -udata dff dffcemux dffrstmux -udata dffcepol dffrstpol - -// (1) Starting from a DSP48A/DSP48A1 cell -match dsp - select dsp->type.in(\DSP48A, \DSP48A1) -endmatch - -code sigA sigB sigC sigD sigM clock - auto unextend = [](const SigSpec &sig) { - int i; - for (i = GetSize(sig)-1; i > 0; i--) - if (sig[i] != sig[i-1]) - break; - // Do not remove non-const sign bit - if (sig[i].wire) - ++i; - return sig.extract(0, i); - }; - sigA = unextend(port(dsp, \A)); - sigB = unextend(port(dsp, \B)); - - sigC = port(dsp, \C, SigSpec()); - sigD = port(dsp, \D, SigSpec()); - - SigSpec P = port(dsp, \P); - // Only care about those bits that are used - int i; - for (i = GetSize(P)-1; i >= 0; i--) - if (nusers(P[i]) > 1) - break; - i++; - log_assert(nusers(P.extract_end(i)) <= 1); - // This sigM could have no users if downstream sinks (e.g. $add) is - // narrower than $mul result, for example - if (i == 0) - reject; - sigM = P.extract(0, i); - - clock = port(dsp, \CLK, SigBit()); -endcode - -// (2) Match the driver of the 'B' input to a possible $dff cell (B1REG) -// (attached to at most two $mux cells that implement clock-enable or -// reset functionality, using a subpattern discussed above) -// If matched, treat 'B' input as input of B1REG -code argQ ffB1 ffB1cemux ffB1rstmux ffBcepol ffBrstpol sigB clock - if (param(dsp, \B1REG).as_int() == 0 && param(dsp, \B0REG).as_int() == 0 && port(dsp, \OPMODE, SigSpec()).extract(4, 1).is_fully_zero()) { - argQ = sigB; - subpattern(in_dffe); - if (dff) { - ffB1 = dff; - clock = dffclock; - if (dffrstmux) { - ffB1rstmux = dffrstmux; - ffBrstpol = dffrstpol; - } - if (dffcemux) { - ffB1cemux = dffcemux; - ffBcepol = dffcepol; - } - sigB = dffD; - } - } -endcode - -// (3) Match the driver of the 'B' and 'D' inputs for a possible $add cell -// (pre-adder) -match preAdd - if sigD.empty() || sigD.is_fully_zero() - if param(dsp, \B0REG).as_int() == 0 - // Ensure that preAdder not already used - if port(dsp, \OPMODE, SigSpec()).extract(4, 1).is_fully_zero() - - select preAdd->type.in($add, $sub) - // Output has to be 18 bits or less - select GetSize(port(preAdd, \Y)) <= 18 - select nusers(port(preAdd, \Y)) == 2 - // D port has to be 18 bits or less - select GetSize(port(preAdd, \A)) <= 18 - // B port has to be 18 bits or less - select GetSize(port(preAdd, \B)) <= 18 - index port(preAdd, \Y) === sigB - - optional -endmatch - -code sigB sigD - if (preAdd) { - sigD = port(preAdd, \A); - sigB = port(preAdd, \B); - } -endcode - -// (4) Match 'B' input for B0REG -code argQ ffB0 ffB0cemux ffB0rstmux ffBcepol ffBrstpol sigB clock - if (param(dsp, \B0REG).as_int() == 0) { - argQ = sigB; - subpattern(in_dffe); - if (dff) { - if (ffB1) { - if ((ffB1rstmux != nullptr) ^ (dffrstmux != nullptr)) - goto ffB0_end; - if ((ffB1cemux != nullptr) ^ (dffcemux != nullptr)) - goto ffB0_end; - if (dffrstmux) { - if (ffBrstpol != dffrstpol) - goto ffB0_end; - if (port(ffB1rstmux, \S) != port(dffrstmux, \S)) - goto ffB0_end; - ffB0rstmux = dffrstmux; - } - if (dffcemux) { - if (ffBcepol != dffcepol) - goto ffB0_end; - if (port(ffB1cemux, \S) != port(dffcemux, \S)) - goto ffB0_end; - ffB0cemux = dffcemux; - } - } - ffB0 = dff; - clock = dffclock; - if (dffrstmux) { - ffB0rstmux = dffrstmux; - ffBrstpol = dffrstpol; - } - if (dffcemux) { - ffB0cemux = dffcemux; - ffBcepol = dffcepol; - } - sigB = dffD; - } - } -ffB0_end: -endcode - -// (5) Match 'A' input for A1REG -// If A1REG, then match 'A' input for A0REG -code argQ ffA1 ffA1cemux ffA1rstmux ffAcepol ffArstpol sigA clock ffA0 ffA0cemux ffA0rstmux - if (param(dsp, \A0REG).as_int() == 0 && param(dsp, \A1REG).as_int() == 0) { - argQ = sigA; - subpattern(in_dffe); - if (dff) { - ffA1 = dff; - clock = dffclock; - if (dffrstmux) { - ffA1rstmux = dffrstmux; - ffArstpol = dffrstpol; - } - if (dffcemux) { - ffA1cemux = dffcemux; - ffAcepol = dffcepol; - } - sigA = dffD; - - // Now attempt to match A0 - if (ffA1) { - argQ = sigA; - subpattern(in_dffe); - if (dff) { - if ((ffA1rstmux != nullptr) ^ (dffrstmux != nullptr)) - goto ffA0_end; - if ((ffA1cemux != nullptr) ^ (dffcemux != nullptr)) - goto ffA0_end; - if (dffrstmux) { - if (ffArstpol != dffrstpol) - goto ffA0_end; - if (port(ffA1rstmux, \S) != port(dffrstmux, \S)) - goto ffA0_end; - ffA0rstmux = dffrstmux; - } - if (dffcemux) { - if (ffAcepol != dffcepol) - goto ffA0_end; - if (port(ffA1cemux, \S) != port(dffcemux, \S)) - goto ffA0_end; - ffA0cemux = dffcemux; - } - - ffA0 = dff; - clock = dffclock; - - if (dffcemux) { - ffA0cemux = dffcemux; - ffAcepol = dffcepol; - } - sigA = dffD; - -ffA0_end: ; - } - } - - } - } -endcode - -// (6) Match 'D' input for DREG -code argQ ffD ffDcemux ffDrstmux ffDcepol ffDrstpol sigD clock - if (param(dsp, \DREG).as_int() == 0) { - argQ = sigD; - subpattern(in_dffe); - if (dff) { - ffD = dff; - clock = dffclock; - if (dffrstmux) { - ffDrstmux = dffrstmux; - ffDrstpol = dffrstpol; - } - if (dffcemux) { - ffDcemux = dffcemux; - ffDcepol = dffcepol; - } - sigD = dffD; - } - } -endcode - -// (7) Match 'P' output that exclusively drives an MREG -code argD ffM ffMcemux ffMrstmux ffMcepol ffMrstpol sigM sigP clock - if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) { - argD = sigM; - subpattern(out_dffe); - if (dff) { - ffM = dff; - clock = dffclock; - if (dffrstmux) { - ffMrstmux = dffrstmux; - ffMrstpol = dffrstpol; - } - if (dffcemux) { - ffMcemux = dffcemux; - ffMcepol = dffcepol; - } - sigM = dffQ; - } - } - sigP = sigM; -endcode - -// (8) Match 'P' output that exclusively drives one of two inputs to an $add -// cell (post-adder). -// The other input to the adder is assumed to come in from the 'C' input -// (note: 'P' -> 'C' connections that exist for accumulators are -// recognised in xilinx_dsp.cc). -match postAdd - // Ensure that Z mux is not already used - if port(dsp, \OPMODE, SigSpec()).extract(2,2).is_fully_zero() - - select postAdd->type.in($add) - select GetSize(port(postAdd, \Y)) <= 48 - choice AB {\A, \B} - select nusers(port(postAdd, AB)) <= 3 - filter ffMcemux || nusers(port(postAdd, AB)) == 2 - filter !ffMcemux || nusers(port(postAdd, AB)) == 3 - - index port(postAdd, AB)[0] === sigP[0] - filter GetSize(port(postAdd, AB)) >= GetSize(sigP) - filter port(postAdd, AB).extract(0, GetSize(sigP)) == sigP - // Check that remainder of AB is a sign- or zero-extension - filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(sigP[GetSize(sigP)-1], GetSize(port(postAdd, AB))-GetSize(sigP)) || port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(State::S0, GetSize(port(postAdd, AB))-GetSize(sigP)) - - set postAddAB AB - optional -endmatch - -code sigC sigP - if (postAdd) { - sigC = port(postAdd, postAddAB == \A ? \B : \A); - sigP = port(postAdd, \Y); - } -endcode - -// (9) Match 'P' output that exclusively drives a PREG -code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol sigP clock - if (param(dsp, \PREG).as_int() == 0) { - int users = 2; - // If ffMcemux and no postAdd new-value net must have three users: ffMcemux, ffM and ffPcemux - if (ffMcemux && !postAdd) users++; - if (nusers(sigP) == users) { - argD = sigP; - subpattern(out_dffe); - if (dff) { - ffP = dff; - clock = dffclock; - if (dffrstmux) { - ffPrstmux = dffrstmux; - ffPrstpol = dffrstpol; - } - if (dffcemux) { - ffPcemux = dffcemux; - ffPcepol = dffcepol; - } - sigP = dffQ; - } - } - } -endcode - -// (10) If post-adder and PREG both present, match for a $mux cell driving -// the 'C' input, where one of the $mux's inputs is the PREG output. -// This indicates an accumulator situation, and one where a $mux exists -// to override the accumulated value: -// +--------------------------------+ -// | ____ | -// +--| \ | -// |$mux|-+ | -// 'C' ---|____/ | | -// | /-------\ +----+ | -// +----+ +-| post- |___|PREG|---+ 'P' -// |MREG|------ | adder | +----+ -// +----+ \-------/ -match postAddMux - if postAdd - if ffP - select postAddMux->type.in($mux) - select nusers(port(postAddMux, \Y)) == 2 - choice AB {\A, \B} - index port(postAddMux, AB) === sigP - index port(postAddMux, \Y) === sigC - set postAddMuxAB AB - optional -endmatch - -code sigC - if (postAddMux) - sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); -endcode - -code - accept; -endcode - -// ####################### - -// Subpattern for matching against input registers, based on knowledge of the -// 'Q' input. Typically, identifying registers with clock-enable and reset -// capability would be a task would be handled by other Yosys passes such as -// dff2dffe, but since DSP inference happens much before this, these patterns -// have to be manually identified. -// At a high level: -// (1) Starting from a $dff cell that (partially or fully) drives the given -// 'Q' argument -// (2) Match for a $mux cell implementing synchronous reset semantics --- -// one that exclusively drives the 'D' input of the $dff, with one of its -// $mux inputs being fully zero -// (3) Match for a $mux cell implement clock enable semantics --- one that -// exclusively drives the 'D' input of the $dff (or the other input of -// the reset $mux) and where one of this $mux's inputs is connected to -// the 'Q' output of the $dff -subpattern in_dffe -arg argD argQ clock - -code - dff = nullptr; - if (GetSize(argQ) == 0) - reject; - for (const auto &c : argQ.chunks()) { - // Abandon matches when 'Q' is a constant - if (!c.wire) - reject; - // Abandon matches when 'Q' has the keep attribute set - if (c.wire->get_bool_attribute(\keep)) - reject; - // Abandon matches when 'Q' has a non-zero init attribute set - // (not supported by DSP48E1) - Const init = c.wire->attributes.at(\init, Const()); - if (!init.empty()) - for (auto b : init.extract(c.offset, c.width)) - if (b != State::Sx && b != State::S0) - reject; - } -endcode - -// (1) Starting from a $dff cell that (partially or fully) drives the given -// 'Q' argument -match ff - select ff->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ff, \CLK_POLARITY).as_bool() - - slice offset GetSize(port(ff, \D)) - index port(ff, \Q)[offset] === argQ[0] - - // Check that the rest of argQ is present - filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ) - filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ - - filter clock == SigBit() || port(ff, \CLK) == clock - - set ffoffset offset -endmatch - -code argQ argD - SigSpec Q = port(ff, \Q); - dff = ff; - dffclock = port(ff, \CLK); - dffD = argQ; - argD = port(ff, \D); - argQ = Q; - dffD.replace(argQ, argD); - // Only search for ffrstmux if dffD only - // has two (ff, ffrstmux) users - if (nusers(dffD) > 2) - argD = SigSpec(); -endcode - -// (2) Match for a $mux cell implementing synchronous reset semantics --- -// exclusively drives the 'D' input of the $dff, with one of the $mux -// inputs being fully zero -match ffrstmux - if !argD.empty() - select ffrstmux->type.in($mux) - index port(ffrstmux, \Y) === argD - - choice BA {\B, \A} - // DSP48E1 only supports reset to zero - select port(ffrstmux, BA).is_fully_zero() - - define pol (BA == \B) - set ffrstpol pol - semioptional -endmatch - -code argD - if (ffrstmux) { - dffrstmux = ffrstmux; - dffrstpol = ffrstpol; - argD = port(ffrstmux, ffrstpol ? \A : \B); - dffD.replace(port(ffrstmux, \Y), argD); - - // Only search for ffcemux if argQ has at - // least 3 users (ff, , ffrstmux) and - // dffD only has two (ff, ffrstmux) - if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) - argD = SigSpec(); - } - else - dffrstmux = nullptr; -endcode - -// (3) Match for a $mux cell implement clock enable semantics --- one that -// exclusively drives the 'D' input of the $dff (or the other input of -// the reset $mux) and where one of this $mux's inputs is connected to -// the 'Q' output of the $dff -match ffcemux - if !argD.empty() - select ffcemux->type.in($mux) - index port(ffcemux, \Y) === argD - choice AB {\A, \B} - index port(ffcemux, AB) === argQ - define pol (AB == \A) - set ffcepol pol - semioptional -endmatch - -code argD - if (ffcemux) { - dffcemux = ffcemux; - dffcepol = ffcepol; - argD = port(ffcemux, ffcepol ? \B : \A); - dffD.replace(port(ffcemux, \Y), argD); - } - else - dffcemux = nullptr; -endcode - -// ####################### - -// Subpattern for matching against output registers, based on knowledge of the -// 'D' input. -// At a high level: -// (1) Starting from an optional $mux cell that implements clock enable -// semantics --- one where the given 'D' argument (partially or fully) -// drives one of its two inputs -// (2) Starting from, or continuing onto, another optional $mux cell that -// implements synchronous reset semantics --- one where the given 'D' -// argument (or the clock enable $mux output) drives one of its two inputs -// and where the other input is fully zero -// (3) Match for a $dff cell (whose 'D' input is the 'D' argument, or the -// output of the previous clock enable or reset $mux cells) -subpattern out_dffe -arg argD argQ clock - -code - dff = nullptr; - for (auto c : argD.chunks()) - // Abandon matches when 'D' has the keep attribute set - if (c.wire->get_bool_attribute(\keep)) - reject; -endcode - -// (1) Starting from an optional $mux cell that implements clock enable -// semantics --- one where the given 'D' argument (partially or fully) -// drives one of its two inputs -match ffcemux - select ffcemux->type.in($mux) - // ffcemux output must have two users: ffcemux and ff.D - select nusers(port(ffcemux, \Y)) == 2 - - choice AB {\A, \B} - // keep-last-value net must have at least three users: ffcemux, ff, downstream sink(s) - select nusers(port(ffcemux, AB)) >= 3 - - slice offset GetSize(port(ffcemux, \Y)) - define BA (AB == \A ? \B : \A) - index port(ffcemux, BA)[offset] === argD[0] - - // Check that the rest of argD is present - filter GetSize(port(ffcemux, BA)) >= offset + GetSize(argD) - filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD - - set ffoffset offset - define pol (AB == \A) - set ffcepol pol - - semioptional -endmatch - -code argD argQ - dffcemux = ffcemux; - if (ffcemux) { - SigSpec BA = port(ffcemux, ffcepol ? \B : \A); - SigSpec Y = port(ffcemux, \Y); - argQ = argD; - argD.replace(BA, Y); - argQ.replace(BA, port(ffcemux, ffcepol ? \A : \B)); - - dffcemux = ffcemux; - dffcepol = ffcepol; - } -endcode - -// (2) Starting from, or continuing onto, another optional $mux cell that -// implements synchronous reset semantics --- one where the given 'D' -// argument (or the clock enable $mux output) drives one of its two inputs -// and where the other input is fully zero -match ffrstmux - select ffrstmux->type.in($mux) - // ffrstmux output must have two users: ffrstmux and ff.D - select nusers(port(ffrstmux, \Y)) == 2 - - choice BA {\B, \A} - // DSP48E1 only supports reset to zero - select port(ffrstmux, BA).is_fully_zero() - - slice offset GetSize(port(ffrstmux, \Y)) - define AB (BA == \B ? \A : \B) - index port(ffrstmux, AB)[offset] === argD[0] - - // Check that offset is consistent - filter !ffcemux || ffoffset == offset - // Check that the rest of argD is present - filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD) - filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD - - set ffoffset offset - define pol (AB == \A) - set ffrstpol pol - - semioptional -endmatch - -code argD argQ - dffrstmux = ffrstmux; - if (ffrstmux) { - SigSpec AB = port(ffrstmux, ffrstpol ? \A : \B); - SigSpec Y = port(ffrstmux, \Y); - argD.replace(AB, Y); - - dffrstmux = ffrstmux; - dffrstpol = ffrstpol; - } -endcode - -// (3) Match for a $dff cell (whose 'D' input is the 'D' argument, or the -// output of the previous clock enable or reset $mux cells) -match ff - select ff->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ff, \CLK_POLARITY).as_bool() - - slice offset GetSize(port(ff, \D)) - index port(ff, \D)[offset] === argD[0] - - // Check that offset is consistent - filter (!ffcemux && !ffrstmux) || ffoffset == offset - // Check that the rest of argD is present - filter GetSize(port(ff, \D)) >= offset + GetSize(argD) - filter port(ff, \D).extract(offset, GetSize(argD)) == argD - // Check that FF.Q is connected to CE-mux - filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ - - filter clock == SigBit() || port(ff, \CLK) == clock - - set ffoffset offset -endmatch - -code argQ - SigSpec D = port(ff, \D); - SigSpec Q = port(ff, \Q); - if (!ffcemux) { - argQ = argD; - argQ.replace(D, Q); - } - - // Abandon matches when 'Q' has a non-zero init attribute set - // (not supported by DSP48E1) - for (auto c : argQ.chunks()) { - Const init = c.wire->attributes.at(\init, Const()); - if (!init.empty()) - for (auto b : init.extract(c.offset, c.width)) - if (b != State::Sx && b != State::S0) - reject; - } - - dff = ff; - dffQ = argQ; - dffclock = port(ff, \CLK); -endcode diff --git a/passes/pmgen/xilinx_dsp_CREG.pmg b/passes/pmgen/xilinx_dsp_CREG.pmg index 42d4d1b9b5d..5cd34162e2b 100644 --- a/passes/pmgen/xilinx_dsp_CREG.pmg +++ b/passes/pmgen/xilinx_dsp_CREG.pmg @@ -1,7 +1,7 @@ // This file describes the second of three pattern matcher setups that // forms the `xilinx_dsp` pass described in xilinx_dsp.cc // At a high level, it works as follows: -// (1) Starting from a DSP48* cell that (a) doesn't have a CREG already, +// (1) Starting from a DSP48E1 cell that (a) doesn't have a CREG already, // and (b) uses the 'C' port // (2) Match the driver of the 'C' input to a possible $dff cell (CREG) // (attached to at most two $mux cells that implement clock-enable or @@ -38,11 +38,11 @@ udata dffclock udata dff dffcemux dffrstmux udata dffcepol dffrstpol -// (1) Starting from a DSP48* cell that (a) doesn't have a CREG already, +// (1) Starting from a DSP48E1 cell that (a) doesn't have a CREG already, // and (b) uses the 'C' port match dsp - select dsp->type.in(\DSP48A, \DSP48A1, \DSP48E1) - select param(dsp, \CREG).as_int() == 0 + select dsp->type.in(\DSP48E1) + select param(dsp, \CREG, 1).as_int() == 0 select nusers(port(dsp, \C, SigSpec())) > 1 endmatch @@ -60,8 +60,7 @@ code sigC sigP clock sigC = unextend(port(dsp, \C, SigSpec())); SigSpec P = port(dsp, \P); - if (!dsp->type.in(\DSP48E1) || - param(dsp, \USE_MULT).decode_string() == "MULTIPLY") { + if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") { // Only care about those bits that are used int i; for (i = GetSize(P)-1; i >= 0; i--) diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg index 8babb88e6a9..7a32df2b7d2 100644 --- a/passes/pmgen/xilinx_dsp_cascade.pmg +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -62,11 +62,12 @@ code #define MAX_DSP_CASCADE 20 endcode -// (1) Starting from a DSP48* cell that (a) has the Z multiplexer -// (controlled by OPMODE[3:2] for DSP48A*, by OPMODE[6:4] for DSP48E1) -// set to zero and (b) doesn't already use the 'PCOUT' port +// (1) Starting from a DSP48E1 cell that (a) has the Z multiplexer +// (controlled by OPMODE[6:4]) set to zero and (b) doesn't already +// use the 'PCOUT' port match first - select (first->type.in(\DSP48A, \DSP48A1) && port(first, \OPMODE, Const(0, 8)).extract(2,2) == Const::from_string("00")) || (first->type.in(\DSP48E1) && port(first, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("000")) + select first->type.in(\DSP48E1) + select port(first, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("000") select nusers(port(first, \PCOUT, SigSpec())) <= 1 endmatch @@ -99,21 +100,14 @@ finally add_siguser(cascade, dsp); SigSpec opmode = port(dsp_pcin, \OPMODE, Const(0, 7)); - if (dsp->type.in(\DSP48A, \DSP48A1)) { - log_assert(P == 0); - opmode[3] = State::S0; - opmode[2] = State::S1; - } - else if (dsp->type.in(\DSP48E1)) { - if (P == 17) - opmode[6] = State::S1; - else if (P == 0) - opmode[6] = State::S0; - else log_abort(); - - opmode[5] = State::S0; - opmode[4] = State::S1; - } + if (P == 17) + opmode[6] = State::S1; + else if (P == 0) + opmode[6] = State::S0; + else log_abort(); + + opmode[5] = State::S0; + opmode[4] = State::S1; dsp_pcin->setPort(\OPMODE, opmode); log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); @@ -126,42 +120,21 @@ finally add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); - if (dsp->type.in(\DSP48E1)) - dsp->setParam(ID(ACASCREG), AREG); + dsp->setParam(ID(ACASCREG), AREG); dsp_pcin->setParam(ID(A_INPUT), Const("CASCADE")); log_debug("ACOUT -> ACIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); } if (BREG >= 0) { Wire *cascade = module->addWire(NEW_ID, 18); - if (dsp->type.in(\DSP48A, \DSP48A1)) { - // According to UG389 p9 [https://www.xilinx.com/support/documentation/user_guides/ug389.pdf] - // "The DSP48A1 component uses this input when cascading - // BCOUT from an adjacent DSP48A1 slice. The tools then - // translate BCOUT cascading to the dedicated BCIN input - // and set the B_INPUT attribute for implementation." - dsp_pcin->setPort(ID(B), cascade); - } - else { - dsp_pcin->setPort(ID(B), Const(0, 18)); - dsp_pcin->setPort(ID(BCIN), cascade); - } + dsp_pcin->setPort(ID(B), Const(0, 18)); + dsp_pcin->setPort(ID(BCIN), cascade); dsp->setPort(ID(BCOUT), cascade); add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); - if (dsp->type.in(\DSP48E1)) { - dsp->setParam(ID(BCASCREG), BREG); - // According to UG389 p13 [https://www.xilinx.com/support/documentation/user_guides/ug389.pdf] - // "The attribute is only used by place and route tools and - // is not necessary for the users to set for synthesis. The - // attribute is determined by the connection to the B port - // of the DSP48A1 slice. If the B port is connected to the - // BCOUT of another DSP48A1 slice, then the tools automatically - // set the attribute to 'CASCADE', otherwise it is set to - // 'DIRECT'". - dsp_pcin->setParam(ID(B_INPUT), Const("CASCADE")); - } + dsp->setParam(ID(BCASCREG), BREG); + dsp_pcin->setParam(ID(B_INPUT), Const("CASCADE")); log_debug("BCOUT -> BCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); } @@ -183,25 +156,26 @@ subpattern tail arg first arg next -// (2.1) Match another DSP48* cell that (a) does not have the CREG enabled, +// (2.1) Match another DSP48E1 cell that (a) does not have the CREG enabled, // (b) has its Z multiplexer output set to the 'C' port, which is // driven by the 'P' output of the previous DSP cell, and (c) has its // 'PCIN' port unused match nextP - select !nextP->type.in(\DSP48E1) || !param(nextP, \CREG).as_bool() - select (nextP->type.in(\DSP48A, \DSP48A1) && port(nextP, \OPMODE, Const(0, 8)).extract(2,2) == Const::from_string("11")) || (nextP->type.in(\DSP48E1) && port(nextP, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011")) + select nextP->type.in(\DSP48E1) + select !param(nextP, \CREG, State::S1).as_bool() + select port(nextP, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") select nusers(port(nextP, \C, SigSpec())) > 1 select nusers(port(nextP, \PCIN, SigSpec())) == 0 index port(nextP, \C)[0] === port(std::get<0>(chain.back()), \P)[0] semioptional endmatch -// (2.2) For DSP48E1 only, same as (2.1) but with the 'C' port driven -// by the 'P' output of the previous DSP cell right-shifted by 17 bits +// (2.2) Same as (2.1) but with the 'C' port driven by the 'P' output of the +// previous DSP cell right-shifted by 17 bits match nextP_shift17 if !nextP select nextP_shift17->type.in(\DSP48E1) - select !param(nextP_shift17, \CREG).as_bool() + select !param(nextP_shift17, \CREG, State::S1).as_bool() select port(nextP_shift17, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") select nusers(port(nextP_shift17, \C, SigSpec())) > 1 select nusers(port(nextP_shift17, \PCIN, SigSpec())) == 0 @@ -214,8 +188,6 @@ code next if (!nextP) next = nextP_shift17; if (next) { - if (next->type != first->type) - reject; unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) @@ -230,50 +202,38 @@ code next endcode // (3) For this subequent DSP48E1 match (i.e. PCOUT -> PCIN cascade exists) -// if (a) this DSP48E1 does not already have an ACOUT -> ACIN cascade, -// (b) the previous DSP does not already use its ACOUT port, then -// examine if an ACOUT -> ACIN cascade opportunity exists if -// (i) A ports are identical, or (ii) separated by a -// $dff-with-optional-clock-enable-or-reset and checking that the 'D' input -// of this register is the same as the 'A' input of the previous DSP -// TODO: Check for two levels of flops, instead of just one +// if (a) the previous DSP48E1 uses either the A2REG or A1REG, (b) this +// DSP48 does not use A2REG nor A1REG, (c) this DSP48E1 does not already +// have an ACOUT -> ACIN cascade, (d) the previous DSP does not already +// use its ACOUT port, then examine if an ACOUT -> ACIN cascade +// opportunity exists by matching for a $dff-with-optional-clock-enable- +// or-reset and checking that the 'D' input of this register is the same +// as the 'A' input of the previous DSP code argQ clock AREG AREG = -1; - if (next && next->type.in(\DSP48E1)) { + if (next) { Cell *prev = std::get<0>(chain.back()); - - if (param(next, \A_INPUT).decode_string() == "DIRECT" && - port(next, \ACIN, SigSpec()).is_fully_zero() && + if (param(prev, \AREG, 2).as_int() > 0 && + param(next, \AREG, 2).as_int() > 0 && + param(next, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && nusers(port(prev, \ACOUT, SigSpec())) <= 1) { - if (param(prev, \AREG) == 0) { - if (port(prev, \A) == port(next, \A)) - AREG = 0; - } - else { - argQ = unextend(port(next, \A)); - clock = port(prev, \CLK); - subpattern(in_dffe); - if (dff) { - if (!dffrstmux && port(prev, \RSTA, State::S0) != State::S0) - goto reject_AREG; - if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTA, State::S0)) - goto reject_AREG; - IdString CEA; - if (param(prev, \AREG) == 1) - CEA = \CEA2; - else if (param(prev, \AREG) == 2) - CEA = \CEA1; - else log_abort(); - if (!dffcemux && port(prev, CEA, State::S0) != State::S1) - goto reject_AREG; - if (dffcemux && port(dffcemux, \S) != port(prev, CEA, State::S0)) - goto reject_AREG; - if (dffD == unextend(port(prev, \A))) - AREG = 1; - } + argQ = unextend(port(next, \A)); + clock = port(prev, \CLK); + subpattern(in_dffe); + if (dff) { + if (!dffrstmux && port(prev, \RSTA, State::S0) != State::S0) + goto reject_AREG; + if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTA, State::S0)) + goto reject_AREG; + if (!dffcemux && port(prev, \CEA2, State::S0) != State::S0) + goto reject_AREG; + if (dffcemux && port(dffcemux, \S) != port(prev, \CEA2, State::S0)) + goto reject_AREG; + if (dffD == unextend(port(prev, \A))) + AREG = 1; +reject_AREG: ; } } -reject_AREG: ; } endcode @@ -282,47 +242,28 @@ code argQ clock BREG BREG = -1; if (next) { Cell *prev = std::get<0>(chain.back()); - if ((next->type != \DSP48E1 || param(next, \B_INPUT).decode_string() == "DIRECT") && + if (param(prev, \BREG, 2).as_int() > 0 && + param(next, \BREG, 2).as_int() > 0 && + param(next, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && port(next, \BCIN, SigSpec()).is_fully_zero() && nusers(port(prev, \BCOUT, SigSpec())) <= 1) { - if ((next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG) == 0 && param(prev, \B1REG) == 0) || - (next->type.in(\DSP48E1) && param(prev, \BREG) == 0)) { - if (port(prev, \B) == port(next, \B)) - BREG = 0; - } - else { - argQ = unextend(port(next, \B)); - clock = port(prev, \CLK); - subpattern(in_dffe); - if (dff) { - if (!dffrstmux && port(prev, \RSTB, State::S0) != State::S0) - goto reject_BREG; - if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTB, State::S0)) - goto reject_BREG; - IdString CEB; - if (next->type.in(\DSP48A, \DSP48A1)) - CEB = \CEB; - else if (next->type.in(\DSP48E1)) { - if (param(prev, \BREG) == 1) - CEB = \CEB2; - else if (param(prev, \BREG) == 2) - CEB = \CEB1; - else log_abort(); - } - else log_abort(); - if (!dffcemux && port(prev, CEB, State::S0) != State::S1) - goto reject_BREG; - if (dffcemux && port(dffcemux, \S) != port(prev, CEB, State::S0)) - goto reject_BREG; - if (dffD == unextend(port(prev, \B))) { - if (next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG) != 0) - goto reject_BREG; - BREG = 1; - } - } + argQ = unextend(port(next, \B)); + clock = port(prev, \CLK); + subpattern(in_dffe); + if (dff) { + if (!dffrstmux && port(prev, \RSTB, State::S0) != State::S0) + goto reject_BREG; + if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTB, State::S0)) + goto reject_BREG; + if (!dffcemux && port(prev, \CEB2, State::S0) != State::S0) + goto reject_BREG; + if (dffcemux && port(dffcemux, \S) != port(prev, \CEB2, State::S0)) + goto reject_BREG; + if (dffD == unextend(port(prev, \B))) + BREG = 1; +reject_BREG: ; } } -reject_BREG: ; } endcode diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 1410850c749..3d264e8d4e0 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -36,9 +36,9 @@ void run_fixed(xilinx_srl_pm &pm) for (auto cell : ud.longest_chain) { log_debug(" %s\n", log_id(cell)); if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) { - SigBit Q = cell->getPort(ID::Q); + SigBit Q = cell->getPort(ID(Q)); log_assert(Q.wire); - auto it = Q.wire->attributes.find(ID::init); + auto it = Q.wire->attributes.find(ID(init)); if (it != Q.wire->attributes.end()) { auto &i = it->second[Q.offset]; initval.append(i); @@ -48,7 +48,7 @@ void run_fixed(xilinx_srl_pm &pm) initval.append(State::Sx); } else if (cell->type.in(ID(FDRE), ID(FDRE_1))) { - if (cell->getParam(ID::INIT).as_bool()) + if (cell->parameters.at(ID(INIT), State::S0).as_bool()) initval.append(State::S1); else initval.append(State::S0); @@ -64,14 +64,14 @@ void run_fixed(xilinx_srl_pm &pm) pm.module->swap_names(c, first_cell); if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID(FDRE), ID(FDRE_1))) { - c->setParam(ID::DEPTH, GetSize(ud.longest_chain)); - c->setParam(ID::INIT, initval.as_const()); + c->setParam(ID(DEPTH), GetSize(ud.longest_chain)); + c->setParam(ID(INIT), initval.as_const()); if (first_cell->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) c->setParam(ID(CLKPOL), 1); - else if (first_cell->type.in(ID($_DFF_N_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1))) + else if (first_cell->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1))) c->setParam(ID(CLKPOL), 0); else if (first_cell->type.in(ID(FDRE))) { - if (!first_cell->getParam(ID(IS_C_INVERTED)).as_bool()) + if (!first_cell->parameters.at(ID(IS_C_INVERTED), State::S0).as_bool()) c->setParam(ID(CLKPOL), 1); else c->setParam(ID(CLKPOL), 0); @@ -85,16 +85,16 @@ void run_fixed(xilinx_srl_pm &pm) else c->setParam(ID(ENPOL), 2); - c->setPort(ID::C, first_cell->getPort(ID::C)); - c->setPort(ID::D, first_cell->getPort(ID::D)); - c->setPort(ID::Q, last_cell->getPort(ID::Q)); - c->setPort(ID::L, GetSize(ud.longest_chain)-1); + c->setPort(ID(C), first_cell->getPort(ID(C))); + c->setPort(ID(D), first_cell->getPort(ID(D))); + c->setPort(ID(Q), last_cell->getPort(ID(Q))); + c->setPort(ID(L), GetSize(ud.longest_chain)-1); if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - c->setPort(ID::E, State::S1); + c->setPort(ID(E), State::S1); else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - c->setPort(ID::E, first_cell->getPort(ID::E)); + c->setPort(ID(E), first_cell->getPort(ID(E))); else if (first_cell->type.in(ID(FDRE), ID(FDRE_1))) - c->setPort(ID::E, first_cell->getPort(ID(CE))); + c->setPort(ID(E), first_cell->getPort(ID(CE))); else log_abort(); } @@ -117,9 +117,9 @@ void run_variable(xilinx_srl_pm &pm) auto slice = i.second; log_debug(" %s\n", log_id(cell)); if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { - SigBit Q = cell->getPort(ID::Q)[slice]; + SigBit Q = cell->getPort(ID(Q))[slice]; log_assert(Q.wire); - auto it = Q.wire->attributes.find(ID::init); + auto it = Q.wire->attributes.find(ID(init)); if (it != Q.wire->attributes.end()) { auto &i = it->second[Q.offset]; initval.append(i); @@ -140,15 +140,15 @@ void run_variable(xilinx_srl_pm &pm) pm.module->swap_names(c, first_cell); if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { - c->setParam(ID::DEPTH, GetSize(ud.chain)); - c->setParam(ID::INIT, initval.as_const()); + c->setParam(ID(DEPTH), GetSize(ud.chain)); + c->setParam(ID(INIT), initval.as_const()); Const clkpol, enpol; if (first_cell->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) clkpol = 1; - else if (first_cell->type.in(ID($_DFF_N_), ID($_DFFE_NN_), ID($_DFFE_NP_))) + else if (first_cell->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_))) clkpol = 0; else if (first_cell->type.in(ID($dff), ID($dffe))) - clkpol = first_cell->getParam(ID::CLK_POLARITY); + clkpol = first_cell->getParam(ID(CLK_POLARITY)); else log_abort(); if (first_cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) @@ -156,27 +156,27 @@ void run_variable(xilinx_srl_pm &pm) else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) enpol = 0; else if (first_cell->type.in(ID($dffe))) - enpol = first_cell->getParam(ID::EN_POLARITY); + enpol = first_cell->getParam(ID(EN_POLARITY)); else enpol = 2; c->setParam(ID(CLKPOL), clkpol); c->setParam(ID(ENPOL), enpol); if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - c->setPort(ID::C, first_cell->getPort(ID::C)); + c->setPort(ID(C), first_cell->getPort(ID(C))); else if (first_cell->type.in(ID($dff), ID($dffe))) - c->setPort(ID::C, first_cell->getPort(ID::CLK)); + c->setPort(ID(C), first_cell->getPort(ID(CLK))); else log_abort(); - c->setPort(ID::D, first_cell->getPort(ID::D)[first_slice]); - c->setPort(ID::Q, st.shiftx->getPort(ID::Y)); - c->setPort(ID::L, st.shiftx->getPort(ID::B)); + c->setPort(ID(D), first_cell->getPort(ID(D))[first_slice]); + c->setPort(ID(Q), st.shiftx->getPort(ID(Y))); + c->setPort(ID(L), st.shiftx->getPort(ID(B))); if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($dff))) - c->setPort(ID::E, State::S1); + c->setPort(ID(E), State::S1); else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - c->setPort(ID::E, first_cell->getPort(ID::E)); + c->setPort(ID(E), first_cell->getPort(ID(E))); else if (first_cell->type.in(ID($dffe))) - c->setPort(ID::E, first_cell->getPort(ID::EN)); + c->setPort(ID(E), first_cell->getPort(ID(EN))); else log_abort(); } @@ -188,7 +188,7 @@ void run_variable(xilinx_srl_pm &pm) struct XilinxSrlPass : public Pass { XilinxSrlPass() : Pass("xilinx_srl", "Xilinx shift register extraction") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -212,7 +212,7 @@ struct XilinxSrlPass : public Pass { log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing XILINX_SRL pass (Xilinx shift register extraction).\n"); diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 80f0a27c29b..535b3dfdcca 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -13,8 +13,8 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() - select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED).as_bool() - select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED).as_bool() + select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED, State::S0).as_bool() select !first->type.in(\FDRE, \FDRE_1) || port(first, \R, State::S0).is_fully_zero() filter !non_first_cells.count(first) generate @@ -84,8 +84,8 @@ arg en_port match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() - select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED).as_bool() - select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED).as_bool() + select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED, State::S0).as_bool() select !first->type.in(\FDRE, \FDRE_1) || port(first, \R, State::S0).is_fully_zero() endmatch @@ -111,9 +111,9 @@ match next index port(next, \Q) === port(first, \D) filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) - filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool() - filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool() - filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED, State::S0).as_bool() == param(first, \IS_C_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED, State::S0).as_bool() == param(first, \IS_D_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED, State::S0).as_bool() == param(first, \IS_R_INVERTED, State::S0).as_bool() filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R, State::S0).is_fully_zero() endmatch @@ -138,9 +138,9 @@ match next index port(next, \Q) === port(chain.back(), \D) filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) - filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool() - filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool() - filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED, State::S0).as_bool() == param(first, \IS_C_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED, State::S0).as_bool() == param(first, \IS_D_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED, State::S0).as_bool() == param(first, \IS_R_INVERTED, State::S0).as_bool() filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R, State::S0).is_fully_zero() generate Cell *cell = module->addCell(NEW_ID, chain.back()->type); diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc index f20a167b447..a5b4a3112c1 100644 --- a/passes/proc/proc.cc +++ b/passes/proc/proc.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct ProcPass : public Pass { ProcPass() : Pass("proc", "translate processes to netlists") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -58,7 +58,7 @@ struct ProcPass : public Pass { log(" executed in -ifx mode.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string global_arst; bool ifxmode = false; diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index 16db461b258..c606deb8880 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -39,45 +39,45 @@ bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSpec ref, for (auto cell : mod->cells()) { - if (cell->type == ID($reduce_or) && cell->getPort(ID::Y) == signal) - return check_signal(mod, cell->getPort(ID::A), ref, polarity); + if (cell->type == "$reduce_or" && cell->getPort("\\Y") == signal) + return check_signal(mod, cell->getPort("\\A"), ref, polarity); - if (cell->type == ID($reduce_bool) && cell->getPort(ID::Y) == signal) - return check_signal(mod, cell->getPort(ID::A), ref, polarity); + if (cell->type == "$reduce_bool" && cell->getPort("\\Y") == signal) + return check_signal(mod, cell->getPort("\\A"), ref, polarity); - if (cell->type == ID($logic_not) && cell->getPort(ID::Y) == signal) { + if (cell->type == "$logic_not" && cell->getPort("\\Y") == signal) { polarity = !polarity; - return check_signal(mod, cell->getPort(ID::A), ref, polarity); + return check_signal(mod, cell->getPort("\\A"), ref, polarity); } - if (cell->type == ID($not) && cell->getPort(ID::Y) == signal) { + if (cell->type == "$not" && cell->getPort("\\Y") == signal) { polarity = !polarity; - return check_signal(mod, cell->getPort(ID::A), ref, polarity); + return check_signal(mod, cell->getPort("\\A"), ref, polarity); } - if (cell->type.in(ID($eq), ID($eqx)) && cell->getPort(ID::Y) == signal) { - if (cell->getPort(ID::A).is_fully_const()) { - if (!cell->getPort(ID::A).as_bool()) + if (cell->type.in("$eq", "$eqx") && cell->getPort("\\Y") == signal) { + if (cell->getPort("\\A").is_fully_const()) { + if (!cell->getPort("\\A").as_bool()) polarity = !polarity; - return check_signal(mod, cell->getPort(ID::B), ref, polarity); + return check_signal(mod, cell->getPort("\\B"), ref, polarity); } - if (cell->getPort(ID::B).is_fully_const()) { - if (!cell->getPort(ID::B).as_bool()) + if (cell->getPort("\\B").is_fully_const()) { + if (!cell->getPort("\\B").as_bool()) polarity = !polarity; - return check_signal(mod, cell->getPort(ID::A), ref, polarity); + return check_signal(mod, cell->getPort("\\A"), ref, polarity); } } - if (cell->type.in(ID($ne), ID($nex)) && cell->getPort(ID::Y) == signal) { - if (cell->getPort(ID::A).is_fully_const()) { - if (cell->getPort(ID::A).as_bool()) + if (cell->type.in("$ne", "$nex") && cell->getPort("\\Y") == signal) { + if (cell->getPort("\\A").is_fully_const()) { + if (cell->getPort("\\A").as_bool()) polarity = !polarity; - return check_signal(mod, cell->getPort(ID::B), ref, polarity); + return check_signal(mod, cell->getPort("\\B"), ref, polarity); } - if (cell->getPort(ID::B).is_fully_const()) { - if (cell->getPort(ID::B).as_bool()) + if (cell->getPort("\\B").is_fully_const()) { + if (cell->getPort("\\B").as_bool()) polarity = !polarity; - return check_signal(mod, cell->getPort(ID::A), ref, polarity); + return check_signal(mod, cell->getPort("\\A"), ref, polarity); } } } @@ -203,7 +203,7 @@ void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map) struct ProcArstPass : public Pass { ProcArstPass() : Pass("proc_arst", "detect asynchronous resets") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -221,7 +221,7 @@ struct ProcArstPass : public Pass { log(" in the 'init' attribute on the net.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string global_arst; bool global_arst_neg = false; @@ -261,8 +261,8 @@ struct ProcArstPass : public Pass { for (auto &act : sync->actions) { RTLIL::SigSpec arst_sig, arst_val; for (auto &chunk : act.first.chunks()) - if (chunk.wire && chunk.wire->attributes.count(ID::init)) { - RTLIL::SigSpec value = chunk.wire->attributes.at(ID::init); + if (chunk.wire && chunk.wire->attributes.count("\\init")) { + RTLIL::SigSpec value = chunk.wire->attributes.at("\\init"); value.extend_u0(chunk.wire->width, false); arst_sig.append(chunk); arst_val.append(value.extract(chunk.offset, chunk.width)); @@ -285,7 +285,7 @@ struct ProcArstPass : public Pass { } for (auto wire : delete_initattr_wires) - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); } } ProcArstPass; diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 5e78b7316dc..114c6ab0393 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -166,7 +166,7 @@ void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count, bool struct ProcCleanPass : public Pass { ProcCleanPass() : Pass("proc_clean", "remove empty parts of processes") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -179,7 +179,7 @@ struct ProcCleanPass : public Pass { log("if it contains only empty structures.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { int total_count = 0; bool quiet = false; diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc index e320a72a678..519d35cd6b4 100644 --- a/passes/proc/proc_dff.cc +++ b/passes/proc/proc_dff.cc @@ -75,69 +75,69 @@ void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::SigSpec log_abort(); if (sync_low_signals.size() > 1) { - RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($reduce_or)); - cell->parameters[ID::A_SIGNED] = RTLIL::Const(0); - cell->parameters[ID::A_WIDTH] = RTLIL::Const(sync_low_signals.size()); - cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); - cell->setPort(ID::A, sync_low_signals); - cell->setPort(ID::Y, sync_low_signals = mod->addWire(NEW_ID)); + RTLIL::Cell *cell = mod->addCell(NEW_ID, "$reduce_or"); + cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); + cell->parameters["\\A_WIDTH"] = RTLIL::Const(sync_low_signals.size()); + cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); + cell->setPort("\\A", sync_low_signals); + cell->setPort("\\Y", sync_low_signals = mod->addWire(NEW_ID)); } if (sync_low_signals.size() > 0) { - RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($not)); - cell->parameters[ID::A_SIGNED] = RTLIL::Const(0); - cell->parameters[ID::A_WIDTH] = RTLIL::Const(sync_low_signals.size()); - cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); - cell->setPort(ID::A, sync_low_signals); - cell->setPort(ID::Y, mod->addWire(NEW_ID)); - sync_high_signals.append(cell->getPort(ID::Y)); + RTLIL::Cell *cell = mod->addCell(NEW_ID, "$not"); + cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); + cell->parameters["\\A_WIDTH"] = RTLIL::Const(sync_low_signals.size()); + cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); + cell->setPort("\\A", sync_low_signals); + cell->setPort("\\Y", mod->addWire(NEW_ID)); + sync_high_signals.append(cell->getPort("\\Y")); } if (sync_high_signals.size() > 1) { - RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($reduce_or)); - cell->parameters[ID::A_SIGNED] = RTLIL::Const(0); - cell->parameters[ID::A_WIDTH] = RTLIL::Const(sync_high_signals.size()); - cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); - cell->setPort(ID::A, sync_high_signals); - cell->setPort(ID::Y, sync_high_signals = mod->addWire(NEW_ID)); + RTLIL::Cell *cell = mod->addCell(NEW_ID, "$reduce_or"); + cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); + cell->parameters["\\A_WIDTH"] = RTLIL::Const(sync_high_signals.size()); + cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); + cell->setPort("\\A", sync_high_signals); + cell->setPort("\\Y", sync_high_signals = mod->addWire(NEW_ID)); } - RTLIL::Cell *inv_cell = mod->addCell(NEW_ID, ID($not)); - inv_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0); - inv_cell->parameters[ID::A_WIDTH] = RTLIL::Const(sig_d.size()); - inv_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(sig_d.size()); - inv_cell->setPort(ID::A, sync_value); - inv_cell->setPort(ID::Y, sync_value_inv = mod->addWire(NEW_ID, sig_d.size())); - - RTLIL::Cell *mux_set_cell = mod->addCell(NEW_ID, ID($mux)); - mux_set_cell->parameters[ID::WIDTH] = RTLIL::Const(sig_d.size()); - mux_set_cell->setPort(ID::A, sig_sr_set); - mux_set_cell->setPort(ID::B, sync_value); - mux_set_cell->setPort(ID::S, sync_high_signals); - mux_set_cell->setPort(ID::Y, sig_sr_set = mod->addWire(NEW_ID, sig_d.size())); - - RTLIL::Cell *mux_clr_cell = mod->addCell(NEW_ID, ID($mux)); - mux_clr_cell->parameters[ID::WIDTH] = RTLIL::Const(sig_d.size()); - mux_clr_cell->setPort(ID::A, sig_sr_clr); - mux_clr_cell->setPort(ID::B, sync_value_inv); - mux_clr_cell->setPort(ID::S, sync_high_signals); - mux_clr_cell->setPort(ID::Y, sig_sr_clr = mod->addWire(NEW_ID, sig_d.size())); + RTLIL::Cell *inv_cell = mod->addCell(NEW_ID, "$not"); + inv_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); + inv_cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig_d.size()); + inv_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(sig_d.size()); + inv_cell->setPort("\\A", sync_value); + inv_cell->setPort("\\Y", sync_value_inv = mod->addWire(NEW_ID, sig_d.size())); + + RTLIL::Cell *mux_set_cell = mod->addCell(NEW_ID, "$mux"); + mux_set_cell->parameters["\\WIDTH"] = RTLIL::Const(sig_d.size()); + mux_set_cell->setPort("\\A", sig_sr_set); + mux_set_cell->setPort("\\B", sync_value); + mux_set_cell->setPort("\\S", sync_high_signals); + mux_set_cell->setPort("\\Y", sig_sr_set = mod->addWire(NEW_ID, sig_d.size())); + + RTLIL::Cell *mux_clr_cell = mod->addCell(NEW_ID, "$mux"); + mux_clr_cell->parameters["\\WIDTH"] = RTLIL::Const(sig_d.size()); + mux_clr_cell->setPort("\\A", sig_sr_clr); + mux_clr_cell->setPort("\\B", sync_value_inv); + mux_clr_cell->setPort("\\S", sync_high_signals); + mux_clr_cell->setPort("\\Y", sig_sr_clr = mod->addWire(NEW_ID, sig_d.size())); } std::stringstream sstr; sstr << "$procdff$" << (autoidx++); - RTLIL::Cell *cell = mod->addCell(sstr.str(), ID($dffsr)); + RTLIL::Cell *cell = mod->addCell(sstr.str(), "$dffsr"); cell->attributes = proc->attributes; - cell->parameters[ID::WIDTH] = RTLIL::Const(sig_d.size()); - cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity, 1); - cell->parameters[ID::SET_POLARITY] = RTLIL::Const(true, 1); - cell->parameters[ID::CLR_POLARITY] = RTLIL::Const(true, 1); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->setPort(ID::CLK, clk); - cell->setPort(ID::SET, sig_sr_set); - cell->setPort(ID::CLR, sig_sr_clr); + cell->parameters["\\WIDTH"] = RTLIL::Const(sig_d.size()); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity, 1); + cell->parameters["\\SET_POLARITY"] = RTLIL::Const(true, 1); + cell->parameters["\\CLR_POLARITY"] = RTLIL::Const(true, 1); + cell->setPort("\\D", sig_d); + cell->setPort("\\Q", sig_q); + cell->setPort("\\CLK", clk); + cell->setPort("\\SET", sig_sr_set); + cell->setPort("\\CLR", sig_sr_clr); log(" created %s cell `%s' with %s edge clock and multiple level-sensitive resets.\n", cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative"); @@ -153,38 +153,38 @@ void gen_dffsr(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec sig_set RTLIL::SigSpec sig_sr_set = mod->addWire(NEW_ID, sig_in.size()); RTLIL::SigSpec sig_sr_clr = mod->addWire(NEW_ID, sig_in.size()); - RTLIL::Cell *inv_set = mod->addCell(NEW_ID, ID($not)); - inv_set->parameters[ID::A_SIGNED] = RTLIL::Const(0); - inv_set->parameters[ID::A_WIDTH] = RTLIL::Const(sig_in.size()); - inv_set->parameters[ID::Y_WIDTH] = RTLIL::Const(sig_in.size()); - inv_set->setPort(ID::A, sig_set); - inv_set->setPort(ID::Y, sig_set_inv); - - RTLIL::Cell *mux_sr_set = mod->addCell(NEW_ID, ID($mux)); - mux_sr_set->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size()); - mux_sr_set->setPort(set_polarity ? ID::A : ID::B, RTLIL::Const(0, sig_in.size())); - mux_sr_set->setPort(set_polarity ? ID::B : ID::A, sig_set); - mux_sr_set->setPort(ID::Y, sig_sr_set); - mux_sr_set->setPort(ID::S, set); - - RTLIL::Cell *mux_sr_clr = mod->addCell(NEW_ID, ID($mux)); - mux_sr_clr->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size()); - mux_sr_clr->setPort(set_polarity ? ID::A : ID::B, RTLIL::Const(0, sig_in.size())); - mux_sr_clr->setPort(set_polarity ? ID::B : ID::A, sig_set_inv); - mux_sr_clr->setPort(ID::Y, sig_sr_clr); - mux_sr_clr->setPort(ID::S, set); - - RTLIL::Cell *cell = mod->addCell(sstr.str(), ID($dffsr)); + RTLIL::Cell *inv_set = mod->addCell(NEW_ID, "$not"); + inv_set->parameters["\\A_SIGNED"] = RTLIL::Const(0); + inv_set->parameters["\\A_WIDTH"] = RTLIL::Const(sig_in.size()); + inv_set->parameters["\\Y_WIDTH"] = RTLIL::Const(sig_in.size()); + inv_set->setPort("\\A", sig_set); + inv_set->setPort("\\Y", sig_set_inv); + + RTLIL::Cell *mux_sr_set = mod->addCell(NEW_ID, "$mux"); + mux_sr_set->parameters["\\WIDTH"] = RTLIL::Const(sig_in.size()); + mux_sr_set->setPort(set_polarity ? "\\A" : "\\B", RTLIL::Const(0, sig_in.size())); + mux_sr_set->setPort(set_polarity ? "\\B" : "\\A", sig_set); + mux_sr_set->setPort("\\Y", sig_sr_set); + mux_sr_set->setPort("\\S", set); + + RTLIL::Cell *mux_sr_clr = mod->addCell(NEW_ID, "$mux"); + mux_sr_clr->parameters["\\WIDTH"] = RTLIL::Const(sig_in.size()); + mux_sr_clr->setPort(set_polarity ? "\\A" : "\\B", RTLIL::Const(0, sig_in.size())); + mux_sr_clr->setPort(set_polarity ? "\\B" : "\\A", sig_set_inv); + mux_sr_clr->setPort("\\Y", sig_sr_clr); + mux_sr_clr->setPort("\\S", set); + + RTLIL::Cell *cell = mod->addCell(sstr.str(), "$dffsr"); cell->attributes = proc->attributes; - cell->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size()); - cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity, 1); - cell->parameters[ID::SET_POLARITY] = RTLIL::Const(true, 1); - cell->parameters[ID::CLR_POLARITY] = RTLIL::Const(true, 1); - cell->setPort(ID::D, sig_in); - cell->setPort(ID::Q, sig_out); - cell->setPort(ID::CLK, clk); - cell->setPort(ID::SET, sig_sr_set); - cell->setPort(ID::CLR, sig_sr_clr); + cell->parameters["\\WIDTH"] = RTLIL::Const(sig_in.size()); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity, 1); + cell->parameters["\\SET_POLARITY"] = RTLIL::Const(true, 1); + cell->parameters["\\CLR_POLARITY"] = RTLIL::Const(true, 1); + cell->setPort("\\D", sig_in); + cell->setPort("\\Q", sig_out); + cell->setPort("\\CLK", clk); + cell->setPort("\\SET", sig_sr_set); + cell->setPort("\\CLR", sig_sr_clr); log(" created %s cell `%s' with %s edge clock and %s level non-const reset.\n", cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative", set_polarity ? "positive" : "negative"); @@ -196,24 +196,24 @@ void gen_dff(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::Const val_rst, RT std::stringstream sstr; sstr << "$procdff$" << (autoidx++); - RTLIL::Cell *cell = mod->addCell(sstr.str(), clk.empty() ? ID($ff) : arst ? ID($adff) : ID($dff)); + RTLIL::Cell *cell = mod->addCell(sstr.str(), clk.empty() ? "$ff" : arst ? "$adff" : "$dff"); cell->attributes = proc->attributes; - cell->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size()); + cell->parameters["\\WIDTH"] = RTLIL::Const(sig_in.size()); if (arst) { - cell->parameters[ID::ARST_POLARITY] = RTLIL::Const(arst_polarity, 1); - cell->parameters[ID::ARST_VALUE] = val_rst; + cell->parameters["\\ARST_POLARITY"] = RTLIL::Const(arst_polarity, 1); + cell->parameters["\\ARST_VALUE"] = val_rst; } if (!clk.empty()) { - cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity, 1); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity, 1); } - cell->setPort(ID::D, sig_in); - cell->setPort(ID::Q, sig_out); + cell->setPort("\\D", sig_in); + cell->setPort("\\Q", sig_out); if (arst) - cell->setPort(ID::ARST, *arst); + cell->setPort("\\ARST", *arst); if (!clk.empty()) - cell->setPort(ID::CLK, clk); + cell->setPort("\\CLK", clk); if (!clk.empty()) log(" created %s cell `%s' with %s edge clock", cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative"); @@ -303,15 +303,15 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce) } log_assert(inputs.size() == compare.size()); - RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($ne)); - cell->parameters[ID::A_SIGNED] = RTLIL::Const(false, 1); - cell->parameters[ID::B_SIGNED] = RTLIL::Const(false, 1); - cell->parameters[ID::A_WIDTH] = RTLIL::Const(inputs.size()); - cell->parameters[ID::B_WIDTH] = RTLIL::Const(inputs.size()); - cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); - cell->setPort(ID::A, inputs); - cell->setPort(ID::B, compare); - cell->setPort(ID::Y, sync_level->signal); + RTLIL::Cell *cell = mod->addCell(NEW_ID, "$ne"); + cell->parameters["\\A_SIGNED"] = RTLIL::Const(false, 1); + cell->parameters["\\B_SIGNED"] = RTLIL::Const(false, 1); + cell->parameters["\\A_WIDTH"] = RTLIL::Const(inputs.size()); + cell->parameters["\\B_WIDTH"] = RTLIL::Const(inputs.size()); + cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); + cell->setPort("\\A", inputs); + cell->setPort("\\B", compare); + cell->setPort("\\Y", sync_level->signal); many_async_rules.clear(); } @@ -370,7 +370,7 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce) struct ProcDffPass : public Pass { ProcDffPass() : Pass("proc_dff", "extract flip-flops from processes") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -380,7 +380,7 @@ struct ProcDffPass : public Pass { log("d-type flip-flop cells.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing PROC_DFF pass (convert process syncs to FFs).\n"); diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc index e7c8a80ddce..a0c8351b6d3 100644 --- a/passes/proc/proc_dlatch.cc +++ b/passes/proc/proc_dlatch.cc @@ -42,16 +42,16 @@ struct proc_dlatch_db_t { for (auto cell : module->cells()) { - if (cell->type.in(ID($mux), ID($pmux))) + if (cell->type.in("$mux", "$pmux")) { - auto sig_y = sigmap(cell->getPort(ID::Y)); + auto sig_y = sigmap(cell->getPort("\\Y")); for (int i = 0; i < GetSize(sig_y); i++) mux_drivers[sig_y[i]] = pair(cell, i); pool mux_srcbits_pool; - for (auto bit : sigmap(cell->getPort(ID::A))) + for (auto bit : sigmap(cell->getPort("\\A"))) mux_srcbits_pool.insert(bit); - for (auto bit : sigmap(cell->getPort(ID::B))) + for (auto bit : sigmap(cell->getPort("\\B"))) mux_srcbits_pool.insert(bit); vector mux_srcbits_vec; @@ -180,9 +180,9 @@ struct proc_dlatch_db_t Cell *cell = it->second.first; int index = it->second.second; - SigSpec sig_a = sigmap(cell->getPort(ID::A)); - SigSpec sig_b = sigmap(cell->getPort(ID::B)); - SigSpec sig_s = sigmap(cell->getPort(ID::S)); + SigSpec sig_a = sigmap(cell->getPort("\\A")); + SigSpec sig_b = sigmap(cell->getPort("\\B")); + SigSpec sig_s = sigmap(cell->getPort("\\S")); int width = GetSize(sig_a); pool children; @@ -190,9 +190,9 @@ struct proc_dlatch_db_t int n = find_mux_feedback(sig_a[index], needle, set_undef); if (n != false_node) { if (set_undef && sig_a[index] == needle) { - SigSpec sig = cell->getPort(ID::A); + SigSpec sig = cell->getPort("\\A"); sig[index] = State::Sx; - cell->setPort(ID::A, sig); + cell->setPort("\\A", sig); } for (int i = 0; i < GetSize(sig_s); i++) n = make_inner(sig_s[i], State::S0, n); @@ -203,9 +203,9 @@ struct proc_dlatch_db_t n = find_mux_feedback(sig_b[i*width + index], needle, set_undef); if (n != false_node) { if (set_undef && sig_b[i*width + index] == needle) { - SigSpec sig = cell->getPort(ID::B); + SigSpec sig = cell->getPort("\\B"); sig[i*width + index] = State::Sx; - cell->setPort(ID::B, sig); + cell->setPort("\\B", sig); } children.insert(make_inner(sig_s[i], State::S1, n)); } @@ -257,9 +257,9 @@ struct proc_dlatch_db_t void fixup_mux(Cell *cell) { - SigSpec sig_a = cell->getPort(ID::A); - SigSpec sig_b = cell->getPort(ID::B); - SigSpec sig_s = cell->getPort(ID::S); + SigSpec sig_a = cell->getPort("\\A"); + SigSpec sig_b = cell->getPort("\\B"); + SigSpec sig_s = cell->getPort("\\S"); SigSpec sig_any_valid_b; SigSpec sig_new_b, sig_new_s; @@ -278,18 +278,18 @@ struct proc_dlatch_db_t } if (sig_a.is_fully_undef() && !sig_any_valid_b.empty()) - cell->setPort(ID::A, sig_any_valid_b); + cell->setPort("\\A", sig_any_valid_b); if (GetSize(sig_new_s) == 1) { - cell->type = ID($mux); - cell->unsetParam(ID::S_WIDTH); + cell->type = "$mux"; + cell->unsetParam("\\S_WIDTH"); } else { - cell->type = ID($pmux); - cell->setParam(ID::S_WIDTH, GetSize(sig_new_s)); + cell->type = "$pmux"; + cell->setParam("\\S_WIDTH", GetSize(sig_new_s)); } - cell->setPort(ID::B, sig_new_b); - cell->setPort(ID::S, sig_new_s); + cell->setPort("\\B", sig_new_b); + cell->setPort("\\S", sig_new_s); } void fixup_muxes() @@ -317,7 +317,7 @@ struct proc_dlatch_db_t pool next_queue; for (auto cell : queue) { - if (cell->type.in(ID($mux), ID($pmux))) + if (cell->type.in("$mux", "$pmux")) fixup_mux(cell); for (auto bit : upstream_cell2net[cell]) for (auto cell : upstream_net2cell[bit]) @@ -349,7 +349,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) continue; } - if (proc->get_bool_attribute(ID::always_ff)) + if (proc->get_bool_attribute(ID(always_ff))) log_error("Found non edge/level sensitive event in always_ff process `%s.%s'.\n", db.module->name.c_str(), proc->name.c_str()); @@ -387,7 +387,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) int offset = 0; for (auto chunk : nolatches_bits.first.chunks()) { SigSpec lhs = chunk, rhs = nolatches_bits.second.extract(offset, chunk.width); - if (proc->get_bool_attribute(ID::always_latch)) + if (proc->get_bool_attribute(ID(always_latch))) log_error("No latch inferred for signal `%s.%s' from always_latch process `%s.%s'.\n", db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str()); else @@ -418,7 +418,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) cell->set_src_attribute(src); db.generated_dlatches.insert(cell); - if (proc->get_bool_attribute(ID::always_comb)) + if (proc->get_bool_attribute(ID(always_comb))) log_error("Latch inferred for signal `%s.%s' from always_comb process `%s.%s'.\n", db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str()); else @@ -434,7 +434,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) struct ProcDlatchPass : public Pass { ProcDlatchPass() : Pass("proc_dlatch", "extract latches from processes") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -444,7 +444,7 @@ struct ProcDlatchPass : public Pass { log("d-type latches.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing PROC_DLATCH pass (convert process syncs to latches).\n"); diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index eb323038d1d..462a384b73b 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.cc @@ -54,7 +54,7 @@ void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc) log_cmd_error("Non-const initialization value: %s = %s\n", log_signal(lhs_c), log_signal(valuesig)); Const value = valuesig.as_const(); - Const &wireinit = lhs_c.wire->attributes[ID::init]; + Const &wireinit = lhs_c.wire->attributes["\\init"]; while (GetSize(wireinit.bits) < lhs_c.wire->width) wireinit.bits.push_back(State::Sx); @@ -86,7 +86,7 @@ void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc) struct ProcInitPass : public Pass { ProcInitPass() : Pass("proc_init", "convert initial block to init attributes") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -97,7 +97,7 @@ struct ProcInitPass : public Pass { log("respective wire.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing PROC_INIT pass (extract init attributes).\n"); diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index d20f345343b..d029282fd49 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -147,7 +147,7 @@ struct SnippetSwCache void apply_attrs(RTLIL::Cell *cell, const RTLIL::SwitchRule *sw, const RTLIL::CaseRule *cs) { cell->attributes = sw->attributes; - cell->add_strpool_attribute(ID::src, cs->get_strpool_attribute(ID::src)); + cell->add_strpool_attribute("\\src", cs->get_strpool_attribute("\\src")); } RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode) @@ -178,19 +178,19 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s else { // create compare cell - RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str().c_str(), cmp_wire->width), ifxmode ? ID($eqx) : ID($eq)); + RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str().c_str(), cmp_wire->width), ifxmode ? "$eqx" : "$eq"); apply_attrs(eq_cell, sw, cs); - eq_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0); - eq_cell->parameters[ID::B_SIGNED] = RTLIL::Const(0); + eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); + eq_cell->parameters["\\B_SIGNED"] = RTLIL::Const(0); - eq_cell->parameters[ID::A_WIDTH] = RTLIL::Const(sig.size()); - eq_cell->parameters[ID::B_WIDTH] = RTLIL::Const(comp.size()); - eq_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); + eq_cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig.size()); + eq_cell->parameters["\\B_WIDTH"] = RTLIL::Const(comp.size()); + eq_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); - eq_cell->setPort(ID::A, sig); - eq_cell->setPort(ID::B, comp); - eq_cell->setPort(ID::Y, RTLIL::SigSpec(cmp_wire, cmp_wire->width++)); + eq_cell->setPort("\\A", sig); + eq_cell->setPort("\\B", comp); + eq_cell->setPort("\\Y", RTLIL::SigSpec(cmp_wire, cmp_wire->width++)); } } @@ -204,15 +204,15 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s ctrl_wire = mod->addWire(sstr.str() + "_CTRL"); // reduce cmp vector to one logic signal - RTLIL::Cell *any_cell = mod->addCell(sstr.str() + "_ANY", ID($reduce_or)); + RTLIL::Cell *any_cell = mod->addCell(sstr.str() + "_ANY", "$reduce_or"); apply_attrs(any_cell, sw, cs); - any_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0); - any_cell->parameters[ID::A_WIDTH] = RTLIL::Const(cmp_wire->width); - any_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1); + any_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); + any_cell->parameters["\\A_WIDTH"] = RTLIL::Const(cmp_wire->width); + any_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); - any_cell->setPort(ID::A, cmp_wire); - any_cell->setPort(ID::Y, RTLIL::SigSpec(ctrl_wire)); + any_cell->setPort("\\A", cmp_wire); + any_cell->setPort("\\Y", RTLIL::SigSpec(ctrl_wire)); } return RTLIL::SigSpec(ctrl_wire); @@ -239,14 +239,14 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s RTLIL::Wire *result_wire = mod->addWire(sstr.str() + "_Y", when_signal.size()); // create the multiplexer itself - RTLIL::Cell *mux_cell = mod->addCell(sstr.str(), ID($mux)); + RTLIL::Cell *mux_cell = mod->addCell(sstr.str(), "$mux"); apply_attrs(mux_cell, sw, cs); - mux_cell->parameters[ID::WIDTH] = RTLIL::Const(when_signal.size()); - mux_cell->setPort(ID::A, else_signal); - mux_cell->setPort(ID::B, when_signal); - mux_cell->setPort(ID::S, ctrl_sig); - mux_cell->setPort(ID::Y, RTLIL::SigSpec(result_wire)); + mux_cell->parameters["\\WIDTH"] = RTLIL::Const(when_signal.size()); + mux_cell->setPort("\\A", else_signal); + mux_cell->setPort("\\B", when_signal); + mux_cell->setPort("\\S", ctrl_sig); + mux_cell->setPort("\\Y", RTLIL::SigSpec(result_wire)); last_mux_cell = mux_cell; return RTLIL::SigSpec(result_wire); @@ -255,24 +255,24 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode) { log_assert(last_mux_cell != NULL); - log_assert(when_signal.size() == last_mux_cell->getPort(ID::A).size()); + log_assert(when_signal.size() == last_mux_cell->getPort("\\A").size()); - if (when_signal == last_mux_cell->getPort(ID::A)) + if (when_signal == last_mux_cell->getPort("\\A")) return; RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, cs, ifxmode); log_assert(ctrl_sig.size() == 1); - last_mux_cell->type = ID($pmux); + last_mux_cell->type = "$pmux"; - RTLIL::SigSpec new_s = last_mux_cell->getPort(ID::S); + RTLIL::SigSpec new_s = last_mux_cell->getPort("\\S"); new_s.append(ctrl_sig); - last_mux_cell->setPort(ID::S, new_s); + last_mux_cell->setPort("\\S", new_s); - RTLIL::SigSpec new_b = last_mux_cell->getPort(ID::B); + RTLIL::SigSpec new_b = last_mux_cell->getPort("\\B"); new_b.append(when_signal); - last_mux_cell->setPort(ID::B, new_b); + last_mux_cell->setPort("\\B", new_b); - last_mux_cell->parameters[ID::S_WIDTH] = last_mux_cell->getPort(ID::S).size(); + last_mux_cell->parameters["\\S_WIDTH"] = last_mux_cell->getPort("\\S").size(); } const pool &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRule *sw) @@ -281,7 +281,7 @@ const pool &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRul { pool bits; - if (sw->get_bool_attribute(ID::full_case)) + if (sw->get_bool_attribute("\\full_case")) { bool first_case = true; @@ -337,7 +337,7 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d std::vector pgroups(sw->cases.size()); bool is_simple_parallel_case = true; - if (!sw->get_bool_attribute(ID::parallel_case)) { + if (!sw->get_bool_attribute("\\parallel_case")) { if (!swpara.count(sw)) { pool case_values; for (size_t i = 0; i < sw->cases.size(); i++) { @@ -438,7 +438,7 @@ void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc, bool ifxmode) struct ProcMuxPass : public Pass { ProcMuxPass() : Pass("proc_mux", "convert decision trees to multiplexers") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -452,7 +452,7 @@ struct ProcMuxPass : public Pass { log(" 'case' expressions and 'if' conditions.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ifxmode = false; log_header(design, "Executing PROC_MUX pass (convert decision trees to multiplexers).\n"); diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc index bd122b91fff..d4aee9df02d 100644 --- a/passes/proc/proc_prune.cc +++ b/passes/proc/proc_prune.cc @@ -38,7 +38,7 @@ struct PruneWorker pool do_switch(RTLIL::SwitchRule *sw, pool assigned, pool &affected) { pool all_assigned; - bool full_case = sw->get_bool_attribute(ID::full_case); + bool full_case = sw->get_bool_attribute("\\full_case"); bool first = true; for (auto it : sw->cases) { if (it->compare.empty()) @@ -93,7 +93,7 @@ struct PruneWorker for (int i = 0; i < GetSize(lhs); i++) { RTLIL::SigBit lhs_bit = lhs[i]; if (lhs_bit.wire && !assigned[lhs_bit]) { - conn.first.append(lhs_bit); + conn.first.append_bit(lhs_bit); conn.second.append(rhs.extract(i)); } } @@ -125,7 +125,7 @@ struct PruneWorker struct ProcPrunePass : public Pass { ProcPrunePass() : Pass("proc_prune", "remove redundant assignments") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -135,7 +135,7 @@ struct ProcPrunePass : public Pass { log("a later assignment to the same signal and removes them.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { int total_removed_count = 0, total_promoted_count = 0; log_header(design, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n"); diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc index ee91637ca2a..4f40be44682 100644 --- a/passes/proc/proc_rmdead.cc +++ b/passes/proc/proc_rmdead.cc @@ -62,15 +62,15 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter) pool.take_all(); } - if (pool.empty() && !sw->get_bool_attribute(ID::full_case)) { - sw->set_bool_attribute(ID::full_case); + if (pool.empty() && !sw->get_bool_attribute("\\full_case")) { + sw->set_bool_attribute("\\full_case"); full_case_counter++; } } struct ProcRmdeadPass : public Pass { ProcRmdeadPass() : Pass("proc_rmdead", "eliminate dead trees in decision trees") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -79,7 +79,7 @@ struct ProcRmdeadPass : public Pass { log("This pass identifies unreachable branches in decision trees and removes them.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing PROC_RMDEAD pass (remove dead branches from decision trees).\n"); diff --git a/passes/sat/Makefile.inc b/passes/sat/Makefile.inc index 7118c156342..fc3ac879ecb 100644 --- a/passes/sat/Makefile.inc +++ b/passes/sat/Makefile.inc @@ -12,7 +12,4 @@ OBJS += passes/sat/supercover.o OBJS += passes/sat/fmcombine.o OBJS += passes/sat/mutate.o OBJS += passes/sat/cutpoint.o -OBJS += passes/sat/fminit.o -ifeq ($(DISABLE_SPAWN),0) -OBJS += passes/sat/qbfsat.o -endif + diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc index e9a10465ea6..3b432c461a8 100644 --- a/passes/sat/assertpmux.cc +++ b/passes/sat/assertpmux.cc @@ -52,14 +52,14 @@ struct AssertpmuxWorker for (auto cell : module->cells()) { - if (cell->type.in(ID($mux), ID($pmux))) + if (cell->type.in("$mux", "$pmux")) { - int width = cell->getParam(ID::WIDTH).as_int(); - int numports = cell->type == ID($mux) ? 2 : cell->getParam(ID::S_WIDTH).as_int() + 1; + int width = cell->getParam("\\WIDTH").as_int(); + int numports = cell->type == "$mux" ? 2 : cell->getParam("\\S_WIDTH").as_int() + 1; - SigSpec sig_a = sigmap(cell->getPort(ID::A)); - SigSpec sig_b = sigmap(cell->getPort(ID::B)); - SigSpec sig_s = sigmap(cell->getPort(ID::S)); + SigSpec sig_a = sigmap(cell->getPort("\\A")); + SigSpec sig_b = sigmap(cell->getPort("\\B")); + SigSpec sig_s = sigmap(cell->getPort("\\S")); for (int i = 0; i < numports; i++) { SigSpec bits = i == 0 ? sig_a : sig_b.extract(width*(i-1), width); @@ -98,12 +98,12 @@ struct AssertpmuxWorker if (muxport_actsignal.count(muxport) == 0) { if (portidx == 0) - muxport_actsignal[muxport] = module->LogicNot(NEW_ID, cell->getPort(ID::S)); + muxport_actsignal[muxport] = module->LogicNot(NEW_ID, cell->getPort("\\S")); else - muxport_actsignal[muxport] = cell->getPort(ID::S)[portidx-1]; + muxport_actsignal[muxport] = cell->getPort("\\S")[portidx-1]; } - output.append(module->LogicAnd(NEW_ID, muxport_actsignal.at(muxport), get_bit_activation(cell->getPort(ID::Y)[bitidx]))); + output.append(module->LogicAnd(NEW_ID, muxport_actsignal.at(muxport), get_bit_activation(cell->getPort("\\Y")[bitidx]))); } output.sort_and_unify(); @@ -148,10 +148,10 @@ struct AssertpmuxWorker { log("Adding assert for $pmux cell %s.%s.\n", log_id(module), log_id(pmux)); - int swidth = pmux->getParam(ID::S_WIDTH).as_int(); + int swidth = pmux->getParam("\\S_WIDTH").as_int(); int cntbits = ceil_log2(swidth+1); - SigSpec sel = pmux->getPort(ID::S); + SigSpec sel = pmux->getPort("\\S"); SigSpec cnt(State::S0, cntbits); for (int i = 0; i < swidth; i++) @@ -164,7 +164,7 @@ struct AssertpmuxWorker assert_en.append(module->LogicNot(NEW_ID, module->Initstate(NEW_ID))); if (!flag_always) - assert_en.append(get_activation(pmux->getPort(ID::Y))); + assert_en.append(get_activation(pmux->getPort("\\Y"))); if (GetSize(assert_en) == 0) assert_en = State::S1; @@ -174,14 +174,14 @@ struct AssertpmuxWorker Cell *assert_cell = module->addAssert(NEW_ID, assert_a, assert_en); - if (pmux->attributes.count(ID::src) != 0) - assert_cell->attributes[ID::src] = pmux->attributes.at(ID::src); + if (pmux->attributes.count("\\src") != 0) + assert_cell->attributes["\\src"] = pmux->attributes.at("\\src"); } }; struct AssertpmuxPass : public Pass { AssertpmuxPass() : Pass("assertpmux", "adds asserts for parallel muxes") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -199,7 +199,7 @@ struct AssertpmuxPass : public Pass { log(" additional constraint and check the $pmux condition always.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_noinit = false; bool flag_always = false; @@ -227,7 +227,7 @@ struct AssertpmuxPass : public Pass { vector pmux_cells; for (auto cell : module->selected_cells()) - if (cell->type == ID($pmux)) + if (cell->type == "$pmux") pmux_cells.push_back(cell); for (auto cell : pmux_cells) diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc index 6fc4809253f..7402485453e 100644 --- a/passes/sat/async2sync.cc +++ b/passes/sat/async2sync.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct Async2syncPass : public Pass { Async2syncPass() : Pass("async2sync", "convert async FF inputs to sync circuits") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -42,7 +42,7 @@ struct Async2syncPass : public Pass { log("Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { // bool flag_noinit = false; @@ -66,9 +66,9 @@ struct Async2syncPass : public Pass { pool del_initbits; for (auto wire : module->wires()) - if (wire->attributes.count(ID::init) > 0) + if (wire->attributes.count("\\init") > 0) { - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); SigSpec initsig = sigmap(wire); for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++) @@ -78,16 +78,16 @@ struct Async2syncPass : public Pass { for (auto cell : vector(module->selected_cells())) { - if (cell->type.in(ID($adff))) + if (cell->type.in("$adff")) { - // bool clk_pol = cell->parameters[ID::CLK_POLARITY].as_bool(); - bool arst_pol = cell->parameters[ID::ARST_POLARITY].as_bool(); - Const arst_val = cell->parameters[ID::ARST_VALUE]; + // bool clk_pol = cell->parameters["\\CLK_POLARITY"].as_bool(); + bool arst_pol = cell->parameters["\\ARST_POLARITY"].as_bool(); + Const arst_val = cell->parameters["\\ARST_VALUE"]; - // SigSpec sig_clk = cell->getPort(ID::CLK); - SigSpec sig_arst = cell->getPort(ID::ARST); - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); + // SigSpec sig_clk = cell->getPort("\\CLK"); + SigSpec sig_arst = cell->getPort("\\ARST"); + SigSpec sig_d = cell->getPort("\\D"); + SigSpec sig_q = cell->getPort("\\Q"); log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n", log_id(module), log_id(cell), log_id(cell->type), @@ -102,7 +102,7 @@ struct Async2syncPass : public Pass { Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d)); Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q)); - new_q->attributes[ID::init] = init_val; + new_q->attributes["\\init"] = init_val; if (arst_pol) { module->addMux(NEW_ID, sig_d, arst_val, sig_arst, new_d); @@ -112,26 +112,26 @@ struct Async2syncPass : public Pass { module->addMux(NEW_ID, arst_val, new_q, sig_arst, sig_q); } - cell->setPort(ID::D, new_d); - cell->setPort(ID::Q, new_q); - cell->unsetPort(ID::ARST); - cell->unsetParam(ID::ARST_POLARITY); - cell->unsetParam(ID::ARST_VALUE); - cell->type = ID($dff); + cell->setPort("\\D", new_d); + cell->setPort("\\Q", new_q); + cell->unsetPort("\\ARST"); + cell->unsetParam("\\ARST_POLARITY"); + cell->unsetParam("\\ARST_VALUE"); + cell->type = "$dff"; continue; } - if (cell->type.in(ID($dffsr))) + if (cell->type.in("$dffsr")) { - // bool clk_pol = cell->parameters[ID::CLK_POLARITY].as_bool(); - bool set_pol = cell->parameters[ID::SET_POLARITY].as_bool(); - bool clr_pol = cell->parameters[ID::CLR_POLARITY].as_bool(); + // bool clk_pol = cell->parameters["\\CLK_POLARITY"].as_bool(); + bool set_pol = cell->parameters["\\SET_POLARITY"].as_bool(); + bool clr_pol = cell->parameters["\\CLR_POLARITY"].as_bool(); - // SigSpec sig_clk = cell->getPort(ID::CLK); - SigSpec sig_set = cell->getPort(ID::SET); - SigSpec sig_clr = cell->getPort(ID::CLR); - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); + // SigSpec sig_clk = cell->getPort("\\CLK"); + SigSpec sig_set = cell->getPort("\\SET"); + SigSpec sig_clr = cell->getPort("\\CLR"); + SigSpec sig_d = cell->getPort("\\D"); + SigSpec sig_q = cell->getPort("\\Q"); log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n", log_id(module), log_id(cell), log_id(cell->type), @@ -146,7 +146,7 @@ struct Async2syncPass : public Pass { Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d)); Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q)); - new_q->attributes[ID::init] = init_val; + new_q->attributes["\\init"] = init_val; if (!set_pol) sig_set = module->Not(NEW_ID, sig_set); @@ -160,23 +160,23 @@ struct Async2syncPass : public Pass { tmp = module->Or(NEW_ID, new_q, sig_set); module->addAnd(NEW_ID, tmp, sig_clr, sig_q); - cell->setPort(ID::D, new_d); - cell->setPort(ID::Q, new_q); - cell->unsetPort(ID::SET); - cell->unsetPort(ID::CLR); - cell->unsetParam(ID::SET_POLARITY); - cell->unsetParam(ID::CLR_POLARITY); - cell->type = ID($dff); + cell->setPort("\\D", new_d); + cell->setPort("\\Q", new_q); + cell->unsetPort("\\SET"); + cell->unsetPort("\\CLR"); + cell->unsetParam("\\SET_POLARITY"); + cell->unsetParam("\\CLR_POLARITY"); + cell->type = "$dff"; continue; } - if (cell->type.in(ID($dlatch))) + if (cell->type.in("$dlatch")) { - bool en_pol = cell->parameters[ID::EN_POLARITY].as_bool(); + bool en_pol = cell->parameters["\\EN_POLARITY"].as_bool(); - SigSpec sig_en = cell->getPort(ID::EN); - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); + SigSpec sig_en = cell->getPort("\\EN"); + SigSpec sig_d = cell->getPort("\\D"); + SigSpec sig_q = cell->getPort("\\Q"); log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n", log_id(module), log_id(cell), log_id(cell->type), @@ -190,7 +190,7 @@ struct Async2syncPass : public Pass { } Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q)); - new_q->attributes[ID::init] = init_val; + new_q->attributes["\\init"] = init_val; if (en_pol) { module->addMux(NEW_ID, new_q, sig_d, sig_en, sig_q); @@ -198,20 +198,20 @@ struct Async2syncPass : public Pass { module->addMux(NEW_ID, sig_d, new_q, sig_en, sig_q); } - cell->setPort(ID::D, sig_q); - cell->setPort(ID::Q, new_q); - cell->unsetPort(ID::EN); - cell->unsetParam(ID::EN_POLARITY); - cell->type = ID($ff); + cell->setPort("\\D", sig_q); + cell->setPort("\\Q", new_q); + cell->unsetPort("\\EN"); + cell->unsetParam("\\EN_POLARITY"); + cell->type = "$ff"; continue; } } for (auto wire : module->wires()) - if (wire->attributes.count(ID::init) > 0) + if (wire->attributes.count("\\init") > 0) { bool delete_initattr = true; - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); SigSpec initsig = sigmap(wire); for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++) @@ -221,9 +221,9 @@ struct Async2syncPass : public Pass { delete_initattr = false; if (delete_initattr) - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); else - wire->attributes.at(ID::init) = initval; + wire->attributes.at("\\init") = initval; } } } diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc index e5c5d0486d6..4bb4aa04762 100644 --- a/passes/sat/clk2fflogic.cc +++ b/passes/sat/clk2fflogic.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct Clk2fflogicPass : public Pass { Clk2fflogicPass() : Pass("clk2fflogic", "convert clocked FFs to generic $ff cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -36,7 +36,7 @@ struct Clk2fflogicPass : public Pass { log("multiple clocks.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { // bool flag_noinit = false; @@ -60,9 +60,9 @@ struct Clk2fflogicPass : public Pass { pool del_initbits; for (auto wire : module->wires()) - if (wire->attributes.count(ID::init) > 0) + if (wire->attributes.count("\\init") > 0) { - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); SigSpec initsig = sigmap(wire); for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++) @@ -72,26 +72,26 @@ struct Clk2fflogicPass : public Pass { for (auto cell : vector(module->selected_cells())) { - if (cell->type.in(ID($mem))) + if (cell->type.in("$mem")) { - int abits = cell->getParam(ID::ABITS).as_int(); - int width = cell->getParam(ID::WIDTH).as_int(); - int rd_ports = cell->getParam(ID::RD_PORTS).as_int(); - int wr_ports = cell->getParam(ID::WR_PORTS).as_int(); + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); + int rd_ports = cell->getParam("\\RD_PORTS").as_int(); + int wr_ports = cell->getParam("\\WR_PORTS").as_int(); for (int i = 0; i < rd_ports; i++) { - if (cell->getParam(ID::RD_CLK_ENABLE).extract(i).as_bool()) + if (cell->getParam("\\RD_CLK_ENABLE").extract(i).as_bool()) log_error("Read port %d of memory %s.%s is clocked. This is not supported by \"clk2fflogic\"! " "Call \"memory\" with -nordff to avoid this error.\n", i, log_id(cell), log_id(module)); } - Const wr_clk_en_param = cell->getParam(ID::WR_CLK_ENABLE); - Const wr_clk_pol_param = cell->getParam(ID::WR_CLK_POLARITY); + Const wr_clk_en_param = cell->getParam("\\WR_CLK_ENABLE"); + Const wr_clk_pol_param = cell->getParam("\\WR_CLK_POLARITY"); - SigSpec wr_clk_port = cell->getPort(ID::WR_CLK); - SigSpec wr_en_port = cell->getPort(ID::WR_EN); - SigSpec wr_addr_port = cell->getPort(ID::WR_ADDR); - SigSpec wr_data_port = cell->getPort(ID::WR_DATA); + SigSpec wr_clk_port = cell->getPort("\\WR_CLK"); + SigSpec wr_en_port = cell->getPort("\\WR_EN"); + SigSpec wr_addr_port = cell->getPort("\\WR_ADDR"); + SigSpec wr_data_port = cell->getPort("\\WR_DATA"); for (int wport = 0; wport < wr_ports; wport++) { @@ -111,17 +111,17 @@ struct Clk2fflogicPass : public Pass { log_signal(addr), log_signal(data)); Wire *past_clk = module->addWire(NEW_ID); - past_clk->attributes[ID::init] = clkpol ? State::S1 : State::S0; + past_clk->attributes["\\init"] = clkpol ? State::S1 : State::S0; module->addFf(NEW_ID, clk, past_clk); SigSpec clock_edge_pattern; if (clkpol) { - clock_edge_pattern.append(State::S0); - clock_edge_pattern.append(State::S1); + clock_edge_pattern.append_bit(State::S0); + clock_edge_pattern.append_bit(State::S1); } else { - clock_edge_pattern.append(State::S1); - clock_edge_pattern.append(State::S0); + clock_edge_pattern.append_bit(State::S1); + clock_edge_pattern.append_bit(State::S0); } SigSpec clock_edge = module->Eqx(NEW_ID, {clk, SigSpec(past_clk)}, clock_edge_pattern); @@ -144,22 +144,22 @@ struct Clk2fflogicPass : public Pass { wr_clk_pol_param[wport] = State::S0; } - cell->setParam(ID::WR_CLK_ENABLE, wr_clk_en_param); - cell->setParam(ID::WR_CLK_POLARITY, wr_clk_pol_param); + cell->setParam("\\WR_CLK_ENABLE", wr_clk_en_param); + cell->setParam("\\WR_CLK_POLARITY", wr_clk_pol_param); - cell->setPort(ID::WR_CLK, wr_clk_port); - cell->setPort(ID::WR_EN, wr_en_port); - cell->setPort(ID::WR_ADDR, wr_addr_port); - cell->setPort(ID::WR_DATA, wr_data_port); + cell->setPort("\\WR_CLK", wr_clk_port); + cell->setPort("\\WR_EN", wr_en_port); + cell->setPort("\\WR_ADDR", wr_addr_port); + cell->setPort("\\WR_DATA", wr_data_port); } - if (cell->type.in(ID($dlatch), ID($dlatchsr))) + if (cell->type.in("$dlatch", "$dlatchsr")) { - bool enpol = cell->parameters[ID::EN_POLARITY].as_bool(); + bool enpol = cell->parameters["\\EN_POLARITY"].as_bool(); - SigSpec sig_en = cell->getPort(ID::EN); - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); + SigSpec sig_en = cell->getPort("\\EN"); + SigSpec sig_d = cell->getPort("\\D"); + SigSpec sig_q = cell->getPort("\\Q"); log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n", log_id(module), log_id(cell), log_id(cell->type), @@ -168,7 +168,7 @@ struct Clk2fflogicPass : public Pass { Wire *past_q = module->addWire(NEW_ID, GetSize(sig_q)); module->addFf(NEW_ID, sig_q, past_q); - if (cell->type == ID($dlatch)) + if (cell->type == "$dlatch") { if (enpol) module->addMux(NEW_ID, past_q, sig_d, sig_en, sig_q); @@ -183,13 +183,13 @@ struct Clk2fflogicPass : public Pass { else t = module->Mux(NEW_ID, sig_d, past_q, sig_en); - SigSpec s = cell->getPort(ID::SET); - if (!cell->parameters[ID::SET_POLARITY].as_bool()) + SigSpec s = cell->getPort("\\SET"); + if (!cell->parameters["\\SET_POLARITY"].as_bool()) s = module->Not(NEW_ID, s); t = module->Or(NEW_ID, t, s); - SigSpec c = cell->getPort(ID::CLR); - if (cell->parameters[ID::CLR_POLARITY].as_bool()) + SigSpec c = cell->getPort("\\CLR"); + if (cell->parameters["\\CLR_POLARITY"].as_bool()) c = module->Not(NEW_ID, c); module->addAnd(NEW_ID, t, c, sig_q); } @@ -208,47 +208,23 @@ struct Clk2fflogicPass : public Pass { } if (assign_initval) - past_q->attributes[ID::init] = initval; + past_q->attributes["\\init"] = initval; module->remove(cell); continue; } - bool word_dff = cell->type.in(ID($dff), ID($adff), ID($dffsr)); - if (word_dff || cell->type.in(ID($_DFF_N_), ID($_DFF_P_), - ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_PP0_), ID($_DFF_PP1_), ID($_DFF_PN0_), ID($_DFF_PN1_), - ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), - ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_))) + if (cell->type.in("$dff", "$adff", "$dffsr")) { - bool clkpol; - SigSpec clk; - if (word_dff) { - clkpol = cell->parameters[ID::CLK_POLARITY].as_bool(); - clk = cell->getPort(ID::CLK); - } - else { - if (cell->type.in(ID($_DFF_P_), ID($_DFF_N_), - ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_PP0_), ID($_DFF_PP1_), ID($_DFF_PN0_), ID($_DFF_PN1_))) - clkpol = cell->type[6] == 'P'; - else if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), - ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_))) - clkpol = cell->type[8] == 'P'; - else log_abort(); - clk = cell->getPort(ID::C); - } + bool clkpol = cell->parameters["\\CLK_POLARITY"].as_bool(); + SigSpec clk = cell->getPort("\\CLK"); Wire *past_clk = module->addWire(NEW_ID); - past_clk->attributes[ID::init] = clkpol ? State::S1 : State::S0; + past_clk->attributes["\\init"] = clkpol ? State::S1 : State::S0; + module->addFf(NEW_ID, clk, past_clk); - if (word_dff) - module->addFf(NEW_ID, clk, past_clk); - else - module->addFfGate(NEW_ID, clk, past_clk); - - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); + SigSpec sig_d = cell->getPort("\\D"); + SigSpec sig_q = cell->getPort("\\Q"); log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n", log_id(module), log_id(cell), log_id(cell->type), @@ -257,105 +233,58 @@ struct Clk2fflogicPass : public Pass { SigSpec clock_edge_pattern; if (clkpol) { - clock_edge_pattern.append(State::S0); - clock_edge_pattern.append(State::S1); + clock_edge_pattern.append_bit(State::S0); + clock_edge_pattern.append_bit(State::S1); } else { - clock_edge_pattern.append(State::S1); - clock_edge_pattern.append(State::S0); + clock_edge_pattern.append_bit(State::S1); + clock_edge_pattern.append_bit(State::S0); } SigSpec clock_edge = module->Eqx(NEW_ID, {clk, SigSpec(past_clk)}, clock_edge_pattern); Wire *past_d = module->addWire(NEW_ID, GetSize(sig_d)); Wire *past_q = module->addWire(NEW_ID, GetSize(sig_q)); - if (word_dff) { - module->addFf(NEW_ID, sig_d, past_d); - module->addFf(NEW_ID, sig_q, past_q); - } - else { - module->addFfGate(NEW_ID, sig_d, past_d); - module->addFfGate(NEW_ID, sig_q, past_q); - } + module->addFf(NEW_ID, sig_d, past_d); + module->addFf(NEW_ID, sig_q, past_q); - if (cell->type == ID($adff)) + if (cell->type == "$adff") { - SigSpec arst = cell->getPort(ID::ARST); + SigSpec arst = cell->getPort("\\ARST"); SigSpec qval = module->Mux(NEW_ID, past_q, past_d, clock_edge); - Const rstval = cell->parameters[ID::ARST_VALUE]; + Const rstval = cell->parameters["\\ARST_VALUE"]; Wire *past_arst = module->addWire(NEW_ID); module->addFf(NEW_ID, arst, past_arst); - if (cell->parameters[ID::ARST_POLARITY].as_bool()) + if (cell->parameters["\\ARST_POLARITY"].as_bool()) arst = module->LogicOr(NEW_ID, arst, past_arst); else arst = module->LogicAnd(NEW_ID, arst, past_arst); - if (cell->parameters[ID::ARST_POLARITY].as_bool()) + if (cell->parameters["\\ARST_POLARITY"].as_bool()) module->addMux(NEW_ID, qval, rstval, arst, sig_q); else module->addMux(NEW_ID, rstval, qval, arst, sig_q); } else - if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_PP0_), ID($_DFF_PP1_), ID($_DFF_PN0_), ID($_DFF_PN1_))) - { - SigSpec arst = cell->getPort(ID::R); - SigSpec qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge); - SigBit rstval = (cell->type[8] == '1'); - - Wire *past_arst = module->addWire(NEW_ID); - module->addFfGate(NEW_ID, arst, past_arst); - if (cell->type[7] == 'P') - arst = module->OrGate(NEW_ID, arst, past_arst); - else - arst = module->AndGate(NEW_ID, arst, past_arst); - - if (cell->type[7] == 'P') - module->addMuxGate(NEW_ID, qval, rstval, arst, sig_q); - else - module->addMuxGate(NEW_ID, rstval, qval, arst, sig_q); - } - else - if (cell->type == ID($dffsr)) + if (cell->type == "$dffsr") { SigSpec qval = module->Mux(NEW_ID, past_q, past_d, clock_edge); - SigSpec setval = cell->getPort(ID::SET); - SigSpec clrval = cell->getPort(ID::CLR); + SigSpec setval = cell->getPort("\\SET"); + SigSpec clrval = cell->getPort("\\CLR"); - if (!cell->parameters[ID::SET_POLARITY].as_bool()) + if (!cell->parameters["\\SET_POLARITY"].as_bool()) setval = module->Not(NEW_ID, setval); - if (cell->parameters[ID::CLR_POLARITY].as_bool()) + if (cell->parameters["\\CLR_POLARITY"].as_bool()) clrval = module->Not(NEW_ID, clrval); qval = module->Or(NEW_ID, qval, setval); module->addAnd(NEW_ID, qval, clrval, sig_q); } else - if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), - ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_))) - { - SigSpec qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge); - SigSpec setval = cell->getPort(ID::S); - SigSpec clrval = cell->getPort(ID::R); - - if (cell->type[9] != 'P') - setval = module->Not(NEW_ID, setval); - - if (cell->type[10] == 'P') - clrval = module->Not(NEW_ID, clrval); - - qval = module->OrGate(NEW_ID, qval, setval); - module->addAndGate(NEW_ID, qval, clrval, sig_q); - } - else if (cell->type == ID($dff)) { module->addMux(NEW_ID, past_q, past_d, clock_edge, sig_q); } - else - { - module->addMuxGate(NEW_ID, past_q, past_d, clock_edge, sig_q); - } Const initval; bool assign_initval = false; @@ -371,8 +300,8 @@ struct Clk2fflogicPass : public Pass { } if (assign_initval) { - past_d->attributes[ID::init] = initval; - past_q->attributes[ID::init] = initval; + past_d->attributes["\\init"] = initval; + past_q->attributes["\\init"] = initval; } module->remove(cell); @@ -381,10 +310,10 @@ struct Clk2fflogicPass : public Pass { } for (auto wire : module->wires()) - if (wire->attributes.count(ID::init) > 0) + if (wire->attributes.count("\\init") > 0) { bool delete_initattr = true; - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); SigSpec initsig = sigmap(wire); for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++) @@ -394,9 +323,9 @@ struct Clk2fflogicPass : public Pass { delete_initattr = false; if (delete_initattr) - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); else - wire->attributes.at(ID::init) = initval; + wire->attributes.at("\\init") = initval; } } diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index 6fc267d51ee..b4549bc39b1 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct CutpointPass : public Pass { CutpointPass() : Pass("cutpoint", "adds formal cut points to the design") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -38,7 +38,7 @@ struct CutpointPass : public Pass { log(" $anyseq cell and drive the cutpoint net from that\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_undef = false; @@ -75,7 +75,7 @@ struct CutpointPass : public Pass { pool cutpoint_bits; for (auto cell : module->selected_cells()) { - if (cell->type == ID($anyseq)) + if (cell->type == "$anyseq") continue; log("Removing cell %s.%s, making all cell outputs cutpoints.\n", log_id(module), log_id(cell)); for (auto &conn : cell->connections()) { @@ -126,16 +126,15 @@ struct CutpointPass : public Pass { } vector rewrite_wires; - for (auto id : module->ports) { - RTLIL::Wire *wire = module->wire(id); - if (wire->port_input) { - int bit_count = 0; - for (auto &bit : sigmap(wire)) - if (cutpoint_bits.count(bit)) - bit_count++; - if (bit_count) - rewrite_wires.push_back(wire); - } + for (auto wire : module->wires()) { + if (!wire->port_input) + continue; + int bit_count = 0; + for (auto &bit : sigmap(wire)) + if (cutpoint_bits.count(bit)) + bit_count++; + if (bit_count) + rewrite_wires.push_back(wire); } for (auto wire : rewrite_wires) { diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc index 085e7c5b840..e0bb439f4d8 100644 --- a/passes/sat/eval.cc +++ b/passes/sat/eval.cc @@ -88,24 +88,25 @@ struct BruteForceEquivChecker mod1(mod1), mod2(mod2), counter(0), errors(0), ignore_x_mod1(ignore_x_mod1) { log("Checking for equivalence (brute-force): %s vs %s\n", mod1->name.c_str(), mod2->name.c_str()); - for (auto w : mod1->wires()) + for (auto &w : mod1->wires_) { - if (w->port_id == 0) + RTLIL::Wire *wire1 = w.second; + if (wire1->port_id == 0) continue; - if (mod2->wire(w->name) == nullptr) - log_cmd_error("Port %s in module 1 has no counterpart in module 2!\n", w->name.c_str()); + if (mod2->wires_.count(wire1->name) == 0) + log_cmd_error("Port %s in module 1 has no counterpart in module 2!\n", wire1->name.c_str()); - RTLIL::Wire *w2 = mod2->wire(w->name); - if (w->width != w2->width || w->port_input != w2->port_input || w->port_output != w2->port_output) - log_cmd_error("Port %s in module 1 does not match its counterpart in module 2!\n", w->name.c_str()); + RTLIL::Wire *wire2 = mod2->wires_.at(wire1->name); + if (wire1->width != wire2->width || wire1->port_input != wire2->port_input || wire1->port_output != wire2->port_output) + log_cmd_error("Port %s in module 1 does not match its counterpart in module 2!\n", wire1->name.c_str()); - if (w->port_input) { - mod1_inputs.append(w); - mod2_inputs.append(w2); + if (wire1->port_input) { + mod1_inputs.append(wire1); + mod2_inputs.append(wire2); } else { - mod1_outputs.append(w); - mod2_outputs.append(w2); + mod1_outputs.append(wire1); + mod2_outputs.append(wire2); } } @@ -147,17 +148,17 @@ struct VlogHammerReporter SatGen satgen(ez.get(), &sigmap); satgen.model_undef = model_undef; - for (auto c : module->cells()) - if (!satgen.importCell(c)) - log_error("Failed to import cell %s (type %s) to SAT database.\n", log_id(c->name), log_id(c->type)); + for (auto &c : module->cells_) + if (!satgen.importCell(c.second)) + log_error("Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c.first), RTLIL::id2cstr(c.second->type)); ez->assume(satgen.signals_eq(recorded_set_vars, recorded_set_vals)); - std::vector y_vec = satgen.importDefSigSpec(module->wire(ID(y))); + std::vector y_vec = satgen.importDefSigSpec(module->wires_.at("\\y")); std::vector y_values; if (model_undef) { - std::vector y_undef_vec = satgen.importUndefSigSpec(module->wire(ID(y))); + std::vector y_undef_vec = satgen.importUndefSigSpec(module->wires_.at("\\y")); y_vec.insert(y_vec.end(), y_undef_vec.begin(), y_undef_vec.end()); } @@ -252,7 +253,7 @@ struct VlogHammerReporter std::vector bits(patterns[idx].bits.begin(), patterns[idx].bits.begin() + total_input_width); for (int i = 0; i < int(inputs.size()); i++) { - RTLIL::Wire *wire = module->wire(inputs[i]); + RTLIL::Wire *wire = module->wires_.at(inputs[i]); for (int j = input_widths[i]-1; j >= 0; j--) { ce.set(RTLIL::SigSpec(wire, j), bits.back()); recorded_set_vars.append(RTLIL::SigSpec(wire, j)); @@ -262,21 +263,21 @@ struct VlogHammerReporter if (module == modules.front()) { RTLIL::SigSpec sig(wire); if (!ce.eval(sig)) - log_error("Can't read back value for port %s!\n", log_id(inputs[i])); + log_error("Can't read back value for port %s!\n", RTLIL::id2cstr(inputs[i])); input_pattern_list += stringf(" %s", sig.as_const().as_string().c_str()); - log("++PAT++ %d %s %s #\n", idx, log_id(inputs[i]), sig.as_const().as_string().c_str()); + log("++PAT++ %d %s %s #\n", idx, RTLIL::id2cstr(inputs[i]), sig.as_const().as_string().c_str()); } } - if (module->wire(ID(y)) == nullptr) - log_error("No output wire (y) found in module %s!\n", log_id(module->name)); + if (module->wires_.count("\\y") == 0) + log_error("No output wire (y) found in module %s!\n", RTLIL::id2cstr(module->name)); - RTLIL::SigSpec sig(module->wire(ID(y))); + RTLIL::SigSpec sig(module->wires_.at("\\y")); RTLIL::SigSpec undef; while (!ce.eval(sig, undef)) { - // log_error("Evaluation of y in module %s failed: sig=%s, undef=%s\n", log_id(module->name), log_signal(sig), log_signal(undef)); - log_warning("Setting signal %s in module %s to undef.\n", log_signal(undef), log_id(module->name)); + // log_error("Evaluation of y in module %s failed: sig=%s, undef=%s\n", RTLIL::id2cstr(module->name), log_signal(sig), log_signal(undef)); + log_warning("Setting signal %s in module %s to undef.\n", log_signal(undef), RTLIL::id2cstr(module->name)); ce.set(undef, RTLIL::Const(RTLIL::State::Sx, undef.size())); } @@ -288,7 +289,7 @@ struct VlogHammerReporter sat_check(module, recorded_set_vars, recorded_set_vals, sig, true); } else if (rtl_sig.size() > 0) { if (rtl_sig.size() != sig.size()) - log_error("Output (y) has a different width in module %s compared to rtl!\n", log_id(module->name)); + log_error("Output (y) has a different width in module %s compared to rtl!\n", RTLIL::id2cstr(module->name)); for (int i = 0; i < GetSize(sig); i++) if (rtl_sig[i] == RTLIL::State::Sx) sig[i] = RTLIL::State::Sx; @@ -306,10 +307,10 @@ struct VlogHammerReporter { for (auto name : split(module_list, ",")) { RTLIL::IdString esc_name = RTLIL::escape_id(module_prefix + name); - if (design->module(esc_name) == nullptr) + if (design->modules_.count(esc_name) == 0) log_error("Can't find module %s in current design!\n", name.c_str()); log("Using module %s (%s).\n", esc_name.c_str(), name.c_str()); - modules.push_back(design->module(esc_name)); + modules.push_back(design->modules_.at(esc_name)); module_names.push_back(name); } @@ -318,11 +319,11 @@ struct VlogHammerReporter int width = -1; RTLIL::IdString esc_name = RTLIL::escape_id(name); for (auto mod : modules) { - if (mod->wire(esc_name) == nullptr) - log_error("Can't find input %s in module %s!\n", name.c_str(), log_id(mod->name)); - RTLIL::Wire *port = mod->wire(esc_name); + if (mod->wires_.count(esc_name) == 0) + log_error("Can't find input %s in module %s!\n", name.c_str(), RTLIL::id2cstr(mod->name)); + RTLIL::Wire *port = mod->wires_.at(esc_name); if (!port->port_input || port->port_output) - log_error("Wire %s in module %s is not an input!\n", name.c_str(), log_id(mod->name)); + log_error("Wire %s in module %s is not an input!\n", name.c_str(), RTLIL::id2cstr(mod->name)); if (width >= 0 && width != port->width) log_error("Port %s has different sizes in the different modules!\n", name.c_str()); width = port->width; @@ -359,7 +360,7 @@ struct VlogHammerReporter struct EvalPass : public Pass { EvalPass() : Pass("eval", "evaluate the circuit given an input") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -382,7 +383,7 @@ struct EvalPass : public Pass { log(" then all output ports of the current module are used.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::vector> sets; std::vector shows, tables; @@ -414,11 +415,11 @@ struct EvalPass : public Pass { /* this should only be used for regression testing of ConstEval -- see vloghammer */ std::string mod1_name = RTLIL::escape_id(args[++argidx]); std::string mod2_name = RTLIL::escape_id(args[++argidx]); - if (design->module(mod1_name) == nullptr) + if (design->modules_.count(mod1_name) == 0) log_error("Can't find module `%s'!\n", mod1_name.c_str()); - if (design->module(mod2_name) == nullptr) + if (design->modules_.count(mod2_name) == 0) log_error("Can't find module `%s'!\n", mod2_name.c_str()); - BruteForceEquivChecker checker(design->module(mod1_name), design->module(mod2_name), args[argidx-2] == "-brute_force_equiv_checker_x"); + BruteForceEquivChecker checker(design->modules_.at(mod1_name), design->modules_.at(mod2_name), args[argidx-2] == "-brute_force_equiv_checker_x"); if (checker.errors > 0) log_cmd_error("Modules are not equivalent!\n"); log("Verified %s = %s (using brute-force check on %d cases).\n", @@ -440,12 +441,13 @@ struct EvalPass : public Pass { extra_args(args, argidx, design); RTLIL::Module *module = NULL; - for (auto mod : design->selected_modules()) { - if (module) - log_cmd_error("Only one module must be selected for the EVAL pass! (selected: %s and %s)\n", - log_id(module->name), log_id(mod->name)); - module = mod; - } + for (auto &mod_it : design->modules_) + if (design->selected(mod_it.second)) { + if (module) + log_cmd_error("Only one module must be selected for the EVAL pass! (selected: %s and %s)\n", + RTLIL::id2cstr(module->name), RTLIL::id2cstr(mod_it.first)); + module = mod_it.second; + } if (module == NULL) log_cmd_error("Can't perform EVAL on an empty selection!\n"); @@ -466,9 +468,9 @@ struct EvalPass : public Pass { } if (shows.size() == 0) { - for (auto w : module->wires()) - if (w->port_output) - shows.push_back(w->name.str()); + for (auto &it : module->wires_) + if (it.second->port_output) + shows.push_back(it.second->name.str()); } if (tables.empty()) diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index 2c65821cfd8..29dfc7b19f0 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -53,7 +53,7 @@ bool consider_cell(RTLIL::Design *design, std::set &dff_cells, { if (cell->name[0] == '$' || dff_cells.count(cell->name)) return false; - if (cell->type[0] == '\\' && (design->module(cell->type) == nullptr)) + if (cell->type[0] == '\\' && !design->modules_.count(cell->type)) return false; return true; } @@ -85,24 +85,27 @@ void find_dff_wires(std::set &dff_wires, RTLIL::Module *module) SigMap sigmap(module); SigPool dffsignals; - for (auto cell : module->cells()) { - if (ct.cell_known(cell->type) && cell->hasPort(ID::Q)) - dffsignals.add(sigmap(cell->getPort(ID::Q))); + for (auto &it : module->cells_) { + if (ct.cell_known(it.second->type) && it.second->hasPort("\\Q")) + dffsignals.add(sigmap(it.second->getPort("\\Q"))); } - for (auto w : module->wires()) { - if (dffsignals.check_any(w)) - dff_wires.insert(w->name); + for (auto &it : module->wires_) { + if (dffsignals.check_any(it.second)) + dff_wires.insert(it.first); } } -void create_dff_dq_map(std::map &map, RTLIL::Module *module) +void create_dff_dq_map(std::map &map, RTLIL::Design *design, RTLIL::Module *module) { std::map bit_info; SigMap sigmap(module); - for (auto cell : module->selected_cells()) + for (auto &it : module->cells_) { + if (!design->selected(module, it.second)) + continue; + dff_map_bit_info_t info; info.bit_d = RTLIL::State::Sm; info.bit_clk = RTLIL::State::Sm; @@ -110,13 +113,13 @@ void create_dff_dq_map(std::map &map, RTLIL::Mo info.clk_polarity = false; info.arst_polarity = false; info.arst_value = RTLIL::State::Sm; - info.cell = cell; + info.cell = it.second; - if (info.cell->type == ID($dff)) { - info.bit_clk = sigmap(info.cell->getPort(ID::CLK)).as_bit(); - info.clk_polarity = info.cell->parameters.at(ID::CLK_POLARITY).as_bool(); - std::vector sig_d = sigmap(info.cell->getPort(ID::D)).to_sigbit_vector(); - std::vector sig_q = sigmap(info.cell->getPort(ID::Q)).to_sigbit_vector(); + if (info.cell->type == "$dff") { + info.bit_clk = sigmap(info.cell->getPort("\\CLK")).as_bit(); + info.clk_polarity = info.cell->parameters.at("\\CLK_POLARITY").as_bool(); + std::vector sig_d = sigmap(info.cell->getPort("\\D")).to_sigbit_vector(); + std::vector sig_q = sigmap(info.cell->getPort("\\Q")).to_sigbit_vector(); for (size_t i = 0; i < sig_d.size(); i++) { info.bit_d = sig_d.at(i); bit_info[sig_q.at(i)] = info; @@ -124,14 +127,14 @@ void create_dff_dq_map(std::map &map, RTLIL::Mo continue; } - if (info.cell->type == ID($adff)) { - info.bit_clk = sigmap(info.cell->getPort(ID::CLK)).as_bit(); - info.bit_arst = sigmap(info.cell->getPort(ID::ARST)).as_bit(); - info.clk_polarity = info.cell->parameters.at(ID::CLK_POLARITY).as_bool(); - info.arst_polarity = info.cell->parameters.at(ID::ARST_POLARITY).as_bool(); - std::vector sig_d = sigmap(info.cell->getPort(ID::D)).to_sigbit_vector(); - std::vector sig_q = sigmap(info.cell->getPort(ID::Q)).to_sigbit_vector(); - std::vector arst_value = info.cell->parameters.at(ID::ARST_VALUE).bits; + if (info.cell->type == "$adff") { + info.bit_clk = sigmap(info.cell->getPort("\\CLK")).as_bit(); + info.bit_arst = sigmap(info.cell->getPort("\\ARST")).as_bit(); + info.clk_polarity = info.cell->parameters.at("\\CLK_POLARITY").as_bool(); + info.arst_polarity = info.cell->parameters.at("\\ARST_POLARITY").as_bool(); + std::vector sig_d = sigmap(info.cell->getPort("\\D")).to_sigbit_vector(); + std::vector sig_q = sigmap(info.cell->getPort("\\Q")).to_sigbit_vector(); + std::vector arst_value = info.cell->parameters.at("\\ARST_VALUE").bits; for (size_t i = 0; i < sig_d.size(); i++) { info.bit_d = sig_d.at(i); info.arst_value = arst_value.at(i); @@ -140,33 +143,33 @@ void create_dff_dq_map(std::map &map, RTLIL::Mo continue; } - if (info.cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { - info.bit_clk = sigmap(info.cell->getPort(ID::C)).as_bit(); - info.clk_polarity = info.cell->type == ID($_DFF_P_); - info.bit_d = sigmap(info.cell->getPort(ID::D)).as_bit(); - bit_info[sigmap(info.cell->getPort(ID::Q)).as_bit()] = info; + if (info.cell->type.in("$_DFF_N_", "$_DFF_P_")) { + info.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit(); + info.clk_polarity = info.cell->type == "$_DFF_P_"; + info.bit_d = sigmap(info.cell->getPort("\\D")).as_bit(); + bit_info[sigmap(info.cell->getPort("\\Q")).as_bit()] = info; continue; } if (info.cell->type.size() == 10 && info.cell->type.begins_with("$_DFF_")) { - info.bit_clk = sigmap(info.cell->getPort(ID::C)).as_bit(); - info.bit_arst = sigmap(info.cell->getPort(ID::R)).as_bit(); + info.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit(); + info.bit_arst = sigmap(info.cell->getPort("\\R")).as_bit(); info.clk_polarity = info.cell->type[6] == 'P'; info.arst_polarity = info.cell->type[7] == 'P'; info.arst_value = info.cell->type[0] == '1' ? RTLIL::State::S1 : RTLIL::State::S0; - info.bit_d = sigmap(info.cell->getPort(ID::D)).as_bit(); - bit_info[sigmap(info.cell->getPort(ID::Q)).as_bit()] = info; + info.bit_d = sigmap(info.cell->getPort("\\D")).as_bit(); + bit_info[sigmap(info.cell->getPort("\\Q")).as_bit()] = info; continue; } } std::map empty_dq_map; - for (auto w : module->wires()) + for (auto &it : module->wires_) { - if (!consider_wire(w, empty_dq_map)) + if (!consider_wire(it.second, empty_dq_map)) continue; - std::vector bits_q = sigmap(w).to_sigbit_vector(); + std::vector bits_q = sigmap(it.second).to_sigbit_vector(); std::vector bits_d; std::vector arst_value; std::set cells; @@ -204,7 +207,7 @@ void create_dff_dq_map(std::map &map, RTLIL::Mo info.arst_value = arst_value; for (auto it : cells) info.cells.push_back(it->name); - map[w->name] = info; + map[it.first] = info; } } @@ -217,7 +220,7 @@ RTLIL::Wire *add_new_wire(RTLIL::Module *module, RTLIL::IdString name, int width struct ExposePass : public Pass { ExposePass() : Pass("expose", "convert internal signals to module ports") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -254,7 +257,7 @@ struct ExposePass : public Pass { log(" designator for the exposed signal.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_shared = false; bool flag_evert = false; @@ -281,15 +284,11 @@ struct ExposePass : public Pass { flag_dff = true; continue; } - if (args[argidx] == "-cut") { - if (flag_input) - log_cmd_error("Options -cut and -input are mutually exclusive.\n"); + if (args[argidx] == "-cut" && !flag_input) { flag_cut = true; continue; } - if (args[argidx] == "-input") { - if (flag_cut) - log_cmd_error("Options -cut and -input are mutually exclusive.\n"); + if (args[argidx] == "-input" && !flag_cut) { flag_input = true; continue; } @@ -315,23 +314,26 @@ struct ExposePass : public Pass { RTLIL::Module *first_module = NULL; std::set shared_dff_wires; - for (auto mod : design->selected_modules()) + for (auto &mod_it : design->modules_) { - create_dff_dq_map(dff_dq_maps[mod], mod); + if (!design->selected(mod_it.second)) + continue; + + create_dff_dq_map(dff_dq_maps[mod_it.second], design, mod_it.second); if (!flag_shared) continue; if (first_module == NULL) { - for (auto &it : dff_dq_maps[mod]) + for (auto &it : dff_dq_maps[mod_it.second]) shared_dff_wires.insert(it.first); - first_module = mod; + first_module = mod_it.second; } else { std::set new_shared_dff_wires; for (auto &it : shared_dff_wires) { - if (!dff_dq_maps[mod].count(it)) + if (!dff_dq_maps[mod_it.second].count(it)) continue; - if (!compare_wires(first_module->wire(it), mod->wire(it))) + if (!compare_wires(first_module->wires_.at(it), mod_it.second->wires_.at(it))) continue; new_shared_dff_wires.insert(it); } @@ -362,23 +364,28 @@ struct ExposePass : public Pass { { RTLIL::Module *first_module = NULL; - for (auto module : design->selected_modules()) + for (auto &mod_it : design->modules_) { + RTLIL::Module *module = mod_it.second; + + if (!design->selected(module)) + continue; + std::set dff_wires; if (flag_dff) find_dff_wires(dff_wires, module); if (first_module == NULL) { - for (auto w : module->wires()) - if (design->selected(module, w) && consider_wire(w, dff_dq_maps[module])) - if (!flag_dff || dff_wires.count(w->name)) - shared_wires.insert(w->name); + for (auto &it : module->wires_) + if (design->selected(module, it.second) && consider_wire(it.second, dff_dq_maps[module])) + if (!flag_dff || dff_wires.count(it.first)) + shared_wires.insert(it.first); if (flag_evert) - for (auto cell : module->cells()) - if (design->selected(module, cell) && consider_cell(design, dff_cells[module], cell)) - shared_cells.insert(cell->name); + for (auto &it : module->cells_) + if (design->selected(module, it.second) && consider_cell(design, dff_cells[module], it.second)) + shared_cells.insert(it.first); first_module = module; } @@ -390,16 +397,16 @@ struct ExposePass : public Pass { { RTLIL::Wire *wire; - if (module->wire(it) == nullptr) + if (module->wires_.count(it) == 0) goto delete_shared_wire; - wire = module->wire(it); + wire = module->wires_.at(it); if (!design->selected(module, wire)) goto delete_shared_wire; if (!consider_wire(wire, dff_dq_maps[module])) goto delete_shared_wire; - if (!compare_wires(first_module->wire(it), wire)) + if (!compare_wires(first_module->wires_.at(it), wire)) goto delete_shared_wire; if (flag_dff && !dff_wires.count(it)) goto delete_shared_wire; @@ -414,16 +421,16 @@ struct ExposePass : public Pass { { RTLIL::Cell *cell; - if (module->cell(it) == nullptr) + if (module->cells_.count(it) == 0) goto delete_shared_cell; - cell = module->cell(it); + cell = module->cells_.at(it); if (!design->selected(module, cell)) goto delete_shared_cell; if (!consider_cell(design, dff_cells[module], cell)) goto delete_shared_cell; - if (!compare_cells(first_module->cell(it), cell)) + if (!compare_cells(first_module->cells_.at(it), cell)) goto delete_shared_cell; if (0) @@ -439,8 +446,13 @@ struct ExposePass : public Pass { } } - for (auto module : design->selected_modules()) + for (auto &mod_it : design->modules_) { + RTLIL::Module *module = mod_it.second; + + if (!design->selected(module)) + continue; + std::set dff_wires; if (flag_dff && !flag_shared) find_dff_wires(dff_wires, module); @@ -449,54 +461,49 @@ struct ExposePass : public Pass { SigMap out_to_in_map; - std::map wire_map; - - for (auto w : module->wires()) + for (auto &it : module->wires_) { if (flag_shared) { - if (shared_wires.count(w->name) == 0) + if (shared_wires.count(it.first) == 0) continue; } else { - if (!design->selected(module, w) || !consider_wire(w, dff_dq_maps[module])) + if (!design->selected(module, it.second) || !consider_wire(it.second, dff_dq_maps[module])) continue; - if (flag_dff && !dff_wires.count(w->name)) + if (flag_dff && !dff_wires.count(it.first)) continue; } if (flag_input) { - if (!w->port_input) { - w->port_input = true; - log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name)); - wire_map[w] = NEW_ID; + if (!it.second->port_input) { + it.second->port_input = true; + log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(it.second->name)); + RTLIL::Wire *w = module->addWire(NEW_ID, GetSize(it.second)); + out_to_in_map.add(it.second, w); } } else { - if (!w->port_output) { - w->port_output = true; - log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name)); + if (!it.second->port_output) { + it.second->port_output = true; + log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(it.second->name)); } if (flag_cut) { - wire_map[w] = w->name.str() + sep + "i"; + RTLIL::Wire *in_wire = add_new_wire(module, it.second->name.str() + sep + "i", it.second->width); + in_wire->port_input = true; + out_to_in_map.add(sigmap(it.second), in_wire); } } } if (flag_input) { - for (auto &wm : wire_map) - { - RTLIL::Wire *in_wire = module->addWire(wm.second, GetSize(wm.first)); - out_to_in_map.add(wm.first, in_wire); - } - - for (auto cell : module->cells()) { - if (!ct.cell_known(cell->type)) + for (auto &it : module->cells_) { + if (!ct.cell_known(it.second->type)) continue; - for (auto &conn : cell->connections_) - if (ct.cell_output(cell->type, conn.first)) + for (auto &conn : it.second->connections_) + if (ct.cell_output(it.second->type, conn.first)) conn.second = out_to_in_map(sigmap(conn.second)); } @@ -506,18 +513,11 @@ struct ExposePass : public Pass { if (flag_cut) { - for (auto &wm : wire_map) - { - RTLIL::Wire *in_wire = add_new_wire(module, wm.second, wm.first->width); - in_wire->port_input = true; - out_to_in_map.add(sigmap(wm.first), in_wire); - } - - for (auto cell : module->cells()) { - if (!ct.cell_known(cell->type)) + for (auto &it : module->cells_) { + if (!ct.cell_known(it.second->type)) continue; - for (auto &conn : cell->connections_) - if (ct.cell_input(cell->type, conn.first)) + for (auto &conn : it.second->connections_) + if (ct.cell_input(it.second->type, conn.first)) conn.second = out_to_in_map(sigmap(conn.second)); } @@ -529,10 +529,10 @@ struct ExposePass : public Pass { for (auto &dq : dff_dq_maps[module]) { - if (module->wire(dq.first) == nullptr) + if (!module->wires_.count(dq.first)) continue; - RTLIL::Wire *wire = module->wire(dq.first); + RTLIL::Wire *wire = module->wires_.at(dq.first); std::set wire_bits_set = sigmap(wire).to_sigbit_set(); std::vector wire_bits_vec = sigmap(wire).to_sigbit_vector(); @@ -541,12 +541,12 @@ struct ExposePass : public Pass { RTLIL::Wire *wire_dummy_q = add_new_wire(module, NEW_ID, 0); for (auto &cell_name : info.cells) { - RTLIL::Cell *cell = module->cell(cell_name); - std::vector cell_q_bits = sigmap(cell->getPort(ID::Q)).to_sigbit_vector(); + RTLIL::Cell *cell = module->cells_.at(cell_name); + std::vector cell_q_bits = sigmap(cell->getPort("\\Q")).to_sigbit_vector(); for (auto &bit : cell_q_bits) if (wire_bits_set.count(bit)) bit = RTLIL::SigBit(wire_dummy_q, wire_dummy_q->width++); - cell->setPort(ID::Q, cell_q_bits); + cell->setPort("\\Q", cell_q_bits); } RTLIL::Wire *wire_q = add_new_wire(module, wire->name.str() + sep + "q", wire->width); @@ -574,12 +574,12 @@ struct ExposePass : public Pass { if (info.clk_polarity) { module->connect(RTLIL::SigSig(wire_c, info.sig_clk)); } else { - RTLIL::Cell *c = module->addCell(NEW_ID, ID($not)); - c->parameters[ID::A_SIGNED] = 0; - c->parameters[ID::A_WIDTH] = 1; - c->parameters[ID::Y_WIDTH] = 1; - c->setPort(ID::A, info.sig_clk); - c->setPort(ID::Y, wire_c); + RTLIL::Cell *c = module->addCell(NEW_ID, "$not"); + c->parameters["\\A_SIGNED"] = 0; + c->parameters["\\A_WIDTH"] = 1; + c->parameters["\\Y_WIDTH"] = 1; + c->setPort("\\A", info.sig_clk); + c->setPort("\\Y", wire_c); } if (info.sig_arst != RTLIL::State::Sm) @@ -590,12 +590,12 @@ struct ExposePass : public Pass { if (info.arst_polarity) { module->connect(RTLIL::SigSig(wire_r, info.sig_arst)); } else { - RTLIL::Cell *c = module->addCell(NEW_ID, ID($not)); - c->parameters[ID::A_SIGNED] = 0; - c->parameters[ID::A_WIDTH] = 1; - c->parameters[ID::Y_WIDTH] = 1; - c->setPort(ID::A, info.sig_arst); - c->setPort(ID::Y, wire_r); + RTLIL::Cell *c = module->addCell(NEW_ID, "$not"); + c->parameters["\\A_SIGNED"] = 0; + c->parameters["\\A_WIDTH"] = 1; + c->parameters["\\Y_WIDTH"] = 1; + c->setPort("\\A", info.sig_arst); + c->setPort("\\Y", wire_r); } RTLIL::Wire *wire_v = add_new_wire(module, wire->name.str() + sep + "v", wire->width); @@ -609,22 +609,25 @@ struct ExposePass : public Pass { { std::vector delete_cells; - for (auto cell : module->cells()) + for (auto &it : module->cells_) { if (flag_shared) { - if (shared_cells.count(cell->name) == 0) + if (shared_cells.count(it.first) == 0) continue; } else { - if (!design->selected(module, cell) || !consider_cell(design, dff_cells[module], cell)) + if (!design->selected(module, it.second) || !consider_cell(design, dff_cells[module], it.second)) continue; } - if (design->module(cell->type) != nullptr) + RTLIL::Cell *cell = it.second; + + if (design->modules_.count(cell->type)) { - RTLIL::Module *mod = design->module(cell->type); + RTLIL::Module *mod = design->modules_.at(cell->type); - for (auto p : mod->wires()) + for (auto &it : mod->wires_) { + RTLIL::Wire *p = it.second; if (!p->port_input && !p->port_output) continue; diff --git a/passes/sat/fmcombine.cc b/passes/sat/fmcombine.cc index 5694a7473dd..00c098542c2 100644 --- a/passes/sat/fmcombine.cc +++ b/passes/sat/fmcombine.cc @@ -43,7 +43,7 @@ struct FmcombineWorker FmcombineWorker(Design *design, IdString orig_type, const opts_t &opts) : opts(opts), design(design), original(design->module(orig_type)), - orig_type(orig_type), combined_type(stringf("$fmcombine%s", orig_type.c_str())) + orig_type(orig_type), combined_type("$fmcombine" + orig_type.str()) { } @@ -106,7 +106,7 @@ struct FmcombineWorker for (auto cell : original->cells()) { if (design->module(cell->type) == nullptr) { - if (opts.anyeq && cell->type.in(ID($anyseq), ID($anyconst))) { + if (opts.anyeq && cell->type.in("$anyseq", "$anyconst")) { Cell *gold = import_prim_cell(cell, "_gold"); for (auto &conn : cell->connections()) module->connect(import_sig(conn.second, "_gate"), gold->getPort(conn.first)); @@ -114,10 +114,10 @@ struct FmcombineWorker Cell *gold = import_prim_cell(cell, "_gold"); Cell *gate = import_prim_cell(cell, "_gate"); if (opts.initeq) { - if (cell->type.in(ID($ff), ID($dff), ID($dffe), - ID($dffsr), ID($adff), ID($dlatch), ID($dlatchsr))) { - SigSpec gold_q = gold->getPort(ID::Q); - SigSpec gate_q = gate->getPort(ID::Q); + if (cell->type.in("$ff", "$dff", "$dffe", + "$dffsr", "$adff", "$dlatch", "$dlatchsr")) { + SigSpec gold_q = gold->getPort("\\Q"); + SigSpec gate_q = gate->getPort("\\Q"); SigSpec en = module->Initstate(NEW_ID); SigSpec eq = module->Eq(NEW_ID, gold_q, gate_q); module->addAssume(NEW_ID, eq, en); @@ -235,7 +235,7 @@ struct FmcombineWorker struct FmcombinePass : public Pass { FmcombinePass() : Pass("fmcombine", "combine two instances of a cell into one") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -272,7 +272,7 @@ struct FmcombinePass : public Pass { log("If none of -fwd, -bwd, and -nop is given, then -fwd is used as default.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { opts_t opts; Module *module = nullptr; @@ -359,7 +359,7 @@ struct FmcombinePass : public Pass { Cell *cell = module->addCell(combined_cell_name, worker.combined_type); cell->attributes = gold_cell->attributes; - cell->add_strpool_attribute(ID::src, gate_cell->get_strpool_attribute(ID::src)); + cell->add_strpool_attribute("\\src", gate_cell->get_strpool_attribute("\\src")); log("Combining cells %s and %s in module %s into new cell %s.\n", log_id(gold_cell), log_id(gate_cell), log_id(module), log_id(cell)); diff --git a/passes/sat/fminit.cc b/passes/sat/fminit.cc deleted file mode 100644 index c72e62548d8..00000000000 --- a/passes/sat/fminit.cc +++ /dev/null @@ -1,197 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * 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 - -struct FminitPass : public Pass { - FminitPass() : Pass("fminit", "set init values/sequences for formal") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" fminit [options] \n"); - log("\n"); - log("This pass creates init constraints (for example for reset sequences) in a formal\n"); - log("model.\n"); - log("\n"); - log(" -seq \n"); - log(" Set sequence using comma-separated list of values, use 'z for\n"); - log(" unconstrained bits. The last value is used for the remainder of the\n"); - log(" trace.\n"); - log("\n"); - log(" -set \n"); - log(" Add constant value constraint\n"); - log("\n"); - log(" -posedge \n"); - log(" -negedge \n"); - log(" Set clock for init sequences\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - vector>> initdata; - vector> setdata; - string clocksignal; - bool clockedge; - - log_header(design, "Executing FMINIT pass.\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - // if (args[argidx] == "-o" && argidx+1 < args.size()) { - // filename = args[++argidx]; - // continue; - // } - if (args[argidx] == "-seq" && argidx+2 < args.size()) { - string lhs = args[++argidx]; - string rhs = args[++argidx]; - initdata.push_back(make_pair(lhs, split_tokens(rhs, ","))); - continue; - } - if (args[argidx] == "-set" && argidx+2 < args.size()) { - string lhs = args[++argidx]; - string rhs = args[++argidx]; - setdata.push_back(make_pair(lhs, rhs)); - continue; - } - if (args[argidx] == "-posedge" && argidx+1 < args.size()) { - clocksignal = args[++argidx]; - clockedge = true; - continue; - } - if (args[argidx] == "-negedge" && argidx+1 < args.size()) { - clocksignal = args[++argidx]; - clockedge = true; - continue; - } - break; - } - extra_args(args, argidx, design); - - Module *module = nullptr; - - for (auto mod : design->selected_modules()) { - if (module != nullptr) - log_error("'fminit' requires exactly one module to be selected.\n"); - module = mod; - } - - if (module == nullptr) - log_error("'fminit' requires exactly one module to be selected.\n"); - - SigSpec clksig; - if (!clocksignal.empty()) { - if (!SigSpec::parse(clksig, module, clocksignal)) - log_error("Error parsing expression '%s'.\n", clocksignal.c_str()); - } - - for (auto &it : setdata) - { - SigSpec lhs, rhs; - - if (!SigSpec::parse(lhs, module, it.first)) - log_error("Error parsing expression '%s'.\n", it.first.c_str()); - - if (!SigSpec::parse_rhs(lhs, rhs, module, it.second)) - log_error("Error parsing expression '%s'.\n", it.second.c_str()); - - SigSpec final_lhs, final_rhs; - - for (int i = 0; i < GetSize(rhs); i++) - if (rhs[i] != State::Sz) { - final_lhs.append(lhs[i]); - final_rhs.append(rhs[i]); - } - - if (!final_lhs.empty()) { - SigSpec eq = module->Eq(NEW_ID, final_lhs, final_rhs); - module->addAssume(NEW_ID, eq, State::S1); - } - } - - vector ctrlsig; - vector ctrlsig_latched; - - for (auto &it : initdata) - { - SigSpec lhs, rhs; - - if (!SigSpec::parse(lhs, module, it.first)) - log_error("Error parsing expression '%s'.\n", it.first.c_str()); - - for (int i = 0; i < GetSize(it.second); i++) - { - if (i >= GetSize(ctrlsig)) - { - SigSpec insig = i > 0 ? ctrlsig.at(i-1) : State::S0; - - Wire *outwire = module->addWire(NEW_ID); - outwire->attributes[ID::init] = i > 0 ? State::S0 : State::S1; - - if (clksig.empty()) - module->addFf(NEW_ID, insig, outwire); - else - module->addDff(NEW_ID, clksig, insig, outwire, clockedge); - - ctrlsig.push_back(outwire); - ctrlsig_latched.push_back(SigSpec()); - } - - if (i+1 == GetSize(it.second) && ctrlsig_latched[i].empty()) - { - Wire *ffwire = module->addWire(NEW_ID); - ffwire->attributes[ID::init] = State::S0; - SigSpec outsig = module->Or(NEW_ID, ffwire, ctrlsig[i]); - - if (clksig.empty()) - module->addFf(NEW_ID, outsig, ffwire); - else - module->addDff(NEW_ID, clksig, outsig, ffwire, clockedge); - - ctrlsig_latched[i] = outsig; - } - - SigSpec ctrl = i+1 == GetSize(it.second) ? ctrlsig_latched[i] : ctrlsig[i]; - - SigSpec final_lhs, final_rhs; - - if (!SigSpec::parse_rhs(lhs, rhs, module, it.second[i])) - log_error("Error parsing expression '%s'.\n", it.second[i].c_str()); - - for (int i = 0; i < GetSize(rhs); i++) - if (rhs[i] != State::Sz) { - final_lhs.append(lhs[i]); - final_rhs.append(rhs[i]); - } - - if (!final_lhs.empty()) { - SigSpec eq = module->Eq(NEW_ID, final_lhs, final_rhs); - module->addAssume(NEW_ID, eq, ctrl); - } - } - } - } -} FminitPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/sat/freduce.cc b/passes/sat/freduce.cc index 762edfdfbf0..f29631639ba 100644 --- a/passes/sat/freduce.cc +++ b/passes/sat/freduce.cc @@ -614,29 +614,29 @@ struct FreduceWorker int bits_full_total = 0; std::vector> batches; - for (auto w : module->wires()) - if (w->port_input) { - batches.push_back(sigmap(w).to_sigbit_set()); - bits_full_total += w->width; + for (auto &it : module->wires_) + if (it.second->port_input) { + batches.push_back(sigmap(it.second).to_sigbit_set()); + bits_full_total += it.second->width; } - for (auto cell : module->cells()) { - if (ct.cell_known(cell->type)) { + for (auto &it : module->cells_) { + if (ct.cell_known(it.second->type)) { std::set inputs, outputs; - for (auto &port : cell->connections()) { + for (auto &port : it.second->connections()) { std::vector bits = sigmap(port.second).to_sigbit_vector(); - if (ct.cell_output(cell->type, port.first)) + if (ct.cell_output(it.second->type, port.first)) outputs.insert(bits.begin(), bits.end()); else inputs.insert(bits.begin(), bits.end()); } - std::pair> drv(cell, inputs); + std::pair> drv(it.second, inputs); for (auto &bit : outputs) drivers[bit] = drv; batches.push_back(outputs); bits_full_total += outputs.size(); } - if (inv_mode && cell->type == ID($_NOT_)) - inv_pairs.insert(std::pair(sigmap(cell->getPort(ID::A)), sigmap(cell->getPort(ID::Y)))); + if (inv_mode && it.second->type == "$_NOT_") + inv_pairs.insert(std::pair(sigmap(it.second->getPort("\\A")), sigmap(it.second->getPort("\\Y")))); } int bits_count = 0; @@ -731,9 +731,9 @@ struct FreduceWorker { inv_sig = module->addWire(NEW_ID); - RTLIL::Cell *inv_cell = module->addCell(NEW_ID, ID($_NOT_)); - inv_cell->setPort(ID::A, grp[0].bit); - inv_cell->setPort(ID::Y, inv_sig); + RTLIL::Cell *inv_cell = module->addCell(NEW_ID, "$_NOT_"); + inv_cell->setPort("\\A", grp[0].bit); + inv_cell->setPort("\\Y", inv_sig); } module->connect(RTLIL::SigSig(grp[i].bit, inv_sig)); @@ -760,7 +760,7 @@ struct FreduceWorker struct FreducePass : public Pass { FreducePass() : Pass("freduce", "perform functional reduction") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -791,7 +791,7 @@ struct FreducePass : public Pass { log("circuit that is analyzed.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { reduce_counter = 0; reduce_stop_at = 0; @@ -828,8 +828,10 @@ struct FreducePass : public Pass { extra_args(args, argidx, design); int bitcount = 0; - for (auto module : design->selected_modules()) { - bitcount += FreduceWorker(design, module).run(); + for (auto &mod_it : design->modules_) { + RTLIL::Module *module = mod_it.second; + if (design->selected(module)) + bitcount += FreduceWorker(design, module).run(); } log("Rewired a total of %d signal bits.\n", bitcount); diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc index fe4a819f329..49ef4006156 100644 --- a/passes/sat/miter.cc +++ b/passes/sat/miter.cc @@ -66,48 +66,50 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: RTLIL::IdString gate_name = RTLIL::escape_id(args[argidx++]); RTLIL::IdString miter_name = RTLIL::escape_id(args[argidx++]); - if (design->module(gold_name) == nullptr) + if (design->modules_.count(gold_name) == 0) log_cmd_error("Can't find gold module %s!\n", gold_name.c_str()); - if (design->module(gate_name) == nullptr) + if (design->modules_.count(gate_name) == 0) log_cmd_error("Can't find gate module %s!\n", gate_name.c_str()); - if (design->module(miter_name) != nullptr) + if (design->modules_.count(miter_name) != 0) log_cmd_error("There is already a module %s!\n", miter_name.c_str()); - RTLIL::Module *gold_module = design->module(gold_name); - RTLIL::Module *gate_module = design->module(gate_name); + RTLIL::Module *gold_module = design->modules_.at(gold_name); + RTLIL::Module *gate_module = design->modules_.at(gate_name); - for (auto gold_wire : gold_module->wires()) { - if (gold_wire->port_id == 0) + for (auto &it : gold_module->wires_) { + RTLIL::Wire *w1 = it.second, *w2; + if (w1->port_id == 0) continue; - RTLIL::Wire *gate_wire = gate_module->wire(gold_wire->name); - if (gate_wire == nullptr) + if (gate_module->wires_.count(it.second->name) == 0) goto match_gold_port_error; - if (gold_wire->port_input != gate_wire->port_input) + w2 = gate_module->wires_.at(it.second->name); + if (w1->port_input != w2->port_input) goto match_gold_port_error; - if (gold_wire->port_output != gate_wire->port_output) + if (w1->port_output != w2->port_output) goto match_gold_port_error; - if (gold_wire->width != gate_wire->width) + if (w1->width != w2->width) goto match_gold_port_error; continue; match_gold_port_error: - log_cmd_error("No matching port in gate module was found for %s!\n", gold_wire->name.c_str()); + log_cmd_error("No matching port in gate module was found for %s!\n", it.second->name.c_str()); } - for (auto gate_wire : gate_module->wires()) { - if (gate_wire->port_id == 0) + for (auto &it : gate_module->wires_) { + RTLIL::Wire *w1 = it.second, *w2; + if (w1->port_id == 0) continue; - RTLIL::Wire *gold_wire = gold_module->wire(gate_wire->name); - if (gold_wire == nullptr) + if (gold_module->wires_.count(it.second->name) == 0) goto match_gate_port_error; - if (gate_wire->port_input != gold_wire->port_input) + w2 = gold_module->wires_.at(it.second->name); + if (w1->port_input != w2->port_input) goto match_gate_port_error; - if (gate_wire->port_output != gold_wire->port_output) + if (w1->port_output != w2->port_output) goto match_gate_port_error; - if (gate_wire->width != gold_wire->width) + if (w1->width != w2->width) goto match_gate_port_error; continue; match_gate_port_error: - log_cmd_error("No matching port in gold module was found for %s!\n", gate_wire->name.c_str()); + log_cmd_error("No matching port in gold module was found for %s!\n", it.second->name.c_str()); } log("Creating miter cell \"%s\" with gold cell \"%s\" and gate cell \"%s\".\n", RTLIL::id2cstr(miter_name), RTLIL::id2cstr(gold_name), RTLIL::id2cstr(gate_name)); @@ -116,101 +118,103 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: miter_module->name = miter_name; design->add(miter_module); - RTLIL::Cell *gold_cell = miter_module->addCell(ID(gold), gold_name); - RTLIL::Cell *gate_cell = miter_module->addCell(ID(gate), gate_name); + RTLIL::Cell *gold_cell = miter_module->addCell("\\gold", gold_name); + RTLIL::Cell *gate_cell = miter_module->addCell("\\gate", gate_name); RTLIL::SigSpec all_conditions; - for (auto gold_wire : gold_module->wires()) + for (auto &it : gold_module->wires_) { - if (gold_wire->port_input) + RTLIL::Wire *w1 = it.second; + + if (w1->port_input) { - RTLIL::Wire *w = miter_module->addWire("\\in_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width); - w->port_input = true; + RTLIL::Wire *w2 = miter_module->addWire("\\in_" + RTLIL::unescape_id(w1->name), w1->width); + w2->port_input = true; - gold_cell->setPort(gold_wire->name, w); - gate_cell->setPort(gold_wire->name, w); + gold_cell->setPort(w1->name, w2); + gate_cell->setPort(w1->name, w2); } - if (gold_wire->port_output) + if (w1->port_output) { - RTLIL::Wire *w_gold = miter_module->addWire("\\gold_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width); - w_gold->port_output = flag_make_outputs; + RTLIL::Wire *w2_gold = miter_module->addWire("\\gold_" + RTLIL::unescape_id(w1->name), w1->width); + w2_gold->port_output = flag_make_outputs; - RTLIL::Wire *w_gate = miter_module->addWire("\\gate_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width); - w_gate->port_output = flag_make_outputs; + RTLIL::Wire *w2_gate = miter_module->addWire("\\gate_" + RTLIL::unescape_id(w1->name), w1->width); + w2_gate->port_output = flag_make_outputs; - gold_cell->setPort(gold_wire->name, w_gold); - gate_cell->setPort(gold_wire->name, w_gate); + gold_cell->setPort(w1->name, w2_gold); + gate_cell->setPort(w1->name, w2_gate); RTLIL::SigSpec this_condition; if (flag_ignore_gold_x) { - RTLIL::SigSpec gold_x = miter_module->addWire(NEW_ID, w_gold->width); - for (int i = 0; i < w_gold->width; i++) { - RTLIL::Cell *eqx_cell = miter_module->addCell(NEW_ID, ID($eqx)); - eqx_cell->parameters[ID::A_WIDTH] = 1; - eqx_cell->parameters[ID::B_WIDTH] = 1; - eqx_cell->parameters[ID::Y_WIDTH] = 1; - eqx_cell->parameters[ID::A_SIGNED] = 0; - eqx_cell->parameters[ID::B_SIGNED] = 0; - eqx_cell->setPort(ID::A, RTLIL::SigSpec(w_gold, i)); - eqx_cell->setPort(ID::B, RTLIL::State::Sx); - eqx_cell->setPort(ID::Y, gold_x.extract(i, 1)); + RTLIL::SigSpec gold_x = miter_module->addWire(NEW_ID, w2_gold->width); + for (int i = 0; i < w2_gold->width; i++) { + RTLIL::Cell *eqx_cell = miter_module->addCell(NEW_ID, "$eqx"); + eqx_cell->parameters["\\A_WIDTH"] = 1; + eqx_cell->parameters["\\B_WIDTH"] = 1; + eqx_cell->parameters["\\Y_WIDTH"] = 1; + eqx_cell->parameters["\\A_SIGNED"] = 0; + eqx_cell->parameters["\\B_SIGNED"] = 0; + eqx_cell->setPort("\\A", RTLIL::SigSpec(w2_gold, i)); + eqx_cell->setPort("\\B", RTLIL::State::Sx); + eqx_cell->setPort("\\Y", gold_x.extract(i, 1)); } - RTLIL::SigSpec gold_masked = miter_module->addWire(NEW_ID, w_gold->width); - RTLIL::SigSpec gate_masked = miter_module->addWire(NEW_ID, w_gate->width); - - RTLIL::Cell *or_gold_cell = miter_module->addCell(NEW_ID, ID($or)); - or_gold_cell->parameters[ID::A_WIDTH] = w_gold->width; - or_gold_cell->parameters[ID::B_WIDTH] = w_gold->width; - or_gold_cell->parameters[ID::Y_WIDTH] = w_gold->width; - or_gold_cell->parameters[ID::A_SIGNED] = 0; - or_gold_cell->parameters[ID::B_SIGNED] = 0; - or_gold_cell->setPort(ID::A, w_gold); - or_gold_cell->setPort(ID::B, gold_x); - or_gold_cell->setPort(ID::Y, gold_masked); - - RTLIL::Cell *or_gate_cell = miter_module->addCell(NEW_ID, ID($or)); - or_gate_cell->parameters[ID::A_WIDTH] = w_gate->width; - or_gate_cell->parameters[ID::B_WIDTH] = w_gate->width; - or_gate_cell->parameters[ID::Y_WIDTH] = w_gate->width; - or_gate_cell->parameters[ID::A_SIGNED] = 0; - or_gate_cell->parameters[ID::B_SIGNED] = 0; - or_gate_cell->setPort(ID::A, w_gate); - or_gate_cell->setPort(ID::B, gold_x); - or_gate_cell->setPort(ID::Y, gate_masked); - - RTLIL::Cell *eq_cell = miter_module->addCell(NEW_ID, ID($eqx)); - eq_cell->parameters[ID::A_WIDTH] = w_gold->width; - eq_cell->parameters[ID::B_WIDTH] = w_gate->width; - eq_cell->parameters[ID::Y_WIDTH] = 1; - eq_cell->parameters[ID::A_SIGNED] = 0; - eq_cell->parameters[ID::B_SIGNED] = 0; - eq_cell->setPort(ID::A, gold_masked); - eq_cell->setPort(ID::B, gate_masked); - eq_cell->setPort(ID::Y, miter_module->addWire(NEW_ID)); - this_condition = eq_cell->getPort(ID::Y); + RTLIL::SigSpec gold_masked = miter_module->addWire(NEW_ID, w2_gold->width); + RTLIL::SigSpec gate_masked = miter_module->addWire(NEW_ID, w2_gate->width); + + RTLIL::Cell *or_gold_cell = miter_module->addCell(NEW_ID, "$or"); + or_gold_cell->parameters["\\A_WIDTH"] = w2_gold->width; + or_gold_cell->parameters["\\B_WIDTH"] = w2_gold->width; + or_gold_cell->parameters["\\Y_WIDTH"] = w2_gold->width; + or_gold_cell->parameters["\\A_SIGNED"] = 0; + or_gold_cell->parameters["\\B_SIGNED"] = 0; + or_gold_cell->setPort("\\A", w2_gold); + or_gold_cell->setPort("\\B", gold_x); + or_gold_cell->setPort("\\Y", gold_masked); + + RTLIL::Cell *or_gate_cell = miter_module->addCell(NEW_ID, "$or"); + or_gate_cell->parameters["\\A_WIDTH"] = w2_gate->width; + or_gate_cell->parameters["\\B_WIDTH"] = w2_gate->width; + or_gate_cell->parameters["\\Y_WIDTH"] = w2_gate->width; + or_gate_cell->parameters["\\A_SIGNED"] = 0; + or_gate_cell->parameters["\\B_SIGNED"] = 0; + or_gate_cell->setPort("\\A", w2_gate); + or_gate_cell->setPort("\\B", gold_x); + or_gate_cell->setPort("\\Y", gate_masked); + + RTLIL::Cell *eq_cell = miter_module->addCell(NEW_ID, "$eqx"); + eq_cell->parameters["\\A_WIDTH"] = w2_gold->width; + eq_cell->parameters["\\B_WIDTH"] = w2_gate->width; + eq_cell->parameters["\\Y_WIDTH"] = 1; + eq_cell->parameters["\\A_SIGNED"] = 0; + eq_cell->parameters["\\B_SIGNED"] = 0; + eq_cell->setPort("\\A", gold_masked); + eq_cell->setPort("\\B", gate_masked); + eq_cell->setPort("\\Y", miter_module->addWire(NEW_ID)); + this_condition = eq_cell->getPort("\\Y"); } else { - RTLIL::Cell *eq_cell = miter_module->addCell(NEW_ID, ID($eqx)); - eq_cell->parameters[ID::A_WIDTH] = w_gold->width; - eq_cell->parameters[ID::B_WIDTH] = w_gate->width; - eq_cell->parameters[ID::Y_WIDTH] = 1; - eq_cell->parameters[ID::A_SIGNED] = 0; - eq_cell->parameters[ID::B_SIGNED] = 0; - eq_cell->setPort(ID::A, w_gold); - eq_cell->setPort(ID::B, w_gate); - eq_cell->setPort(ID::Y, miter_module->addWire(NEW_ID)); - this_condition = eq_cell->getPort(ID::Y); + RTLIL::Cell *eq_cell = miter_module->addCell(NEW_ID, "$eqx"); + eq_cell->parameters["\\A_WIDTH"] = w2_gold->width; + eq_cell->parameters["\\B_WIDTH"] = w2_gate->width; + eq_cell->parameters["\\Y_WIDTH"] = 1; + eq_cell->parameters["\\A_SIGNED"] = 0; + eq_cell->parameters["\\B_SIGNED"] = 0; + eq_cell->setPort("\\A", w2_gold); + eq_cell->setPort("\\B", w2_gate); + eq_cell->setPort("\\Y", miter_module->addWire(NEW_ID)); + this_condition = eq_cell->getPort("\\Y"); } if (flag_make_outcmp) { - RTLIL::Wire *w_cmp = miter_module->addWire("\\cmp_" + RTLIL::unescape_id(gold_wire->name)); + RTLIL::Wire *w_cmp = miter_module->addWire("\\cmp_" + RTLIL::unescape_id(w1->name)); w_cmp->port_output = true; miter_module->connect(RTLIL::SigSig(w_cmp, this_condition)); } @@ -220,31 +224,31 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: } if (all_conditions.size() != 1) { - RTLIL::Cell *reduce_cell = miter_module->addCell(NEW_ID, ID($reduce_and)); - reduce_cell->parameters[ID::A_WIDTH] = all_conditions.size(); - reduce_cell->parameters[ID::Y_WIDTH] = 1; - reduce_cell->parameters[ID::A_SIGNED] = 0; - reduce_cell->setPort(ID::A, all_conditions); - reduce_cell->setPort(ID::Y, miter_module->addWire(NEW_ID)); - all_conditions = reduce_cell->getPort(ID::Y); + RTLIL::Cell *reduce_cell = miter_module->addCell(NEW_ID, "$reduce_and"); + reduce_cell->parameters["\\A_WIDTH"] = all_conditions.size(); + reduce_cell->parameters["\\Y_WIDTH"] = 1; + reduce_cell->parameters["\\A_SIGNED"] = 0; + reduce_cell->setPort("\\A", all_conditions); + reduce_cell->setPort("\\Y", miter_module->addWire(NEW_ID)); + all_conditions = reduce_cell->getPort("\\Y"); } if (flag_make_assert) { - RTLIL::Cell *assert_cell = miter_module->addCell(NEW_ID, ID($assert)); - assert_cell->setPort(ID::A, all_conditions); - assert_cell->setPort(ID::EN, State::S1); + RTLIL::Cell *assert_cell = miter_module->addCell(NEW_ID, "$assert"); + assert_cell->setPort("\\A", all_conditions); + assert_cell->setPort("\\EN", State::S1); } - RTLIL::Wire *w_trigger = miter_module->addWire(ID(trigger)); + RTLIL::Wire *w_trigger = miter_module->addWire("\\trigger"); w_trigger->port_output = true; - RTLIL::Cell *not_cell = miter_module->addCell(NEW_ID, ID($not)); - not_cell->parameters[ID::A_WIDTH] = all_conditions.size(); - not_cell->parameters[ID::A_WIDTH] = all_conditions.size(); - not_cell->parameters[ID::Y_WIDTH] = w_trigger->width; - not_cell->parameters[ID::A_SIGNED] = 0; - not_cell->setPort(ID::A, all_conditions); - not_cell->setPort(ID::Y, w_trigger); + RTLIL::Cell *not_cell = miter_module->addCell(NEW_ID, "$not"); + not_cell->parameters["\\A_WIDTH"] = all_conditions.size(); + not_cell->parameters["\\A_WIDTH"] = all_conditions.size(); + not_cell->parameters["\\Y_WIDTH"] = w_trigger->width; + not_cell->parameters["\\A_SIGNED"] = 0; + not_cell->setPort("\\A", all_conditions); + not_cell->setPort("\\Y", w_trigger); miter_module->fixup_ports(); @@ -281,9 +285,9 @@ void create_miter_assert(struct Pass *that, std::vector args, RTLIL IdString module_name = RTLIL::escape_id(args[argidx++]); IdString miter_name = argidx < args.size() ? RTLIL::escape_id(args[argidx++]) : ""; - if (design->module(module_name) == nullptr) + if (design->modules_.count(module_name) == 0) log_cmd_error("Can't find module %s!\n", module_name.c_str()); - if (!miter_name.empty() && design->module(miter_name) != nullptr) + if (!miter_name.empty() && design->modules_.count(miter_name) != 0) log_cmd_error("There is already a module %s!\n", miter_name.c_str()); Module *module = design->module(module_name); @@ -298,7 +302,7 @@ void create_miter_assert(struct Pass *that, std::vector args, RTLIL for (auto wire : module->wires()) wire->port_output = false; - Wire *trigger = module->addWire(ID(trigger)); + Wire *trigger = module->addWire("\\trigger"); trigger->port_output = true; module->fixup_ports(); @@ -312,13 +316,13 @@ void create_miter_assert(struct Pass *that, std::vector args, RTLIL vector cell_list = module->cells(); for (auto cell : cell_list) { - if (!cell->type.in(ID($assert), ID($assume))) + if (!cell->type.in("$assert", "$assume")) continue; - SigBit is_active = module->Nex(NEW_ID, cell->getPort(ID::A), State::S1); - SigBit is_enabled = module->Eqx(NEW_ID, cell->getPort(ID::EN), State::S1); + SigBit is_active = module->Nex(NEW_ID, cell->getPort("\\A"), State::S1); + SigBit is_enabled = module->Eqx(NEW_ID, cell->getPort("\\EN"), State::S1); - if (cell->type == ID($assert)) { + if (cell->type == "$assert") { assert_signals.append(module->And(NEW_ID, is_active, is_enabled)); } else { assume_signals.append(module->And(NEW_ID, is_active, is_enabled)); @@ -334,7 +338,7 @@ void create_miter_assert(struct Pass *that, std::vector args, RTLIL else { Wire *assume_q = module->addWire(NEW_ID); - assume_q->attributes[ID::init] = State::S0; + assume_q->attributes["\\init"] = State::S0; assume_signals.append(assume_q); SigSpec assume_nok = module->ReduceOr(NEW_ID, assume_signals); @@ -354,7 +358,7 @@ void create_miter_assert(struct Pass *that, std::vector args, RTLIL struct MiterPass : public Pass { MiterPass() : Pass("miter", "automatically create a miter circuit") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -398,7 +402,7 @@ struct MiterPass : public Pass { log(" call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { if (args.size() > 1 && args[1] == "-equiv") { create_miter_equiv(this, args, design); diff --git a/passes/sat/mutate.cc b/passes/sat/mutate.cc index 15abee73ed4..b53bbfeb2d1 100644 --- a/passes/sat/mutate.cc +++ b/passes/sat/mutate.cc @@ -439,7 +439,7 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena dict bit_user_cnt; for (auto wire : module->wires()) { - if (wire->name[0] == '\\' && wire->attributes.count(ID::src)) + if (wire->name[0] == '\\' && wire->attributes.count("\\src")) sigmap.add(wire); } @@ -489,12 +489,12 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena entry.port = conn.first; entry.portbit = i; - for (auto &s : cell->get_strpool_attribute(ID::src)) + for (auto &s : cell->get_strpool_attribute("\\src")) entry.src.insert(s); SigBit bit = sigmap(conn.second[i]); if (bit.wire && bit.wire->name[0] == '\\' && (cell->output(conn.first) || bit_user_cnt[bit] == 1)) { - for (auto &s : bit.wire->get_strpool_attribute(ID::src)) + for (auto &s : bit.wire->get_strpool_attribute("\\src")) entry.src.insert(s); entry.wire = bit.wire->name; entry.wirebit = bit.offset; @@ -726,7 +726,7 @@ void mutate_cnot(Design *design, const mutate_opts_t &opts, bool one) struct MutatePass : public Pass { MutatePass() : Pass("mutate", "generate or apply design mutations") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -790,7 +790,7 @@ struct MutatePass : public Pass { log(" Ignored. (They are generated by -list for documentation purposes.)\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { mutate_opts_t opts; string filename; diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc deleted file mode 100644 index f4624ab3bb7..00000000000 --- a/passes/sat/qbfsat.cc +++ /dev/null @@ -1,798 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 Alberto Gonzalez - * - * 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/celltypes.h" -#include "kernel/consteval.h" -#include "kernel/log.h" -#include "kernel/rtlil.h" -#include "kernel/register.h" -#include -#include - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -static inline unsigned int difference(unsigned int a, unsigned int b) { - if (a < b) - return b - a; - else - return a - b; -} - -struct QbfSolutionType { - std::vector stdout_lines; - dict, std::string> hole_to_value; - double solver_time; - bool sat; - bool unknown; //true if neither 'sat' nor 'unsat' - - QbfSolutionType() : solver_time(0.0), sat(false), unknown(true) {} -}; - -struct QbfSolveOptions { - bool specialize, specialize_from_file, write_solution, nocleanup, dump_final_smt2, assume_outputs, assume_neg; - bool nooptimize, nobisection; - bool sat, unsat, show_smtbmc; - enum Solver{Z3, Yices, CVC4} solver; - int timeout; - std::string specialize_soln_file; - std::string write_soln_soln_file; - std::string dump_final_smt2_file; - size_t argidx; - QbfSolveOptions() : specialize(false), specialize_from_file(false), write_solution(false), - nocleanup(false), dump_final_smt2(false), assume_outputs(false), assume_neg(false), - nooptimize(false), nobisection(false), sat(false), unsat(false), show_smtbmc(false), - solver(Yices), timeout(0), argidx(0) {}; -}; - -std::string get_solver_name(const QbfSolveOptions &opt) { - if (opt.solver == opt.Solver::Z3) - return "z3"; - else if (opt.solver == opt.Solver::Yices) - return "yices"; - else if (opt.solver == opt.Solver::CVC4) - return "cvc4"; - else - log_cmd_error("unknown solver specified.\n"); - return ""; -} - -void recover_solution(QbfSolutionType &sol) { - YS_REGEX_TYPE sat_regex = YS_REGEX_COMPILE("Status: PASSED"); - YS_REGEX_TYPE unsat_regex = YS_REGEX_COMPILE("Solver Error.*model is not available"); - YS_REGEX_TYPE unsat_regex2 = YS_REGEX_COMPILE("Status: FAILED"); - YS_REGEX_TYPE timeout_regex = YS_REGEX_COMPILE("No solution found! \\(timeout\\)"); - YS_REGEX_TYPE timeout_regex2 = YS_REGEX_COMPILE("No solution found! \\(interrupted\\)"); - YS_REGEX_TYPE unknown_regex = YS_REGEX_COMPILE("No solution found! \\(unknown\\)"); - YS_REGEX_TYPE unknown_regex2 = YS_REGEX_COMPILE("Unexpected EOF response from solver"); - YS_REGEX_TYPE memout_regex = YS_REGEX_COMPILE("Solver Error:.*error \"out of memory\""); - YS_REGEX_TYPE hole_value_regex = YS_REGEX_COMPILE_WITH_SUBS("Value for anyconst in [a-zA-Z0-9_]* \\(([^:]*:[^\\)]*)\\): (.*)"); -#ifndef NDEBUG - YS_REGEX_TYPE hole_loc_regex = YS_REGEX_COMPILE("[^:]*:[0-9]+.[0-9]+-[0-9]+.[0-9]+"); - YS_REGEX_TYPE hole_val_regex = YS_REGEX_COMPILE("[0-9]+"); -#endif - YS_REGEX_MATCH_TYPE m; - bool sat_regex_found = false; - bool unsat_regex_found = false; - dict hole_value_recovered; - for (const std::string &x : sol.stdout_lines) { - if(YS_REGEX_NS::regex_search(x, m, hole_value_regex)) { - std::string loc = m[1].str(); - std::string val = m[2].str(); -#ifndef NDEBUG - log_assert(YS_REGEX_NS::regex_search(loc, hole_loc_regex)); - log_assert(YS_REGEX_NS::regex_search(val, hole_val_regex)); -#endif - auto locs = split_tokens(loc, "|"); - pool loc_pool(locs.begin(), locs.end()); - sol.hole_to_value[loc_pool] = val; - } - else if (YS_REGEX_NS::regex_search(x, sat_regex)) { - sat_regex_found = true; - sol.sat = true; - sol.unknown = false; - } - else if (YS_REGEX_NS::regex_search(x, unsat_regex)) { - unsat_regex_found = true; - sol.sat = false; - sol.unknown = false; - } - else if (YS_REGEX_NS::regex_search(x, memout_regex)) { - sol.unknown = true; - log_warning("solver ran out of memory\n"); - } - else if (YS_REGEX_NS::regex_search(x, timeout_regex)) { - sol.unknown = true; - log_warning("solver timed out\n"); - } - else if (YS_REGEX_NS::regex_search(x, timeout_regex2)) { - sol.unknown = true; - log_warning("solver timed out\n"); - } - else if (YS_REGEX_NS::regex_search(x, unknown_regex)) { - sol.unknown = true; - log_warning("solver returned \"unknown\"\n"); - } - else if (YS_REGEX_NS::regex_search(x, unsat_regex2)) { - unsat_regex_found = true; - sol.sat = false; - sol.unknown = false; - } - else if (YS_REGEX_NS::regex_search(x, unknown_regex2)) { - sol.unknown = true; - } - } -#ifndef NDEBUG - log_assert(!sol.unknown && sol.sat? sat_regex_found : true); - log_assert(!sol.unknown && !sol.sat? unsat_regex_found : true); -#endif -} - -dict, int>, RTLIL::SigBit> get_hole_loc_idx_sigbit_map(RTLIL::Module *module, const QbfSolutionType &sol) { - dict, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit; - for (auto cell : module->cells()) { - pool cell_src = cell->get_strpool_attribute(ID::src); - auto pos = sol.hole_to_value.find(cell_src); - if (pos != sol.hole_to_value.end() && cell->type.in("$anyconst", "$anyseq")) { - RTLIL::SigSpec port_y = cell->getPort(ID::Y); - for (int i = GetSize(port_y) - 1; i >= 0; --i) { - hole_loc_idx_to_sigbit[std::make_pair(pos->first, i)] = port_y[i]; - } - } - } - - return hole_loc_idx_to_sigbit; -} - -pool validate_design_and_get_inputs(RTLIL::Module *module, const QbfSolveOptions &opt) { - bool found_input = false; - bool found_hole = false; - bool found_1bit_output = false; - bool found_assert_assume = false; - pool input_wires; - for (auto wire : module->wires()) { - if (wire->port_input) { - found_input = true; - input_wires.insert(wire->name.str()); - } - if (wire->port_output && wire->width == 1) - found_1bit_output = true; - } - for (auto cell : module->cells()) { - if (cell->type == "$allconst") - found_input = true; - if (cell->type == "$anyconst") - found_hole = true; - if (cell->type.in("$assert", "$assume")) - found_assert_assume = true; - } - if (!found_input) - log_cmd_error("Can't perform QBF-SAT on a miter with no inputs!\n"); - if (!found_hole) - log_cmd_error("Did not find any existentially-quantified variables. Use 'sat' instead.\n"); - if (!found_1bit_output && !found_assert_assume) - log_cmd_error("Did not find any single-bit outputs or $assert/$assume cells. Is this a miter circuit?\n"); - if (!found_assert_assume && !opt.assume_outputs) - log_cmd_error("Did not find any $assert/$assume cells. Single-bit outputs were found, but `-assume-outputs` was not specified.\n"); - - return input_wires; -} - -void write_solution(RTLIL::Module *module, const QbfSolutionType &sol, const std::string &file) { - std::ofstream fout(file.c_str()); - if (!fout) - log_cmd_error("could not open solution file for writing.\n"); - - //There is a question here: How exactly shall we identify holes? - //There are at least two reasonable options: - //1. By the source location of the $anyconst cells - //2. By the name(s) of the wire(s) connected to each SigBit of the $anyconst cell->getPort(ID::Y) SigSpec. - // - //Option 1 has the benefit of being very precise. There is very limited potential for confusion, as long - //as the source attribute has been set. However, if the source attribute is not set, this won't work. - //More importantly, we want to have the ability to port hole assignments to other modules with compatible - //hole names and widths. Obviously in those cases source locations of the $anyconst cells will not match. - // - //Option 2 has the benefits previously described, but wire names can be changed automatically by - //optimization or techmapping passes, especially when (ex/im)porting from BLIF for optimization with ABC. - // - //The approach taken here is to allow both options. We write the assignment information for each bit of - //the solution on a separate line. Each line is of one of two forms: - // - //location bit name = value - //location bit name [offset] = value - // - //where '[', ']', and '=' are literal symbols, "location" is the $anyconst cell source location attribute, - //"bit" is the index of the $anyconst cell, "name" is the `wire->name` field of the SigBit corresponding - //to the current bit of the $anyconst cell->getPort(ID::Y), "offset" is the `offset` field of that same - //SigBit, and "value", which is either '0' or '1', represents the assignment for that bit. - dict, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module, sol); - for (auto &x : sol.hole_to_value) { - std::string src_as_str = std::accumulate(x.first.begin(), x.first.end(), std::string(), [](const std::string &a, const std::string &b){return a + "|" + b;}); - for (auto i = 0; i < GetSize(x.second); ++i) - fout << src_as_str.c_str() << " " << i << " " << log_signal(hole_loc_idx_to_sigbit[std::make_pair(x.first, i)]) << " = " << x.second[GetSize(x.second) - 1 - i] << std::endl; - } -} - -void specialize_from_file(RTLIL::Module *module, const std::string &file) { - YS_REGEX_TYPE hole_bit_assn_regex = YS_REGEX_COMPILE_WITH_SUBS("^(.+) ([0-9]+) ([^ ]+) \\[([0-9]+)] = ([01])$"); - YS_REGEX_TYPE hole_assn_regex = YS_REGEX_COMPILE_WITH_SUBS("^(.+) ([0-9]+) ([^ ]+) = ([01])$"); //if no index specified - YS_REGEX_MATCH_TYPE bit_m, m; - //(hole_loc, hole_bit, hole_name, hole_offset) -> (value, found) - dict, RTLIL::Cell*> anyconst_loc_to_cell; - dict hole_assignments; - - for (auto cell : module->cells()) - if (cell->type == "$anyconst") - anyconst_loc_to_cell[cell->get_strpool_attribute(ID::src)] = cell; - - std::ifstream fin(file.c_str()); - if (!fin) - log_cmd_error("could not read solution file.\n"); - - std::string buf; - while (std::getline(fin, buf)) { - bool bit_assn = true; - if (!YS_REGEX_NS::regex_search(buf, bit_m, hole_bit_assn_regex)) { - bit_assn = false; - if (!YS_REGEX_NS::regex_search(buf, m, hole_assn_regex)) - log_cmd_error("solution file is not formatted correctly: \"%s\"\n", buf.c_str()); - } - - std::string hole_loc = bit_assn? bit_m[1].str() : m[1].str(); - unsigned int hole_bit = bit_assn? atoi(bit_m[2].str().c_str()) : atoi(m[2].str().c_str()); - std::string hole_name = bit_assn? bit_m[3].str() : m[3].str(); - unsigned int hole_offset = bit_assn? atoi(bit_m[4].str().c_str()) : 0; - RTLIL::State hole_value = bit_assn? (atoi(bit_m[5].str().c_str()) == 1? RTLIL::State::S1 : RTLIL::State::S0) - : (atoi(m[4].str().c_str()) == 1? RTLIL::State::S1 : RTLIL::State::S0); - - //We have two options to identify holes. First, try to match wire names. If we can't find a matching wire, - //then try to find a cell with a matching location. - RTLIL::SigBit hole_sigbit; - if (module->wire(hole_name) != nullptr) { - RTLIL::Wire *hole_wire = module->wire(hole_name); - hole_sigbit = RTLIL::SigSpec(hole_wire)[hole_offset]; - } else { - auto locs = split_tokens(hole_loc, "|"); - pool hole_loc_pool(locs.begin(), locs.end()); - auto hole_cell_it = anyconst_loc_to_cell.find(hole_loc_pool); - if (hole_cell_it == anyconst_loc_to_cell.end()) - YS_DEBUGTRAP; - //log_cmd_error("cannot find matching wire name or $anyconst cell location for hole spec \"%s\"\n", buf.c_str()); - - RTLIL::Cell *hole_cell = hole_cell_it->second; - hole_sigbit = hole_cell->getPort(ID::Y)[hole_bit]; - } - hole_assignments[hole_sigbit] = hole_value; - } - - for (auto &it : anyconst_loc_to_cell) - module->remove(it.second); - - for (auto &it : hole_assignments) { - RTLIL::SigSpec lhs(it.first); - RTLIL::SigSpec rhs(it.second); - log("Specializing %s from file with %s = %d.\n", module->name.c_str(), log_signal(it.first), it.second == RTLIL::State::S1? 1 : 0); - module->connect(lhs, rhs); - } -} - -void specialize(RTLIL::Module *module, const QbfSolutionType &sol, bool quiet = false) { - dict, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module, sol); - pool anyconsts_to_remove; - for (auto cell : module->cells()) - if (cell->type == "$anyconst") - if (hole_loc_idx_to_sigbit.find(std::make_pair(cell->get_strpool_attribute(ID::src), 0)) != hole_loc_idx_to_sigbit.end()) - anyconsts_to_remove.insert(cell); - for (auto cell : anyconsts_to_remove) - module->remove(cell); - for (auto &it : sol.hole_to_value) { - pool hole_loc = it.first; - std::string hole_value = it.second; - - for (unsigned int i = 0; i < hole_value.size(); ++i) { - int bit_idx = GetSize(hole_value) - 1 - i; - auto it = hole_loc_idx_to_sigbit.find(std::make_pair(hole_loc, i)); - log_assert(it != hole_loc_idx_to_sigbit.end()); - - RTLIL::SigBit hole_sigbit = it->second; - log_assert(hole_sigbit.wire != nullptr); - log_assert(hole_value[bit_idx] == '0' || hole_value[bit_idx] == '1'); - RTLIL::SigSpec lhs(hole_sigbit.wire, hole_sigbit.offset, 1); - RTLIL::State hole_bit_val = hole_value[bit_idx] == '1'? RTLIL::State::S1 : RTLIL::State::S0; - if (!quiet) - log("Specializing %s with %s = %d.\n", module->name.c_str(), log_signal(hole_sigbit), hole_bit_val == RTLIL::State::S0? 0 : 1) -; - module->connect(lhs, hole_bit_val); - } - } -} - -void dump_model(RTLIL::Module *module, const QbfSolutionType &sol) { - log("Satisfiable model:\n"); - dict, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module, sol); - for (auto &it : sol.hole_to_value) { - pool hole_loc = it.first; - std::string hole_value = it.second; - - for (unsigned int i = 0; i < hole_value.size(); ++i) { - int bit_idx = GetSize(hole_value) - 1 - i; - auto it = hole_loc_idx_to_sigbit.find(std::make_pair(hole_loc, i)); - log_assert(it != hole_loc_idx_to_sigbit.end()); - - RTLIL::SigBit hole_sigbit = it->second; - log("\t%s = 1'b%c\n", log_signal(hole_sigbit), hole_value[bit_idx]); - } - } -} - -void allconstify_inputs(RTLIL::Module *module, const pool &input_wires) { - for (auto &n : input_wires) { - RTLIL::Wire *input = module->wire(n); -#ifndef NDEBUG - log_assert(input != nullptr); -#endif - - RTLIL::Cell *allconst = module->addCell("$allconst$" + n, "$allconst"); - allconst->setParam(ID(WIDTH), input->width); - allconst->setPort(ID::Y, input); - allconst->set_src_attribute(input->get_src_attribute()); - input->port_input = false; - log("Replaced input %s with $allconst cell.\n", n.c_str()); - } - module->fixup_ports(); -} - -void assume_miter_outputs(RTLIL::Module *module, const QbfSolveOptions &opt) { - std::vector wires_to_assume; - for (auto w : module->wires()) - if (w->port_output && w->width == 1) - wires_to_assume.push_back(w); - - if (wires_to_assume.size() == 0) - return; - else { - log("Adding $assume cell for output(s): "); - for (auto w : wires_to_assume) - log("\"%s\" ", w->name.c_str()); - log("\n"); - } - - if (opt.assume_neg) { - for (unsigned int i = 0; i < wires_to_assume.size(); ++i) { - RTLIL::SigSpec n_wire = module->LogicNot(wires_to_assume[i]->name.str() + "__n__qbfsat", wires_to_assume[i], false, wires_to_assume[i]->get_src_attribute()); - wires_to_assume[i] = n_wire.as_wire(); - } - } - - for (auto i = 0; wires_to_assume.size() > 1; ++i) { - std::vector buf; - for (auto j = 0; j + 1 < GetSize(wires_to_assume); j += 2) { - std::stringstream strstr; strstr << i << "_" << j; - RTLIL::Wire *and_wire = module->addWire("\\_qbfsat_and_" + strstr.str(), 1); - module->addLogicAnd("$_qbfsat_and_" + strstr.str(), wires_to_assume[j], wires_to_assume[j+1], and_wire, false, wires_to_assume[j]->get_src_attribute()); - buf.push_back(and_wire); - } - if (wires_to_assume.size() % 2 == 1) - buf.push_back(wires_to_assume[wires_to_assume.size() - 1]); - wires_to_assume.swap(buf); - } - -#ifndef NDEBUG - log_assert(wires_to_assume.size() == 1); -#endif - module->addAssume("$assume_qbfsat_miter_outputs", wires_to_assume[0], RTLIL::S1); -} - -QbfSolutionType call_qbf_solver(RTLIL::Module *mod, const QbfSolveOptions &opt, const std::string &tempdir_name, const bool quiet = false, const int iter_num = 0) { - //Execute and capture stdout from `yosys-smtbmc -s z3 -t 1 -g --binary [--dump-smt2 ]` - QbfSolutionType ret; - const std::string yosys_smtbmc_exe = proc_self_dirname() + "yosys-smtbmc"; - const std::string smt2_command = "write_smt2 -stbv -wires " + tempdir_name + "/problem" + (iter_num != 0? stringf("%d", iter_num) : "") + ".smt2"; - const std::string smtbmc_warning = "z3: WARNING:"; - const std::string smtbmc_cmd = yosys_smtbmc_exe + " -s " + (get_solver_name(opt)) + (opt.timeout != 0? stringf(" --timeout %d", opt.timeout) : "") + " -t 1 -g --binary " + (opt.dump_final_smt2? "--dump-smt2 " + opt.dump_final_smt2_file + " " : "") + tempdir_name + "/problem" + (iter_num != 0? stringf("%d", iter_num) : "") + ".smt2 2>&1"; - - Pass::call(mod->design, smt2_command); - - auto process_line = [&ret, &smtbmc_warning, &opt, &quiet](const std::string &line) { - ret.stdout_lines.push_back(line.substr(0, line.size()-1)); //don't include trailing newline - auto warning_pos = line.find(smtbmc_warning); - if (warning_pos != std::string::npos) - log_warning("%s", line.substr(warning_pos + smtbmc_warning.size() + 1).c_str()); - else - if (opt.show_smtbmc && !quiet) - log("smtbmc output: %s", line.c_str()); - }; - log_header(mod->design, "Solving QBF-SAT problem.\n"); - if (!quiet) log("Launching \"%s\".\n", smtbmc_cmd.c_str()); - int64_t begin = PerformanceTimer::query(); - run_command(smtbmc_cmd, process_line); - int64_t end = PerformanceTimer::query(); - ret.solver_time = (end - begin) / 1e9f; - if (!quiet) log("Solver finished in %.3f seconds.\n", ret.solver_time); - - recover_solution(ret); - return ret; -} - -QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { - QbfSolutionType ret, best_soln; - const std::string tempdir_name = make_temp_dir("/tmp/yosys-z3-XXXXXX"); - RTLIL::Module *module = mod; - RTLIL::Design *design = module->design; - std::string module_name = module->name.str(); - RTLIL::Wire *wire_to_optimize = nullptr; - RTLIL::IdString wire_to_optimize_name; - bool maximize = false; - log_assert(module->design != nullptr); - - Pass::call(design, "design -push-copy"); - - //Replace input wires with wires assigned $allconst cells: - pool input_wires = validate_design_and_get_inputs(module, opt); - allconstify_inputs(module, input_wires); - if (opt.assume_outputs) - assume_miter_outputs(module, opt); - - //Find the wire to be optimized, if any: - for (auto wire : module->wires()) - if (wire->get_bool_attribute("\\maximize") || wire->get_bool_attribute("\\minimize")) - wire_to_optimize = wire; - if (wire_to_optimize != nullptr) { - wire_to_optimize_name = wire_to_optimize->name; - maximize = wire_to_optimize->get_bool_attribute("\\maximize"); - } - - if (opt.nobisection || opt.nooptimize || wire_to_optimize == nullptr) { - if (wire_to_optimize != nullptr && opt.nooptimize) { - wire_to_optimize->set_bool_attribute("\\maximize", false); - wire_to_optimize->set_bool_attribute("\\minimize", false); - } - ret = call_qbf_solver(module, opt, tempdir_name, false, 0); - } else { - //Do the iterated bisection method: - unsigned int iter_num = 1; - unsigned int success = 0; - unsigned int failure = 0; - unsigned int cur_thresh = 0; - - log_assert(wire_to_optimize != nullptr); - log("%s wire \"%s\".\n", (maximize? "Maximizing" : "Minimizing"), log_signal(wire_to_optimize)); - - //If maximizing, grow until we get a failure. Then bisect success and failure. - while (failure == 0 || difference(success, failure) > 1) { - Pass::call(design, "design -push-copy"); - log_header(design, "Preparing QBF-SAT problem.\n"); - - if (cur_thresh != 0) { - //Add thresholding logic (but not on the initial run when we don't have a sense of where to start): - RTLIL::SigSpec comparator = maximize? module->Ge(NEW_ID, module->wire(wire_to_optimize_name), RTLIL::Const(cur_thresh), false) - : module->Le(NEW_ID, module->wire(wire_to_optimize_name), RTLIL::Const(cur_thresh), false); - - module->addAssume(wire_to_optimize_name.str() + "__threshold", comparator, RTLIL::Const(1, 1)); - log("Trying to solve with %s %s %d.\n", wire_to_optimize_name.c_str(), (maximize? ">=" : "<="), cur_thresh); - } - - ret = call_qbf_solver(module, opt, tempdir_name, false, iter_num); - Pass::call(design, "design -pop"); - module = design->module(module_name); - - if (!ret.unknown && ret.sat) { - Pass::call(design, "design -push-copy"); - specialize(module, ret, true); - - RTLIL::SigSpec wire, value, undef; - RTLIL::SigSpec::parse_sel(wire, design, module, wire_to_optimize_name.str()); - - ConstEval ce(module); - value = wire; - if (!ce.eval(value, undef)) - log_cmd_error("Failed to evaluate signal %s: Missing value for %s.\n", log_signal(wire), log_signal(undef)); - log_assert(value.is_fully_const()); - success = value.as_const().as_int(); - best_soln = ret; - log("Problem is satisfiable with %s = %d.\n", wire_to_optimize_name.c_str(), success); - Pass::call(design, "design -pop"); - module = design->module(module_name); - - //sometimes this happens if we get an 'unknown' or timeout - if (!maximize && success < failure) - break; - else if (maximize && failure != 0 && success > failure) - break; - - } else { - //Treat 'unknown' as UNSAT - failure = cur_thresh; - if (failure == 0) { - log("Problem is NOT satisfiable.\n"); - break; - } - else - log("Problem is NOT satisfiable with %s %s %d.\n", wire_to_optimize_name.c_str(), (maximize? ">=" : "<="), failure); - } - - iter_num++; - if (maximize && failure == 0 && success == 0) - cur_thresh = 2; - else if (maximize && failure == 0) - cur_thresh = 2 * success; //growth - else //if (!maximize || failure != 0) - cur_thresh = (success + failure) / 2; //bisection - } - if (success != 0 || failure != 0) { - log("Wire %s is %s at %d.\n", wire_to_optimize_name.c_str(), (maximize? "maximized" : "minimized"), success); - ret = best_soln; - } - } - - if(!opt.nocleanup) - remove_directory(tempdir_name); - - Pass::call(design, "design -pop"); - - return ret; -} - -QbfSolveOptions parse_args(const std::vector &args) { - QbfSolveOptions opt; - for (opt.argidx = 1; opt.argidx < args.size(); opt.argidx++) { - if (args[opt.argidx] == "-nocleanup") { - opt.nocleanup = true; - continue; - } - else if (args[opt.argidx] == "-specialize") { - opt.specialize = true; - continue; - } - else if (args[opt.argidx] == "-assume-outputs") { - opt.assume_outputs = true; - continue; - } - else if (args[opt.argidx] == "-assume-negative-polarity") { - opt.assume_neg = true; - continue; - } - else if (args[opt.argidx] == "-nooptimize") { - opt.nooptimize = true; - continue; - } - else if (args[opt.argidx] == "-nobisection") { - opt.nobisection = true; - continue; - } - else if (args[opt.argidx] == "-solver") { - if (args.size() <= opt.argidx + 1) - log_cmd_error("solver not specified.\n"); - else { - if (args[opt.argidx+1] == "z3") - opt.solver = opt.Solver::Z3; - else if (args[opt.argidx+1] == "yices") - opt.solver = opt.Solver::Yices; - else if (args[opt.argidx+1] == "cvc4") - opt.solver = opt.Solver::CVC4; - else - log_cmd_error("Unknown solver \"%s\".\n", args[opt.argidx+1].c_str()); - opt.argidx++; - } - continue; - } - else if (args[opt.argidx] == "-timeout") { - if (args.size() <= opt.argidx + 1) - log_cmd_error("timeout not specified.\n"); - else { - int timeout = atoi(args[opt.argidx+1].c_str()); - if (timeout > 0) - opt.timeout = timeout; - else - log_cmd_error("timeout must be greater than 0.\n"); - opt.argidx++; - } - continue; - } - else if (args[opt.argidx] == "-sat") { - opt.sat = true; - continue; - } - else if (args[opt.argidx] == "-unsat") { - opt.unsat = true; - continue; - } - else if (args[opt.argidx] == "-show-smtbmc") { - opt.show_smtbmc = true; - continue; - } - else if (args[opt.argidx] == "-dump-final-smt2") { - opt.dump_final_smt2 = true; - if (args.size() <= opt.argidx + 1) - log_cmd_error("smt2 file not specified.\n"); - else - opt.dump_final_smt2_file = args[++opt.argidx]; - continue; - } - else if (args[opt.argidx] == "-specialize-from-file") { - opt.specialize_from_file = true; - if (args.size() <= opt.argidx + 1) - log_cmd_error("solution file not specified.\n"); - else - opt.specialize_soln_file = args[++opt.argidx]; - continue; - } - else if (args[opt.argidx] == "-write-solution") { - opt.write_solution = true; - if (args.size() <= opt.argidx + 1) - log_cmd_error("solution file not specified.\n"); - else - opt.write_soln_soln_file = args[++opt.argidx]; - continue; - } - break; - } - - return opt; -} - -void print_proof_failed() -{ - log("\n"); - log(" ______ ___ ___ _ _ _ _ \n"); - log(" (_____ \\ / __) / __) (_) | | | |\n"); - log(" _____) )___ ___ ___ _| |__ _| |__ _____ _| | _____ __| | |\n"); - log(" | ____/ ___) _ \\ / _ (_ __) (_ __|____ | | || ___ |/ _ |_|\n"); - log(" | | | | | |_| | |_| || | | | / ___ | | || ____( (_| |_ \n"); - log(" |_| |_| \\___/ \\___/ |_| |_| \\_____|_|\\_)_____)\\____|_|\n"); - log("\n"); -} - -void print_qed() -{ - log("\n"); - log(" /$$$$$$ /$$$$$$$$ /$$$$$$$ \n"); - log(" /$$__ $$ | $$_____/ | $$__ $$ \n"); - log(" | $$ \\ $$ | $$ | $$ \\ $$ \n"); - log(" | $$ | $$ | $$$$$ | $$ | $$ \n"); - log(" | $$ | $$ | $$__/ | $$ | $$ \n"); - log(" | $$/$$ $$ | $$ | $$ | $$ \n"); - log(" | $$$$$$/ /$$| $$$$$$$$ /$$| $$$$$$$//$$\n"); - log(" \\____ $$$|__/|________/|__/|_______/|__/\n"); - log(" \\__/ \n"); - log("\n"); -} - -struct QbfSatPass : public Pass { - QbfSatPass() : Pass("qbfsat", "solve a 2QBF-SAT problem in the circuit") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" qbfsat [options] [selection]\n"); - log("\n"); - log("This command solves an \"exists-forall\" 2QBF-SAT problem defined over the currently\n"); - log("selected module. Existentially-quantified variables are declared by assigning a wire\n"); - log("\"$anyconst\". Universally-quantified variables may be explicitly declared by assigning\n"); - log("a wire \"$allconst\", but module inputs will be treated as universally-quantified\n"); - log("variables by default.\n"); - log("\n"); - log(" -nocleanup\n"); - log(" Do not delete temporary files and directories. Useful for debugging.\n"); - log("\n"); - log(" -dump-final-smt2 \n"); - log(" Pass the --dump-smt2 option to yosys-smtbmc.\n"); - log("\n"); - log(" -assume-outputs\n"); - log(" Add an \"$assume\" cell for the conjunction of all one-bit module output wires.\n"); - log("\n"); - log(" -assume-negative-polarity\n"); - log(" When adding $assume cells for one-bit module output wires, assume they are\n"); - log(" negative polarity signals and should always be low, for example like the\n"); - log(" miters created with the `miter` command.\n"); - log("\n"); - log(" -nooptimize\n"); - log(" Ignore \"\\minimize\" and \"\\maximize\" attributes, do not emit \"(maximize)\" or\n"); - log(" \"(minimize)\" in the SMT-LIBv2, and generally make no attempt to optimize anything.\n"); - log("\n"); - log(" -nobisection\n"); - log(" If a wire is marked with the \"\\minimize\" or \"\\maximize\" attribute, do not\n"); - log(" attempt to optimize that value with the default iterated solving and threshold\n"); - log(" bisection approach. Instead, have yosys-smtbmc emit a \"(minimize)\" or \"(maximize)\"\n"); - log(" command in the SMT-LIBv2 output and hope that the solver supports optimizing\n"); - log(" quantified bitvector problems.\n"); - log("\n"); - log(" -solver \n"); - log(" Use a particular solver. Choose one of: \"z3\", \"yices\", and \"cvc4\".\n"); - log("\n"); - log(" -timeout \n"); - log(" Set the per-iteration timeout in seconds.\n"); - log("\n"); - log(" -sat\n"); - log(" Generate an error if the solver does not return \"sat\".\n"); - log("\n"); - log(" -unsat\n"); - log(" Generate an error if the solver does not return \"unsat\".\n"); - log("\n"); - log(" -show-smtbmc\n"); - log(" Print the output from yosys-smtbmc.\n"); - log("\n"); - log(" -specialize\n"); - log(" If the problem is satisfiable, replace each \"$anyconst\" cell with its\n"); - log(" corresponding constant value from the model produced by the solver.\n"); - log("\n"); - log(" -specialize-from-file \n"); - log(" Do not run the solver, but instead only attempt to replace each \"$anyconst\"\n"); - log(" cell in the current module with a constant value provided by the specified file.\n"); - log("\n"); - log(" -write-solution \n"); - log(" If the problem is satisfiable, write the corresponding constant value for each\n"); - log(" \"$anyconst\" cell from the model produced by the solver to the specified file."); - log("\n"); - log("\n"); - } - - void execute(std::vector args, RTLIL::Design *design) override - { - log_header(design, "Executing QBFSAT pass (solving QBF-SAT problems in the circuit).\n"); - QbfSolveOptions opt = parse_args(args); - extra_args(args, opt.argidx, design); - - RTLIL::Module *module = nullptr; - for (auto mod : design->selected_modules()) { - if (module) - log_cmd_error("Only one module must be selected for the QBF-SAT pass! (selected: %s and %s)\n", log_id(module), log_id(mod)); - module = mod; - } - if (module == nullptr) - log_cmd_error("Can't perform QBF-SAT on an empty selection!\n"); - - log_push(); - if (!opt.specialize_from_file) { - //Save the design to restore after modiyfing the current module. - std::string module_name = module->name.str(); - - QbfSolutionType ret = qbf_solve(module, opt); - module = design->module(module_name); - if (ret.unknown) { - if (opt.sat || opt.unsat) - log_cmd_error("expected problem to be %s\n", opt.sat? "SAT" : "UNSAT"); - } - else if (ret.sat) { - print_qed(); - if (opt.write_solution) { - write_solution(module, ret, opt.write_soln_soln_file); - } - if (opt.specialize) { - specialize(module, ret); - } else { - dump_model(module, ret); - } - if (opt.unsat) - log_cmd_error("expected problem to be UNSAT\n"); - } - else { - print_proof_failed(); - if (opt.sat) - log_cmd_error("expected problem to be SAT\n"); - } - } else - specialize_from_file(module, opt.specialize_soln_file); - log_pop(); - } -} QbfSatPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index d7bf125d155..430bba1e82c 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -256,21 +256,20 @@ struct SatHelper { RTLIL::SigSpec big_lhs, big_rhs; - for (auto wire : module->wires()) + for (auto &it : module->wires_) { - if (wire->attributes.count(ID::init) == 0) + if (it.second->attributes.count("\\init") == 0) continue; - RTLIL::SigSpec lhs = sigmap(wire); - RTLIL::SigSpec rhs = wire->attributes.at(ID::init); + RTLIL::SigSpec lhs = sigmap(it.second); + RTLIL::SigSpec rhs = it.second->attributes.at("\\init"); log_assert(lhs.size() == rhs.size()); RTLIL::SigSpec removed_bits; for (int i = 0; i < lhs.size(); i++) { RTLIL::SigSpec bit = lhs.extract(i, 1); if (rhs[i] == State::Sx || !satgen.initial_state.check_all(bit)) { - if (rhs[i] != State::Sx) - removed_bits.append(bit); + removed_bits.append(bit); lhs.remove(i, 1); rhs.remove(i, 1); i--; @@ -518,9 +517,9 @@ struct SatHelper } else { for (auto &d : drivers) for (auto &p : d->connections()) { - if (d->type == ID($dff) && p.first == ID::CLK) + if (d->type == "$dff" && p.first == "\\CLK") continue; - if (d->type.begins_with("$_DFF_") && p.first == ID::C) + if (d->type.begins_with("$_DFF_") && p.first == "\\C") continue; queued_signals.add(handled_signals.remove(sigmap(p.second))); } @@ -675,9 +674,9 @@ struct SatHelper strftime(stime, sizeof(stime), "%c", now); std::string module_fname = "unknown"; - auto apos = module->attributes.find(ID::src); + auto apos = module->attributes.find("\\src"); if(apos != module->attributes.end()) - module_fname = module->attributes[ID::src].decode_string(); + module_fname = module->attributes["\\src"].decode_string(); fprintf(f, "$date\n"); fprintf(f, " %s\n", stime); @@ -893,7 +892,7 @@ void print_qed() struct SatPass : public Pass { SatPass() : Pass("sat", "solve a SAT problem in the circuit") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1060,7 +1059,7 @@ struct SatPass : public Pass { log(" Like -falsify but do not return an error for timeouts.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::vector> sets, sets_init, prove, prove_x; std::map>> sets_at; @@ -1354,8 +1353,8 @@ struct SatPass : public Pass { if (show_regs) { pool reg_wires; for (auto cell : module->cells()) { - if (cell->type == ID($dff) || cell->type.begins_with("$_DFF_")) - for (auto bit : cell->getPort(ID::Q)) + if (cell->type == "$dff" || cell->type.begins_with("$_DFF_")) + for (auto bit : cell->getPort("\\Q")) if (bit.wire) reg_wires.insert(bit.wire); } diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 1ab082b091e..4c3022c709d 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -108,8 +108,8 @@ struct SimInstance } } - if (wire->attributes.count(ID::init)) { - Const initval = wire->attributes.at(ID::init); + if (wire->attributes.count("\\init")) { + Const initval = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++) if (initval[i] == State::S0 || initval[i] == State::S1) { state_nets[sig[i]] = initval[i]; @@ -128,32 +128,28 @@ struct SimInstance for (auto &port : cell->connections()) { if (cell->input(port.first)) - for (auto bit : sigmap(port.second)) { + for (auto bit : sigmap(port.second)) upd_cells[bit].insert(cell); - // Make sure cell inputs connected to constants are updated in the first cycle - if (bit.wire == nullptr) - dirty_bits.insert(bit); - } } - if (cell->type.in(ID($dff))) { + if (cell->type.in("$dff")) { ff_state_t ff; ff.past_clock = State::Sx; - ff.past_d = Const(State::Sx, cell->getParam(ID::WIDTH).as_int()); + ff.past_d = Const(State::Sx, cell->getParam("\\WIDTH").as_int()); ff_database[cell] = ff; } - if (cell->type == ID($mem)) + if (cell->type == "$mem") { mem_state_t mem; - mem.past_wr_clk = Const(State::Sx, GetSize(cell->getPort(ID::WR_CLK))); - mem.past_wr_en = Const(State::Sx, GetSize(cell->getPort(ID::WR_EN))); - mem.past_wr_addr = Const(State::Sx, GetSize(cell->getPort(ID::WR_ADDR))); - mem.past_wr_data = Const(State::Sx, GetSize(cell->getPort(ID::WR_DATA))); + mem.past_wr_clk = Const(State::Sx, GetSize(cell->getPort("\\WR_CLK"))); + mem.past_wr_en = Const(State::Sx, GetSize(cell->getPort("\\WR_EN"))); + mem.past_wr_addr = Const(State::Sx, GetSize(cell->getPort("\\WR_ADDR"))); + mem.past_wr_data = Const(State::Sx, GetSize(cell->getPort("\\WR_DATA"))); - mem.data = cell->getParam(ID::INIT); - int sz = cell->getParam(ID::SIZE).as_int() * cell->getParam(ID::WIDTH).as_int(); + mem.data = cell->getParam("\\INIT"); + int sz = cell->getParam("\\SIZE").as_int() * cell->getParam("\\WIDTH").as_int(); if (GetSize(mem.data) > sz) mem.data.bits.resize(sz); @@ -164,7 +160,7 @@ struct SimInstance mem_database[cell] = mem; } - if (cell->type.in(ID($assert), ID($cover), ID($assume))) { + if (cell->type.in("$assert", "$cover", "$assume")) { formal_database.insert(cell); } } @@ -177,7 +173,7 @@ struct SimInstance ff_state_t &ff = it.second; zinit(ff.past_d); - SigSpec qsig = cell->getPort(ID::Q); + SigSpec qsig = cell->getPort("\\Q"); Const qdata = get_state(qsig); zinit(qdata); set_state(qsig, qdata); @@ -234,7 +230,7 @@ struct SimInstance bool did_something = false; sig = sigmap(sig); - log_assert(GetSize(sig) <= GetSize(value)); + log_assert(GetSize(sig) == GetSize(value)); for (int i = 0; i < GetSize(sig); i++) if (state_nets.at(sig[i]) != value[i]) { @@ -260,18 +256,18 @@ struct SimInstance { mem_state_t &mem = mem_database.at(cell); - int num_rd_ports = cell->getParam(ID::RD_PORTS).as_int(); + int num_rd_ports = cell->getParam("\\RD_PORTS").as_int(); - int size = cell->getParam(ID::SIZE).as_int(); - int offset = cell->getParam(ID::OFFSET).as_int(); - int abits = cell->getParam(ID::ABITS).as_int(); - int width = cell->getParam(ID::WIDTH).as_int(); + int size = cell->getParam("\\SIZE").as_int(); + int offset = cell->getParam("\\OFFSET").as_int(); + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); - if (cell->getParam(ID::RD_CLK_ENABLE).as_bool()) + if (cell->getParam("\\RD_CLK_ENABLE").as_bool()) log_error("Memory %s.%s has clocked read ports. Run 'memory' with -nordff.\n", log_id(module), log_id(cell)); - SigSpec rd_addr_sig = cell->getPort(ID::RD_ADDR); - SigSpec rd_data_sig = cell->getPort(ID::RD_DATA); + SigSpec rd_addr_sig = cell->getPort("\\RD_ADDR"); + SigSpec rd_data_sig = cell->getPort("\\RD_DATA"); for (int port_idx = 0; port_idx < num_rd_ports; port_idx++) { @@ -307,19 +303,19 @@ struct SimInstance RTLIL::SigSpec sig_a, sig_b, sig_c, sig_d, sig_s, sig_y; bool has_a, has_b, has_c, has_d, has_s, has_y; - has_a = cell->hasPort(ID::A); - has_b = cell->hasPort(ID::B); - has_c = cell->hasPort(ID::C); - has_d = cell->hasPort(ID::D); - has_s = cell->hasPort(ID::S); - has_y = cell->hasPort(ID::Y); + has_a = cell->hasPort("\\A"); + has_b = cell->hasPort("\\B"); + has_c = cell->hasPort("\\C"); + has_d = cell->hasPort("\\D"); + has_s = cell->hasPort("\\S"); + has_y = cell->hasPort("\\Y"); - if (has_a) sig_a = cell->getPort(ID::A); - if (has_b) sig_b = cell->getPort(ID::B); - if (has_c) sig_c = cell->getPort(ID::C); - if (has_d) sig_d = cell->getPort(ID::D); - if (has_s) sig_s = cell->getPort(ID::S); - if (has_y) sig_y = cell->getPort(ID::Y); + if (has_a) sig_a = cell->getPort("\\A"); + if (has_b) sig_b = cell->getPort("\\B"); + if (has_c) sig_c = cell->getPort("\\C"); + if (has_d) sig_d = cell->getPort("\\D"); + if (has_s) sig_s = cell->getPort("\\S"); + if (has_y) sig_y = cell->getPort("\\Y"); if (shared->debug) log("[%s] eval %s (%s)\n", hiername().c_str(), log_id(cell), log_id(cell->type)); @@ -407,16 +403,16 @@ struct SimInstance Cell *cell = it.first; ff_state_t &ff = it.second; - if (cell->type.in(ID($dff))) + if (cell->type.in("$dff")) { - bool clkpol = cell->getParam(ID::CLK_POLARITY).as_bool(); - State current_clock = get_state(cell->getPort(ID::CLK))[0]; + bool clkpol = cell->getParam("\\CLK_POLARITY").as_bool(); + State current_clock = get_state(cell->getPort("\\CLK"))[0]; if (clkpol ? (ff.past_clock == State::S1 || current_clock != State::S1) : (ff.past_clock == State::S0 || current_clock != State::S0)) continue; - if (set_state(cell->getPort(ID::Q), ff.past_d)) + if (set_state(cell->getPort("\\Q"), ff.past_d)) did_something = true; } } @@ -426,16 +422,16 @@ struct SimInstance Cell *cell = it.first; mem_state_t &mem = it.second; - int num_wr_ports = cell->getParam(ID::WR_PORTS).as_int(); + int num_wr_ports = cell->getParam("\\WR_PORTS").as_int(); - int size = cell->getParam(ID::SIZE).as_int(); - int offset = cell->getParam(ID::OFFSET).as_int(); - int abits = cell->getParam(ID::ABITS).as_int(); - int width = cell->getParam(ID::WIDTH).as_int(); + int size = cell->getParam("\\SIZE").as_int(); + int offset = cell->getParam("\\OFFSET").as_int(); + int abits = cell->getParam("\\ABITS").as_int(); + int width = cell->getParam("\\WIDTH").as_int(); - Const wr_clk_enable = cell->getParam(ID::WR_CLK_ENABLE); - Const wr_clk_polarity = cell->getParam(ID::WR_CLK_POLARITY); - Const current_wr_clk = get_state(cell->getPort(ID::WR_CLK)); + Const wr_clk_enable = cell->getParam("\\WR_CLK_ENABLE"); + Const wr_clk_polarity = cell->getParam("\\WR_CLK_POLARITY"); + Const current_wr_clk = get_state(cell->getPort("\\WR_CLK")); for (int port_idx = 0; port_idx < num_wr_ports; port_idx++) { @@ -443,9 +439,9 @@ struct SimInstance if (wr_clk_enable[port_idx] == State::S0) { - addr = get_state(cell->getPort(ID::WR_ADDR).extract(port_idx*abits, abits)); - data = get_state(cell->getPort(ID::WR_DATA).extract(port_idx*width, width)); - enable = get_state(cell->getPort(ID::WR_EN).extract(port_idx*width, width)); + addr = get_state(cell->getPort("\\WR_ADDR").extract(port_idx*abits, abits)); + data = get_state(cell->getPort("\\WR_DATA").extract(port_idx*width, width)); + enable = get_state(cell->getPort("\\WR_EN").extract(port_idx*width, width)); } else { @@ -489,9 +485,9 @@ struct SimInstance Cell *cell = it.first; ff_state_t &ff = it.second; - if (cell->type.in(ID($dff))) { - ff.past_clock = get_state(cell->getPort(ID::CLK))[0]; - ff.past_d = get_state(cell->getPort(ID::D)); + if (cell->type.in("$dff")) { + ff.past_clock = get_state(cell->getPort("\\CLK"))[0]; + ff.past_d = get_state(cell->getPort("\\D")); } } @@ -500,28 +496,28 @@ struct SimInstance Cell *cell = it.first; mem_state_t &mem = it.second; - mem.past_wr_clk = get_state(cell->getPort(ID::WR_CLK)); - mem.past_wr_en = get_state(cell->getPort(ID::WR_EN)); - mem.past_wr_addr = get_state(cell->getPort(ID::WR_ADDR)); - mem.past_wr_data = get_state(cell->getPort(ID::WR_DATA)); + mem.past_wr_clk = get_state(cell->getPort("\\WR_CLK")); + mem.past_wr_en = get_state(cell->getPort("\\WR_EN")); + mem.past_wr_addr = get_state(cell->getPort("\\WR_ADDR")); + mem.past_wr_data = get_state(cell->getPort("\\WR_DATA")); } for (auto cell : formal_database) { string label = log_id(cell); - if (cell->attributes.count(ID::src)) - label = cell->attributes.at(ID::src).decode_string(); + if (cell->attributes.count("\\src")) + label = cell->attributes.at("\\src").decode_string(); - State a = get_state(cell->getPort(ID::A))[0]; - State en = get_state(cell->getPort(ID::EN))[0]; + State a = get_state(cell->getPort("\\A"))[0]; + State en = get_state(cell->getPort("\\EN"))[0]; - if (cell->type == ID($cover) && en == State::S1 && a != State::S1) + if (cell->type == "$cover" && en == State::S1 && a != State::S1) log("Cover %s.%s (%s) reached.\n", hiername().c_str(), log_id(cell), label.c_str()); - if (cell->type == ID($assume) && en == State::S1 && a != State::S1) + if (cell->type == "$assume" && en == State::S1 && a != State::S1) log("Assumption %s.%s (%s) failed.\n", hiername().c_str(), log_id(cell), label.c_str()); - if (cell->type == ID($assert) && en == State::S1 && a != State::S1) + if (cell->type == "$assert" && en == State::S1 && a != State::S1) log_warning("Assert %s.%s (%s) failed.\n", hiername().c_str(), log_id(cell), label.c_str()); } @@ -537,22 +533,22 @@ struct SimInstance wbmods.insert(module); for (auto wire : module->wires()) - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); for (auto &it : ff_database) { Cell *cell = it.first; - SigSpec sig_q = cell->getPort(ID::Q); + SigSpec sig_q = cell->getPort("\\Q"); Const initval = get_state(sig_q); for (int i = 0; i < GetSize(sig_q); i++) { Wire *w = sig_q[i].wire; - if (w->attributes.count(ID::init) == 0) - w->attributes[ID::init] = Const(State::Sx, GetSize(w)); + if (w->attributes.count("\\init") == 0) + w->attributes["\\init"] = Const(State::Sx, GetSize(w)); - w->attributes[ID::init][sig_q[i].offset] = initval[i]; + w->attributes["\\init"][sig_q[i].offset] = initval[i]; } } @@ -568,7 +564,7 @@ struct SimInstance initval.bits.pop_back(); } - cell->setParam(ID::INIT, initval); + cell->setParam("\\INIT", initval); } for (auto it : children) @@ -751,7 +747,7 @@ struct SimWorker : SimShared struct SimPass : public Pass { SimPass() : Pass("sim", "simulate the circuit") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -793,7 +789,7 @@ struct SimPass : public Pass { log(" enable debug output\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { SimWorker worker; int numcycles = 20; diff --git a/passes/sat/supercover.cc b/passes/sat/supercover.cc index aacc044fb11..ba44f02d879 100644 --- a/passes/sat/supercover.cc +++ b/passes/sat/supercover.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct SupercoverPass : public Pass { SupercoverPass() : Pass("supercover", "add hi/lo cover cells for each wire bit") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -35,7 +35,7 @@ struct SupercoverPass : public Pass { log("checking for a hi signal level and one checking for lo level.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { // bool flag_noinit = false; diff --git a/passes/techmap/.gitignore b/passes/techmap/.gitignore new file mode 100644 index 00000000000..e6dcc6bc000 --- /dev/null +++ b/passes/techmap/.gitignore @@ -0,0 +1 @@ +techmap.inc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index a54b4913d6e..cd357d72a26 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -1,5 +1,4 @@ -OBJS += passes/techmap/flatten.o OBJS += passes/techmap/techmap.o OBJS += passes/techmap/simplemap.o OBJS += passes/techmap/dfflibmap.o @@ -9,12 +8,9 @@ OBJS += passes/techmap/libparse.o ifeq ($(ENABLE_ABC),1) OBJS += passes/techmap/abc.o OBJS += passes/techmap/abc9.o -OBJS += passes/techmap/abc9_exe.o -OBJS += passes/techmap/abc9_ops.o ifneq ($(ABCEXTERNAL),) passes/techmap/abc.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' passes/techmap/abc9.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' -passes/techmap/abc9_exe.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' endif endif @@ -35,6 +31,7 @@ OBJS += passes/techmap/aigmap.o OBJS += passes/techmap/tribuf.o OBJS += passes/techmap/lut2mux.o OBJS += passes/techmap/nlutmap.o +OBJS += passes/techmap/dffsr2dff.o OBJS += passes/techmap/shregmap.o OBJS += passes/techmap/deminout.o OBJS += passes/techmap/insbuf.o @@ -46,11 +43,23 @@ OBJS += passes/techmap/flowmap.o OBJS += passes/techmap/extractinv.o endif -ifeq ($(DISABLE_SPAWN),0) -TARGETS += $(PROGRAM_PREFIX)yosys-filterlib$(EXE) +GENFILES += passes/techmap/techmap.inc + +passes/techmap/techmap.inc: techlibs/common/techmap.v + $(Q) mkdir -p $(dir $@) + $(P) echo "// autogenerated from $<" > $@.new + $(Q) echo "static char stdcells_code[] = {" >> $@.new + $(Q) od -v -td1 -An $< | $(SED) -e 's/[0-9][0-9]*/&,/g' >> $@.new + $(Q) echo "0};" >> $@.new + $(Q) mv $@.new $@ + +passes/techmap/techmap.o: passes/techmap/techmap.inc + +ifneq ($(CONFIG),emcc) +TARGETS += yosys-filterlib$(EXE) EXTRA_OBJS += passes/techmap/filterlib.o -$(PROGRAM_PREFIX)yosys-filterlib$(EXE): passes/techmap/filterlib.o +yosys-filterlib$(EXE): passes/techmap/filterlib.o $(Q) mkdir -p $(dir $@) - $(P) $(LD) -o $(PROGRAM_PREFIX)yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS) + $(P) $(LD) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS) endif diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 0a58fdcc0d6..b29480e267e 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -29,17 +29,17 @@ // Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558-562, doi:10.1145/368996.369025 // http://en.wikipedia.org/wiki/Topological_sorting -#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put" -#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p" -#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2" -#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}" -#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put" - -#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}" -#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" -#define ABC_FAST_COMMAND_LUT "strash; dretime; if" -#define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}" -#define ABC_FAST_COMMAND_DFL "strash; dretime; map" +#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put" +#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; if; mfs2" +#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; cover {I} {P}" +#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put" + +#define ABC_FAST_COMMAND_LIB "strash; dretime; retime {D}; map {D}" +#define ABC_FAST_COMMAND_CTR "strash; dretime; retime {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_FAST_COMMAND_LUT "strash; dretime; retime {D}; if" +#define ABC_FAST_COMMAND_SOP "strash; dretime; retime {D}; cover -I {I} -P {P}" +#define ABC_FAST_COMMAND_DFL "strash; dretime; retime {D}; map" #include "kernel/register.h" #include "kernel/sigtools.h" @@ -160,7 +160,7 @@ int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, void mark_port(RTLIL::SigSpec sig) { for (auto &bit : assign_map(sig)) - if (bit.wire != nullptr && signal_map.count(bit) > 0) + if (bit.wire != NULL && signal_map.count(bit) > 0) signal_list[signal_map[bit]].is_port = true; } @@ -170,7 +170,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) { if (clk_polarity != (cell->type == ID($_DFF_P_))) return; - if (clk_sig != assign_map(cell->getPort(ID::C))) + if (clk_sig != assign_map(cell->getPort(ID(C)))) return; if (GetSize(en_sig) != 0) return; @@ -183,21 +183,21 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) return; if (en_polarity != cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) return; - if (clk_sig != assign_map(cell->getPort(ID::C))) + if (clk_sig != assign_map(cell->getPort(ID(C)))) return; - if (en_sig != assign_map(cell->getPort(ID::E))) + if (en_sig != assign_map(cell->getPort(ID(E)))) return; goto matching_dff; } if (0) { matching_dff: - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); + RTLIL::SigSpec sig_d = cell->getPort(ID(D)); + RTLIL::SigSpec sig_q = cell->getPort(ID(Q)); if (keepff) for (auto &c : sig_q.chunks()) - if (c.wire != nullptr) + if (c.wire != NULL) c.wire->attributes[ID::keep] = 1; assign_map.apply(sig_d); @@ -263,7 +263,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) { RTLIL::SigSpec sig_a = cell->getPort(ID::A); RTLIL::SigSpec sig_b = cell->getPort(ID::B); - RTLIL::SigSpec sig_s = cell->getPort(ID::S); + RTLIL::SigSpec sig_s = cell->getPort(ID(S)); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); assign_map.apply(sig_a); @@ -285,7 +285,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) { RTLIL::SigSpec sig_a = cell->getPort(ID::A); RTLIL::SigSpec sig_b = cell->getPort(ID::B); - RTLIL::SigSpec sig_c = cell->getPort(ID::C); + RTLIL::SigSpec sig_c = cell->getPort(ID(C)); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); assign_map.apply(sig_a); @@ -307,8 +307,8 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) { RTLIL::SigSpec sig_a = cell->getPort(ID::A); RTLIL::SigSpec sig_b = cell->getPort(ID::B); - RTLIL::SigSpec sig_c = cell->getPort(ID::C); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); + RTLIL::SigSpec sig_c = cell->getPort(ID(C)); + RTLIL::SigSpec sig_d = cell->getPort(ID(D)); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); assign_map.apply(sig_a); @@ -370,7 +370,7 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp void dump_loop_graph(FILE *f, int &nr, std::map> &edges, std::set &workpool, std::vector &in_counts) { - if (f == nullptr) + if (f == NULL) return; log("Dumping loop state graph to slide %d.\n", ++nr); @@ -406,7 +406,7 @@ void handle_loops() std::vector in_edges_count(signal_list.size()); std::set workpool; - FILE *dot_f = nullptr; + FILE *dot_f = NULL; int dot_nr = 0; // uncomment for troubleshooting the loop detection code @@ -464,9 +464,9 @@ void handle_loops() int id2 = edge_it.first; RTLIL::Wire *w1 = signal_list[id1].bit.wire; RTLIL::Wire *w2 = signal_list[id2].bit.wire; - if (w1 == nullptr) + if (w1 == NULL) id1 = id2; - else if (w2 == nullptr) + else if (w2 == NULL) continue; else if (w1->name[0] == '$' && w2->name[0] == '\\') id1 = id2; @@ -485,7 +485,7 @@ void handle_loops() continue; } - log_assert(signal_list[id1].bit.wire != nullptr); + log_assert(signal_list[id1].bit.wire != NULL); std::stringstream sstr; sstr << "$abcloop$" << (autoidx++); @@ -526,7 +526,7 @@ void handle_loops() } } - if (dot_f != nullptr) + if (dot_f != NULL) fclose(dot_f); } @@ -688,21 +688,21 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin en_polarity = false; en_str = en_str.substr(1); } - if (module->wire(RTLIL::escape_id(en_str)) != nullptr) - en_sig = assign_map(module->wire(RTLIL::escape_id(en_str))); + if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) + en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); } if (clk_str[0] == '!') { clk_polarity = false; clk_str = clk_str.substr(1); } - if (module->wire(RTLIL::escape_id(clk_str)) != nullptr) - clk_sig = assign_map(module->wire(RTLIL::escape_id(clk_str))); + if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0) + clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0)); } if (dff_mode && clk_sig.empty()) log_cmd_error("Clock domain %s not found.\n", clk_str.c_str()); - std::string tempdir_name = "/tmp/" + proc_program_prefix()+ "yosys-abc-XXXXXX"; + std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; if (!cleanup) tempdir_name[0] = tempdir_name[4] = '_'; tempdir_name = make_temp_dir(tempdir_name); @@ -747,10 +747,6 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin else abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; - if (script_file.empty() && !delay_target.empty()) - for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) - abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8); - for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3); @@ -771,10 +767,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (abc_script[i] == ';' && abc_script[i+1] == ' ') abc_script[i+1] = '\n'; - std::string buffer = stringf("%s/abc.script", tempdir_name.c_str()); - FILE *f = fopen(buffer.c_str(), "wt"); - if (f == nullptr) - log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); + FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); fprintf(f, "%s\n", abc_script.c_str()); fclose(f); @@ -793,13 +786,13 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin for (auto c : cells) extract_cell(c, keepff); - for (auto wire : module->wires()) { - if (wire->port_id > 0 || wire->get_bool_attribute(ID::keep)) - mark_port(wire); + for (auto &wire_it : module->wires_) { + if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute(ID::keep)) + mark_port(RTLIL::SigSpec(wire_it.second)); } - for (auto cell : module->cells()) - for (auto &port_it : cell->connections()) + for (auto &cell_it : module->cells_) + for (auto &port_it : cell_it.second->connections()) mark_port(port_it.second); if (clk_sig.size() != 0) @@ -810,9 +803,9 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin handle_loops(); - buffer = stringf("%s/input.blif", tempdir_name.c_str()); + std::string buffer = stringf("%s/input.blif", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); - if (f == nullptr) + if (f == NULL) log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); fprintf(f, ".model netlist\n"); @@ -843,7 +836,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fprintf(f, "# ys__n%-5d %s\n", si.id, log_signal(si.bit)); for (auto &si : signal_list) { - if (si.bit.wire == nullptr) { + if (si.bit.wire == NULL) { fprintf(f, ".names ys__n%d\n", si.id); if (si.bit == RTLIL::State::S1) fprintf(f, "1\n"); @@ -939,7 +932,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); - if (f == nullptr) + if (f == NULL) log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); fprintf(f, "GATE ONE 1 Y=CONST1;\n"); @@ -984,7 +977,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (!lut_costs.empty()) { buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); - if (f == nullptr) + if (f == NULL) log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); for (int i = 0; i < GetSize(lut_costs); i++) fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i)); @@ -1028,15 +1021,16 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin ifs.close(); log_header(design, "Re-integrating ABC results.\n"); - RTLIL::Module *mapped_mod = mapped_design->module(ID(netlist)); - if (mapped_mod == nullptr) + RTLIL::Module *mapped_mod = mapped_design->modules_[ID(netlist)]; + if (mapped_mod == NULL) log_error("ABC output file does not contain a module `netlist'.\n"); - for (auto w : mapped_mod->wires()) { + for (auto &it : mapped_mod->wires_) { + RTLIL::Wire *w = it.second; RTLIL::Wire *orig_wire = nullptr; RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire)); - if (orig_wire != nullptr && orig_wire->attributes.count(ID::src)) - wire->attributes[ID::src] = orig_wire->attributes[ID::src]; - if (markgroups) wire->attributes[ID::abcgroup] = map_autoidx; + if (orig_wire != nullptr && orig_wire->attributes.count(ID(src))) + wire->attributes[ID(src)] = orig_wire->attributes[ID(src)]; + if (markgroups) wire->attributes[ID(abcgroup)] = map_autoidx; design->select(module, wire); } @@ -1048,99 +1042,121 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin cell_stats[RTLIL::unescape_id(c->type)]++; if (c->type.in(ID(ZERO), ID(ONE))) { RTLIL::SigSig conn; - RTLIL::IdString name_y = remap_name(c->getPort(ID::Y).as_wire()->name); - conn.first = module->wire(name_y); + conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]); conn.second = RTLIL::SigSpec(c->type == ID(ZERO) ? 0 : 1, 1); module->connect(conn); continue; } if (c->type == ID(BUF)) { RTLIL::SigSig conn; - RTLIL::IdString name_y = remap_name(c->getPort(ID::Y).as_wire()->name); - RTLIL::IdString name_a = remap_name(c->getPort(ID::A).as_wire()->name); - conn.first = module->wire(name_y); - conn.second = module->wire(name_a); + conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]); + conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]); module->connect(conn); continue; } if (c->type == ID(NOT)) { RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_NOT_)); - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::A, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); - } + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)])); + cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)])); design->select(module, cell); continue; } if (c->type.in(ID(AND), ID(OR), ID(XOR), ID(NAND), ID(NOR), ID(XNOR), ID(ANDNOT), ID(ORNOT))) { RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::A, ID::B, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); - } + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)])); + cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)])); + cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)])); design->select(module, cell); continue; } if (c->type.in(ID(MUX), ID(NMUX))) { RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::A, ID::B, ID::S, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); - } + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)])); + cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)])); + cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)])); + cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)])); design->select(module, cell); continue; } if (c->type == ID(MUX4)) { RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX4_)); - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::A, ID::B, ID::C, ID::D, ID::S, ID::T, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); - } + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)])); + cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)])); + cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)])); + cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)])); + cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)])); + cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)])); + cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)])); design->select(module, cell); continue; } if (c->type == ID(MUX8)) { RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX8_)); - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::S, ID::T, ID::U, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); - } + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)])); + cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)])); + cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)])); + cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)])); + cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)])); + cell->setPort(ID(F), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(F)).as_wire()->name)])); + cell->setPort(ID(G), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(G)).as_wire()->name)])); + cell->setPort(ID(H), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(H)).as_wire()->name)])); + cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)])); + cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)])); + cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)])); + cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)])); design->select(module, cell); continue; } if (c->type == ID(MUX16)) { RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX16_)); - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::I, ID::J, ID::K, - ID::L, ID::M, ID::N, ID::O, ID::P, ID::S, ID::T, ID::U, ID::V, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); - } + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)])); + cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)])); + cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)])); + cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)])); + cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)])); + cell->setPort(ID(F), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(F)).as_wire()->name)])); + cell->setPort(ID(G), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(G)).as_wire()->name)])); + cell->setPort(ID(H), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(H)).as_wire()->name)])); + cell->setPort(ID(I), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(I)).as_wire()->name)])); + cell->setPort(ID(J), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(J)).as_wire()->name)])); + cell->setPort(ID(K), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(K)).as_wire()->name)])); + cell->setPort(ID(L), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(L)).as_wire()->name)])); + cell->setPort(ID(M), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(M)).as_wire()->name)])); + cell->setPort(ID(N), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(N)).as_wire()->name)])); + cell->setPort(ID(O), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(O)).as_wire()->name)])); + cell->setPort(ID(P), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(P)).as_wire()->name)])); + cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)])); + cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)])); + cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)])); + cell->setPort(ID(V), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(V)).as_wire()->name)])); + cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)])); design->select(module, cell); continue; } if (c->type.in(ID(AOI3), ID(OAI3))) { RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::A, ID::B, ID::C, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); - } + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)])); + cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)])); + cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)])); + cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)])); design->select(module, cell); continue; } if (c->type.in(ID(AOI4), ID(OAI4))) { RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::A, ID::B, ID::C, ID::D, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); - } + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)])); + cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)])); + cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)])); + cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)])); + cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)])); design->select(module, cell); continue; } @@ -1152,14 +1168,12 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } else { log_assert(en_sig.size() == 1); cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort(ID::E, en_sig); + cell->setPort(ID(E), en_sig); } - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::D, ID::Q}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); - } - cell->setPort(ID::C, clk_sig); + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)])); + cell->setPort(ID(Q), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Q)).as_wire()->name)])); + cell->setPort(ID(C), clk_sig); design->select(module, cell); continue; } @@ -1169,7 +1183,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (c->type.in(ID(_const0_), ID(_const1_))) { RTLIL::SigSig conn; - conn.first = module->wire(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 == ID(_const0_) ? 0 : 1, 1); module->connect(conn); continue; @@ -1183,27 +1197,25 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } else { log_assert(en_sig.size() == 1); cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort(ID::E, en_sig); - } - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::D, ID::Q}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); + cell->setPort(ID(E), en_sig); } - cell->setPort(ID::C, clk_sig); + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)])); + cell->setPort(ID(Q), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Q)).as_wire()->name)])); + cell->setPort(ID(C), clk_sig); design->select(module, cell); continue; } - if (c->type == ID($lut) && GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID::LUT).as_int() == 2) { - SigSpec my_a = module->wire(remap_name(c->getPort(ID::A).as_wire()->name)); - SigSpec my_y = module->wire(remap_name(c->getPort(ID::Y).as_wire()->name)); + if (c->type == ID($lut) && GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)).as_int() == 2) { + SigSpec my_a = module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]; + SigSpec my_y = module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]; module->connect(my_y, my_a); continue; } RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; cell->parameters = c->parameters; for (auto &conn : c->connections()) { RTLIL::SigSpec newsig; @@ -1211,7 +1223,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (c.width == 0) continue; log_assert(c.width == 1); - newsig.append(module->wire(remap_name(c.wire->name))); + newsig.append(module->wires_[remap_name(c.wire->name)]); } cell->setPort(conn.first, newsig); } @@ -1220,18 +1232,18 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin for (auto conn : mapped_mod->connections()) { if (!conn.first.is_fully_const()) - conn.first = module->wire(remap_name(conn.first.as_wire()->name)); + conn.first = RTLIL::SigSpec(module->wires_[remap_name(conn.first.as_wire()->name)]); if (!conn.second.is_fully_const()) - conn.second = module->wire(remap_name(conn.second.as_wire()->name)); + conn.second = RTLIL::SigSpec(module->wires_[remap_name(conn.second.as_wire()->name)]); module->connect(conn); } if (recover_init) for (auto wire : mapped_mod->wires()) { - if (wire->attributes.count(ID::init)) { - Wire *w = module->wire(remap_name(wire->name)); - log_assert(w->attributes.count(ID::init) == 0); - w->attributes[ID::init] = wire->attributes.at(ID::init); + if (wire->attributes.count(ID(init))) { + Wire *w = module->wires_[remap_name(wire->name)]; + log_assert(w->attributes.count(ID(init)) == 0); + w->attributes[ID(init)] = wire->attributes.at(ID(init)); } } @@ -1245,10 +1257,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin RTLIL::SigSig conn; if (si.type != G(NONE)) { conn.first = si.bit; - conn.second = module->wire(remap_name(buffer)); + conn.second = RTLIL::SigSpec(module->wires_[remap_name(buffer)]); out_wires++; } else { - conn.first = module->wire(remap_name(buffer)); + conn.first = RTLIL::SigSpec(module->wires_[remap_name(buffer)]); conn.second = si.bit; in_wires++; } @@ -1276,7 +1288,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin struct AbcPass : public Pass { AbcPass() : Pass("abc", "use ABC for technology mapping") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1289,7 +1301,7 @@ struct AbcPass : public Pass { #ifdef ABCEXTERNAL log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); #else - log(" use the specified command instead of \"/%syosys-abc\" to execute ABC.\n", proc_program_prefix().c_str()); + log(" use the specified command instead of \"/yosys-abc\" to execute ABC.\n"); #endif log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n"); log("\n"); @@ -1460,7 +1472,7 @@ struct AbcPass : public Pass { log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ABC pass (technology mapping using ABC).\n"); log_push(); @@ -1475,7 +1487,7 @@ struct AbcPass : public Pass { #ifdef ABCEXTERNAL std::string exe_file = ABCEXTERNAL; #else - std::string exe_file = proc_self_dirname() + proc_program_prefix() + "yosys-abc"; + std::string exe_file = proc_self_dirname() + "yosys-abc"; #endif std::string script_file, liberty_file, constr_file, clk_str; std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1"; @@ -1493,66 +1505,17 @@ struct AbcPass : public Pass { #ifdef _WIN32 #ifndef ABCEXTERNAL - if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix()+ "yosys-abc.exe")) - exe_file = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc"; + if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) + exe_file = proc_self_dirname() + "..\\yosys-abc"; #endif #endif - // get arguments from scratchpad first, then override by command arguments - std::string lut_arg, luts_arg, g_arg; - exe_file = design->scratchpad_get_string("abc.exe", exe_file /* inherit default value if not set */); - script_file = design->scratchpad_get_string("abc.script", script_file); - liberty_file = design->scratchpad_get_string("abc.liberty", liberty_file); - constr_file = design->scratchpad_get_string("abc.constr", constr_file); - if (design->scratchpad.count("abc.D")) { - delay_target = "-D " + design->scratchpad_get_string("abc.D"); - } - if (design->scratchpad.count("abc.I")) { - sop_inputs = "-I " + design->scratchpad_get_string("abc.I"); - } - if (design->scratchpad.count("abc.P")) { - sop_products = "-P " + design->scratchpad_get_string("abc.P"); - } - if (design->scratchpad.count("abc.S")) { - lutin_shared = "-S " + design->scratchpad_get_string("abc.S"); - } - lut_arg = design->scratchpad_get_string("abc.lut", lut_arg); - luts_arg = design->scratchpad_get_string("abc.luts", luts_arg); - sop_mode = design->scratchpad_get_bool("abc.sop", sop_mode); - map_mux4 = design->scratchpad_get_bool("abc.mux4", map_mux4); - map_mux8 = design->scratchpad_get_bool("abc.mux8", map_mux8); - map_mux16 = design->scratchpad_get_bool("abc.mux16", map_mux16); - abc_dress = design->scratchpad_get_bool("abc.dress", abc_dress); - g_arg = design->scratchpad_get_string("abc.g", g_arg); - - fast_mode = design->scratchpad_get_bool("abc.fast", fast_mode); - dff_mode = design->scratchpad_get_bool("abc.dff", dff_mode); - if (design->scratchpad.count("abc.clk")) { - clk_str = design->scratchpad_get_string("abc.clk"); - dff_mode = true; - } - keepff = design->scratchpad_get_bool("abc.keepff", keepff); - cleanup = !design->scratchpad_get_bool("abc.nocleanup", !cleanup); - keepff = design->scratchpad_get_bool("abc.keepff", keepff); - show_tempdir = design->scratchpad_get_bool("abc.showtmp", show_tempdir); - markgroups = design->scratchpad_get_bool("abc.markgroups", markgroups); - - if (design->scratchpad_get_bool("abc.debug")) { - cleanup = false; - show_tempdir = true; - } - - size_t argidx, g_argidx; - bool g_arg_from_cmd = false; -#if defined(__wasm) - const char *pwd = "."; -#else + size_t argidx; char pwd [PATH_MAX]; if (!getcwd(pwd, sizeof(pwd))) { log_cmd_error("getcwd failed: %s\n", strerror(errno)); log_abort(); } -#endif for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; if (arg == "-exe" && argidx+1 < args.size()) { @@ -1561,14 +1524,23 @@ struct AbcPass : public Pass { } if (arg == "-script" && argidx+1 < args.size()) { script_file = args[++argidx]; + rewrite_filename(script_file); + if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+') + script_file = std::string(pwd) + "/" + script_file; continue; } if (arg == "-liberty" && argidx+1 < args.size()) { liberty_file = args[++argidx]; + rewrite_filename(liberty_file); + if (!liberty_file.empty() && !is_absolute_path(liberty_file)) + liberty_file = std::string(pwd) + "/" + liberty_file; continue; } if (arg == "-constr" && argidx+1 < args.size()) { + rewrite_filename(constr_file); constr_file = args[++argidx]; + if (!constr_file.empty() && !is_absolute_path(constr_file)) + constr_file = std::string(pwd) + "/" + constr_file; continue; } if (arg == "-D" && argidx+1 < args.size()) { @@ -1588,11 +1560,37 @@ struct AbcPass : public Pass { continue; } if (arg == "-lut" && argidx+1 < args.size()) { - lut_arg = args[++argidx]; + string arg = args[++argidx]; + size_t pos = arg.find_first_of(':'); + int lut_mode = 0, lut_mode2 = 0; + if (pos != string::npos) { + lut_mode = atoi(arg.substr(0, pos).c_str()); + lut_mode2 = atoi(arg.substr(pos+1).c_str()); + } else { + lut_mode = atoi(arg.c_str()); + lut_mode2 = lut_mode; + } + lut_costs.clear(); + for (int i = 0; i < lut_mode; i++) + lut_costs.push_back(1); + for (int i = lut_mode; i < lut_mode2; i++) + lut_costs.push_back(2 << (i - lut_mode)); continue; } if (arg == "-luts" && argidx+1 < args.size()) { - luts_arg = args[++argidx]; + lut_costs.clear(); + for (auto &tok : split_tokens(args[++argidx], ",")) { + auto parts = split_tokens(tok, ":"); + if (GetSize(parts) == 0 && !lut_costs.empty()) + lut_costs.push_back(lut_costs.back()); + else if (GetSize(parts) == 1) + lut_costs.push_back(atoi(parts.at(0).c_str())); + else if (GetSize(parts) == 2) + while (GetSize(lut_costs) < std::atoi(parts.at(0).c_str())) + lut_costs.push_back(atoi(parts.at(1).c_str())); + else + log_cmd_error("Invalid -luts syntax.\n"); + } continue; } if (arg == "-sop") { @@ -1616,11 +1614,123 @@ struct AbcPass : public Pass { continue; } if (arg == "-g" && argidx+1 < args.size()) { - if (g_arg_from_cmd) - log_cmd_error("Can only use -g once. Please combine."); - g_arg = args[++argidx]; - g_argidx = argidx; - g_arg_from_cmd = true; + for (auto g : split_tokens(args[++argidx], ",")) { + vector gate_list; + bool remove_gates = false; + if (GetSize(g) > 0 && g[0] == '-') { + remove_gates = true; + g = g.substr(1); + } + if (g == "AND") goto ok_gate; + if (g == "NAND") goto ok_gate; + if (g == "OR") goto ok_gate; + if (g == "NOR") goto ok_gate; + if (g == "XOR") goto ok_gate; + if (g == "XNOR") goto ok_gate; + if (g == "ANDNOT") goto ok_gate; + if (g == "ORNOT") goto ok_gate; + if (g == "MUX") goto ok_gate; + if (g == "NMUX") goto ok_gate; + if (g == "AOI3") goto ok_gate; + if (g == "OAI3") goto ok_gate; + if (g == "AOI4") goto ok_gate; + if (g == "OAI4") goto ok_gate; + if (g == "simple") { + gate_list.push_back("AND"); + gate_list.push_back("OR"); + gate_list.push_back("XOR"); + gate_list.push_back("MUX"); + goto ok_alias; + } + if (g == "cmos2") { + if (!remove_gates) + cmos_cost = true; + gate_list.push_back("NAND"); + gate_list.push_back("NOR"); + goto ok_alias; + } + if (g == "cmos3") { + if (!remove_gates) + cmos_cost = true; + gate_list.push_back("NAND"); + gate_list.push_back("NOR"); + gate_list.push_back("AOI3"); + gate_list.push_back("OAI3"); + goto ok_alias; + } + if (g == "cmos4") { + if (!remove_gates) + cmos_cost = true; + gate_list.push_back("NAND"); + gate_list.push_back("NOR"); + gate_list.push_back("AOI3"); + gate_list.push_back("OAI3"); + gate_list.push_back("AOI4"); + gate_list.push_back("OAI4"); + goto ok_alias; + } + if (g == "cmos") { + if (!remove_gates) + cmos_cost = true; + gate_list.push_back("NAND"); + gate_list.push_back("NOR"); + gate_list.push_back("AOI3"); + gate_list.push_back("OAI3"); + gate_list.push_back("AOI4"); + gate_list.push_back("OAI4"); + gate_list.push_back("NMUX"); + gate_list.push_back("MUX"); + gate_list.push_back("XOR"); + gate_list.push_back("XNOR"); + goto ok_alias; + } + if (g == "gates") { + gate_list.push_back("AND"); + gate_list.push_back("NAND"); + 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"); + goto ok_alias; + } + if (g == "aig") { + gate_list.push_back("AND"); + gate_list.push_back("NAND"); + gate_list.push_back("OR"); + gate_list.push_back("NOR"); + gate_list.push_back("ANDNOT"); + gate_list.push_back("ORNOT"); + goto ok_alias; + } + if (g == "all") { + gate_list.push_back("AND"); + gate_list.push_back("NAND"); + gate_list.push_back("OR"); + gate_list.push_back("NOR"); + gate_list.push_back("XOR"); + gate_list.push_back("XNOR"); + gate_list.push_back("ANDNOT"); + gate_list.push_back("ORNOT"); + gate_list.push_back("AOI3"); + gate_list.push_back("OAI3"); + gate_list.push_back("AOI4"); + gate_list.push_back("OAI4"); + gate_list.push_back("MUX"); + gate_list.push_back("NMUX"); + } + cmd_error(args, argidx, stringf("Unsupported gate type: %s", g.c_str())); + ok_gate: + gate_list.push_back(g); + ok_alias: + for (auto gate : gate_list) { + if (remove_gates) + enabled_gates.erase(gate); + else + enabled_gates.insert(gate); + } + } continue; } if (arg == "-fast") { @@ -1656,176 +1766,8 @@ struct AbcPass : public Pass { } extra_args(args, argidx, design); - rewrite_filename(script_file); - if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+') - script_file = std::string(pwd) + "/" + script_file; - rewrite_filename(liberty_file); - if (!liberty_file.empty() && !is_absolute_path(liberty_file)) - liberty_file = std::string(pwd) + "/" + liberty_file; - rewrite_filename(constr_file); - if (!constr_file.empty() && !is_absolute_path(constr_file)) - constr_file = std::string(pwd) + "/" + constr_file; - - // handle -lut argument - if (!lut_arg.empty()) { - size_t pos = lut_arg.find_first_of(':'); - int lut_mode = 0, lut_mode2 = 0; - if (pos != string::npos) { - lut_mode = atoi(lut_arg.substr(0, pos).c_str()); - lut_mode2 = atoi(lut_arg.substr(pos+1).c_str()); - } else { - lut_mode = atoi(lut_arg.c_str()); - lut_mode2 = lut_mode; - } - lut_costs.clear(); - for (int i = 0; i < lut_mode; i++) - lut_costs.push_back(1); - for (int i = lut_mode; i < lut_mode2; i++) - lut_costs.push_back(2 << (i - lut_mode)); - } - //handle -luts argument - if (!luts_arg.empty()){ - lut_costs.clear(); - for (auto &tok : split_tokens(luts_arg, ",")) { - auto parts = split_tokens(tok, ":"); - if (GetSize(parts) == 0 && !lut_costs.empty()) - lut_costs.push_back(lut_costs.back()); - else if (GetSize(parts) == 1) - lut_costs.push_back(atoi(parts.at(0).c_str())); - else if (GetSize(parts) == 2) - while (GetSize(lut_costs) < std::atoi(parts.at(0).c_str())) - lut_costs.push_back(atoi(parts.at(1).c_str())); - else - log_cmd_error("Invalid -luts syntax.\n"); - } - } - - // handle -g argument - if (!g_arg.empty()){ - for (auto g : split_tokens(g_arg, ",")) { - vector gate_list; - bool remove_gates = false; - if (GetSize(g) > 0 && g[0] == '-') { - remove_gates = true; - g = g.substr(1); - } - if (g == "AND") goto ok_gate; - if (g == "NAND") goto ok_gate; - if (g == "OR") goto ok_gate; - if (g == "NOR") goto ok_gate; - if (g == "XOR") goto ok_gate; - if (g == "XNOR") goto ok_gate; - if (g == "ANDNOT") goto ok_gate; - if (g == "ORNOT") goto ok_gate; - if (g == "MUX") goto ok_gate; - if (g == "NMUX") goto ok_gate; - if (g == "AOI3") goto ok_gate; - if (g == "OAI3") goto ok_gate; - if (g == "AOI4") goto ok_gate; - if (g == "OAI4") goto ok_gate; - if (g == "simple") { - gate_list.push_back("AND"); - gate_list.push_back("OR"); - gate_list.push_back("XOR"); - gate_list.push_back("MUX"); - goto ok_alias; - } - if (g == "cmos2") { - if (!remove_gates) - cmos_cost = true; - gate_list.push_back("NAND"); - gate_list.push_back("NOR"); - goto ok_alias; - } - if (g == "cmos3") { - if (!remove_gates) - cmos_cost = true; - gate_list.push_back("NAND"); - gate_list.push_back("NOR"); - gate_list.push_back("AOI3"); - gate_list.push_back("OAI3"); - goto ok_alias; - } - if (g == "cmos4") { - if (!remove_gates) - cmos_cost = true; - gate_list.push_back("NAND"); - gate_list.push_back("NOR"); - gate_list.push_back("AOI3"); - gate_list.push_back("OAI3"); - gate_list.push_back("AOI4"); - gate_list.push_back("OAI4"); - goto ok_alias; - } - if (g == "cmos") { - if (!remove_gates) - cmos_cost = true; - gate_list.push_back("NAND"); - gate_list.push_back("NOR"); - gate_list.push_back("AOI3"); - gate_list.push_back("OAI3"); - gate_list.push_back("AOI4"); - gate_list.push_back("OAI4"); - gate_list.push_back("NMUX"); - gate_list.push_back("MUX"); - gate_list.push_back("XOR"); - gate_list.push_back("XNOR"); - goto ok_alias; - } - if (g == "gates") { - gate_list.push_back("AND"); - gate_list.push_back("NAND"); - 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"); - goto ok_alias; - } - if (g == "aig") { - gate_list.push_back("AND"); - gate_list.push_back("NAND"); - gate_list.push_back("OR"); - gate_list.push_back("NOR"); - gate_list.push_back("ANDNOT"); - gate_list.push_back("ORNOT"); - goto ok_alias; - } - if (g == "all") { - gate_list.push_back("AND"); - gate_list.push_back("NAND"); - gate_list.push_back("OR"); - gate_list.push_back("NOR"); - gate_list.push_back("XOR"); - gate_list.push_back("XNOR"); - gate_list.push_back("ANDNOT"); - gate_list.push_back("ORNOT"); - gate_list.push_back("AOI3"); - gate_list.push_back("OAI3"); - gate_list.push_back("AOI4"); - gate_list.push_back("OAI4"); - gate_list.push_back("MUX"); - gate_list.push_back("NMUX"); - } - if (g_arg_from_cmd) - cmd_error(args, g_argidx, stringf("Unsupported gate type: %s", g.c_str())); - else - log_cmd_error("Unsupported gate type: %s", g.c_str()); - ok_gate: - gate_list.push_back(g); - ok_alias: - for (auto gate : gate_list) { - if (remove_gates) - enabled_gates.erase(gate); - else - enabled_gates.insert(gate); - } - } - } - if (!lut_costs.empty() && !liberty_file.empty()) - log_cmd_error("Got -lut and -liberty! These two options are exclusive.\n"); + log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n"); if (!constr_file.empty() && liberty_file.empty()) log_cmd_error("Got -constr but no -liberty!\n"); @@ -1857,9 +1799,9 @@ struct AbcPass : public Pass { signal_init.clear(); for (Wire *wire : mod->wires()) - if (wire->attributes.count(ID::init)) { + if (wire->attributes.count(ID(init))) { SigSpec initsig = assign_map(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) switch (initval[i]) { case State::S0: @@ -1918,14 +1860,14 @@ struct AbcPass : public Pass { if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { - key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID::C)), true, RTLIL::SigSpec()); + key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); } else if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) { bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID::C)), this_en_pol, assign_map(cell->getPort(ID::E))); + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E)))); } else continue; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 127f8934e3d..8276c3c16f8 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * (C) 2019 Eddie Hung + * 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -22,85 +22,812 @@ // Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification // http://www.eecs.berkeley.edu/~alanmi/abc/ +#if 0 +// Based on &flow3 - better QoR but more experimental +#define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \ + "&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ + "&mfs; &ps -l" +#else +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" +#endif + + +#define ABC_FAST_COMMAND_LUT "&st; &if {W} {D}" + #include "kernel/register.h" +#include "kernel/sigtools.h" #include "kernel/celltypes.h" -#include "kernel/rtlil.h" +#include "kernel/cost.h" #include "kernel/log.h" +#include +#include +#include +#include +#include +#include -// abc9_exe.cc -std::string fold_abc9_cmd(std::string str); +#ifndef _WIN32 +# include +# include +#endif + +#include "frontends/aiger/aigerparse.h" +#include "kernel/utils.h" + +#ifdef YOSYS_LINK_ABC +extern "C" int Abc_RealMain(int argc, char *argv[]); +#endif USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -struct Abc9Pass : public ScriptPass +bool markgroups; +int map_autoidx; +SigMap assign_map; +RTLIL::Module *module; + +bool clk_polarity, en_polarity; +RTLIL::SigSpec clk_sig, en_sig; + +inline std::string remap_name(RTLIL::IdString abc9_name) +{ + return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); +} + +void handle_loops(RTLIL::Design *design) +{ + Pass::call(design, "scc -set_attr abc9_scc_id {}"); + + // For every unique SCC found, (arbitrarily) find the first + // cell in the component, and select (and mark) all its output + // wires + pool ids_seen; + for (auto cell : module->cells()) { + auto it = cell->attributes.find(ID(abc9_scc_id)); + if (it != cell->attributes.end()) { + auto r = ids_seen.insert(it->second); + if (r.second) { + for (auto &c : cell->connections_) { + if (c.second.is_fully_const()) continue; + if (cell->output(c.first)) { + SigBit b = c.second.as_bit(); + Wire *w = b.wire; + if (w->port_input) { + // In this case, hopefully the loop break has been already created + // Get the non-prefixed wire + Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str())); + log_assert(wo != nullptr); + log_assert(wo->port_output); + log_assert(b.offset < GetSize(wo)); + c.second = RTLIL::SigBit(wo, b.offset); + } + else { + // Create a new output/input loop break + w->port_input = true; + w = module->wire(stringf("%s.abco", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire)); + w->port_output = true; + } + else { + log_assert(w->port_input); + log_assert(b.offset < GetSize(w)); + } + w->set_bool_attribute(ID(abc9_scc_break)); + c.second = RTLIL::SigBit(w, b.offset); + } + } + } + } + cell->attributes.erase(it); + } + } + + module->fixup_ports(); +} + +std::string add_echos_to_abc9_cmd(std::string str) +{ + std::string new_str, token; + for (size_t i = 0; i < str.size(); i++) { + token += str[i]; + if (str[i] == ';') { + while (i+1 < str.size() && str[i+1] == ' ') + i++; + new_str += "echo + " + token + " " + token + " "; + token.clear(); + } + } + + if (!token.empty()) { + if (!new_str.empty()) + new_str += "echo + " + token + "; "; + new_str += token; + } + + return new_str; +} + +std::string fold_abc9_cmd(std::string str) +{ + std::string token, new_str = " "; + int char_counter = 10; + + for (size_t i = 0; i <= str.size(); i++) { + if (i < str.size()) + token += str[i]; + if (i == str.size() || str[i] == ';') { + if (char_counter + token.size() > 75) + new_str += "\n ", char_counter = 14; + new_str += token, char_counter += token.size(); + token.clear(); + } + } + + return new_str; +} + +std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) +{ + if (show_tempdir) + return text; + + while (1) { + size_t pos = text.find(tempdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "" + text.substr(pos + GetSize(tempdir_name)); + } + + std::string selfdir_name = proc_self_dirname(); + if (selfdir_name != "/") { + while (1) { + size_t pos = text.find(selfdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "/" + text.substr(pos + GetSize(selfdir_name)); + } + } + + return text; +} + +struct abc9_output_filter { - Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { } - void on_register() override + bool got_cr; + int escape_seq_state; + std::string linebuf; + std::string tempdir_name; + bool show_tempdir; + + abc9_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) + { + got_cr = false; + escape_seq_state = 0; + } + + void next_char(char ch) + { + if (escape_seq_state == 0 && ch == '\033') { + escape_seq_state = 1; + return; + } + if (escape_seq_state == 1) { + escape_seq_state = ch == '[' ? 2 : 0; + return; + } + if (escape_seq_state == 2) { + if ((ch < '0' || '9' < ch) && ch != ';') + escape_seq_state = 0; + return; + } + escape_seq_state = 0; + if (ch == '\r') { + got_cr = true; + return; + } + if (ch == '\n') { + log("ABC: %s\n", replace_tempdir(linebuf, tempdir_name, show_tempdir).c_str()); + got_cr = false, linebuf.clear(); + return; + } + if (got_cr) + got_cr = false, linebuf.clear(); + linebuf += ch; + } + + void next_line(const std::string &line) + { + //int pi, po; + //if (sscanf(line.c_str(), "Start-point = pi%d. End-point = po%d.", &pi, &po) == 2) { + // log("ABC: Start-point = pi%d (%s). End-point = po%d (%s).\n", + // pi, pi_map.count(pi) ? pi_map.at(pi).c_str() : "???", + // po, po_map.count(po) ? po_map.at(po).c_str() : "???"); + // return; + //} + + for (char ch : line) + next_char(ch); + } +}; + +void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, + bool cleanup, vector lut_costs, bool dff_mode, std::string clk_str, + bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, + bool show_tempdir, std::string box_file, std::string lut_file, + std::string wire_delay, const dict &box_lookup, bool nomfs +) +{ + module = current_module; + map_autoidx = autoidx++; + + if (clk_str != "$") + { + clk_polarity = true; + clk_sig = RTLIL::SigSpec(); + + en_polarity = true; + en_sig = RTLIL::SigSpec(); + } + + if (!clk_str.empty() && clk_str != "$") + { + if (clk_str.find(',') != std::string::npos) { + int pos = clk_str.find(','); + std::string en_str = clk_str.substr(pos+1); + clk_str = clk_str.substr(0, pos); + if (en_str[0] == '!') { + en_polarity = false; + en_str = en_str.substr(1); + } + if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) + en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); + } + if (clk_str[0] == '!') { + clk_polarity = false; + clk_str = clk_str.substr(1); + } + if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0) + clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0)); + } + + if (dff_mode && clk_sig.empty()) + log_cmd_error("Clock domain %s not found.\n", clk_str.c_str()); + + std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; + if (!cleanup) + tempdir_name[0] = tempdir_name[4] = '_'; + tempdir_name = make_temp_dir(tempdir_name); + log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", + module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); + + std::string abc9_script; + + if (!lut_costs.empty()) { + abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); + if (!box_file.empty()) + abc9_script += stringf("read_box -v %s; ", box_file.c_str()); + } + else + if (!lut_file.empty()) { + abc9_script += stringf("read_lut %s; ", lut_file.c_str()); + if (!box_file.empty()) + abc9_script += stringf("read_box -v %s; ", box_file.c_str()); + } + else + log_abort(); + + abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); + + if (!script_file.empty()) { + if (script_file[0] == '+') { + for (size_t i = 1; i < script_file.size(); i++) + if (script_file[i] == '\'') + abc9_script += "'\\''"; + else if (script_file[i] == ',') + abc9_script += " "; + else + abc9_script += script_file[i]; + } else + abc9_script += stringf("source %s", script_file.c_str()); + } else if (!lut_costs.empty() || !lut_file.empty()) { + //bool all_luts_cost_same = true; + //for (int this_cost : lut_costs) + // if (this_cost != lut_costs.front()) + // all_luts_cost_same = false; + abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; + //if (all_luts_cost_same && !fast_mode) + // abc9_script += "; lutpack {S}"; + } else + log_abort(); + + //if (script_file.empty() && !delay_target.empty()) + // for (size_t pos = abc9_script.find("dretime;"); pos != std::string::npos; pos = abc9_script.find("dretime;", pos+1)) + // abc9_script = abc9_script.substr(0, pos) + "dretime; retime -o {D};" + abc9_script.substr(pos+8); + + for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos)) + abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3); + + //for (size_t pos = abc9_script.find("{S}"); pos != std::string::npos; pos = abc9_script.find("{S}", pos)) + // abc9_script = abc9_script.substr(0, pos) + lutin_shared + abc9_script.substr(pos+3); + + for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos)) + abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3); + + if (nomfs) + for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) + abc9_script = abc9_script.erase(pos, strlen("&mfs")); + + abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); + abc9_script = add_echos_to_abc9_cmd(abc9_script); + + for (size_t i = 0; i+1 < abc9_script.size(); i++) + if (abc9_script[i] == ';' && abc9_script[i+1] == ' ') + abc9_script[i+1] = '\n'; + + FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); + fprintf(f, "%s\n", abc9_script.c_str()); + fclose(f); + + if (dff_mode || !clk_str.empty()) { - RTLIL::constpad["abc9.script.default"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -v; &mfs"; - RTLIL::constpad["abc9.script.default.area"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -a -v; &mfs"; - RTLIL::constpad["abc9.script.default.fast"] = "+&if {C} {W} {D} {R} -v"; - // Based on ABC's &flow - RTLIL::constpad["abc9.script.flow"] = "+&scorr; &sweep;" \ - "&dch -C 500;" \ - /* Round 1 */ \ - /* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ - "&st; &dsdb;" \ - /* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ - "&st; &syn2 -m -R 10; &dsdb;" \ - "&blut -a -K 6;" \ - /* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ - /* Round 2 */ \ - "&st; &sopb;" \ - /* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ - "&st; &dsdb;" \ - /* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ - "&st; &syn2 -m -R 10; &dsdb;" \ - "&blut -a -K 6;" \ - /* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ - /* Round 3 */ \ - /* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ - "&st; &dsdb;" \ - /* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ - "&st; &syn2 -m -R 10; &dsdb;" \ - "&blut -a -K 6;" \ - /* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;"; - // Based on ABC's &flow2 - RTLIL::constpad["abc9.script.flow2"] = "+&scorr; &sweep;" \ - /* Comm1 */ "&synch2 -K 6 -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\ - /* Comm2 */ "&dch -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\ - "&load; &st; &sopb -R 10 -C 4; " \ - /* Comm3 */ "&synch2 -K 6 -C 500; &if -m "/*"-E 5"*/" {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\ - /* Comm2 */ "&dch -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save; "\ - "&load"; - // Based on ABC's &flow3 - RTLIL::constpad["abc9.script.flow3"] = "+&scorr; &sweep;" \ - "&if {C} {W} {D}; &save; &st; &syn2; &if {C} {W} {D} {R} -v; &save; &load;"\ - "&st; &if {C} -g -K 6; &dch -f; &if {C} {W} {D} {R} -v; &save; &load;"\ - "&st; &if {C} -g -K 6; &synch2; &if {C} {W} {D} {R} -v; &save; &load;"\ - "&mfs"; + if (clk_sig.size() == 0) + log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching"); + else { + log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); + if (en_sig.size() != 0) + log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); + log("\n"); + } } - void help() override + + bool count_output = false; + for (auto port_name : module->ports) { + RTLIL::Wire *port_wire = module->wire(port_name); + log_assert(port_wire); + if (port_wire->port_output) { + count_output = true; + break; + } + } + + log_push(); + + if (count_output) + { + design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = design->selection_stack.back(); + sel.select(module); + + handle_loops(design); + + Pass::call(design, "aigmap"); + + //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", + // count_gates, GetSize(signal_list), count_input, count_output); + + Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); + + std::string buffer; + std::ifstream ifs; +#if 0 + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig"); + ifs.open(buffer); + if (ifs.fail()) + log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); + log_assert(!design->module(ID($__abc9__))); + { + AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); + reader.parse_xaiger(); + } + ifs.close(); + Pass::call(design, stringf("write_verilog -noexpr -norename")); + design->remove(design->module(ID($__abc9__))); +#endif + + design->selection_stack.pop_back(); + + log_header(design, "Executing ABC9.\n"); + + if (!lut_costs.empty()) { + buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); + f = fopen(buffer.c_str(), "wt"); + if (f == NULL) + log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); + for (int i = 0; i < GetSize(lut_costs); i++) + fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i)); + fclose(f); + } + + buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str()); + log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str()); + +#ifndef YOSYS_LINK_ABC + abc9_output_filter filt(tempdir_name, show_tempdir); + int ret = run_command(buffer, std::bind(&abc9_output_filter::next_line, filt, std::placeholders::_1)); +#else + // These needs to be mutable, supposedly due to getopt + char *abc9_argv[5]; + string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str()); + abc9_argv[0] = strdup(exe_file.c_str()); + abc9_argv[1] = strdup("-s"); + abc9_argv[2] = strdup("-f"); + abc9_argv[3] = strdup(tmp_script_name.c_str()); + abc9_argv[4] = 0; + int ret = Abc_RealMain(4, abc9_argv); + free(abc9_argv[0]); + free(abc9_argv[1]); + free(abc9_argv[2]); + free(abc9_argv[3]); +#endif + if (ret != 0) + log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); + + buffer = stringf("%s/%s", tempdir_name.c_str(), "output.aig"); + ifs.open(buffer, std::ifstream::binary); + if (ifs.fail()) + log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); + + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); + log_assert(!design->module(ID($__abc9__))); + + AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); + reader.parse_xaiger(box_lookup); + ifs.close(); + +#if 0 + Pass::call(design, stringf("write_verilog -noexpr -norename")); +#endif + + log_header(design, "Re-integrating ABC9 results.\n"); + RTLIL::Module *mapped_mod = design->module(ID($__abc9__)); + if (mapped_mod == NULL) + log_error("ABC output file does not contain a module `$__abc9__'.\n"); + + pool output_bits; + for (auto &it : mapped_mod->wires_) { + RTLIL::Wire *w = it.second; + RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); + if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx; + if (w->port_output) { + RTLIL::Wire *wire = module->wire(w->name); + log_assert(wire); + for (int i = 0; i < GetSize(w); i++) + output_bits.insert({wire, i}); + } + } + + for (auto &it : module->connections_) { + auto &signal = it.first; + auto bits = signal.bits(); + for (auto &b : bits) + if (output_bits.count(b)) + b = module->addWire(NEW_ID); + signal = std::move(bits); + } + + dict abc9_box; + vector boxes; + for (const auto &it : module->cells_) { + auto cell = it.second; + if (cell->type.in(ID($_AND_), ID($_NOT_))) { + module->remove(cell); + continue; + } + auto jt = abc9_box.find(cell->type); + if (jt == abc9_box.end()) { + RTLIL::Module* box_module = design->module(cell->type); + jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; + } + if (jt->second) + boxes.emplace_back(cell); + } + + dict> bit_drivers, bit_users; + TopoSort toposort; + dict not2drivers; + dict> bit2sinks; + + std::map cell_stats; + for (auto c : mapped_mod->cells()) + { + toposort.node(c->name); + + RTLIL::Cell *cell = nullptr; + if (c->type == ID($_NOT_)) { + RTLIL::SigBit a_bit = c->getPort(ID::A); + RTLIL::SigBit y_bit = c->getPort(ID::Y); + bit_users[a_bit].insert(c->name); + bit_drivers[y_bit].insert(c->name); + + if (!a_bit.wire) { + c->setPort(ID::Y, module->addWire(NEW_ID)); + RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); + log_assert(wire); + module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1); + } + else if (!lut_costs.empty() || !lut_file.empty()) { + RTLIL::Cell* driver_lut = nullptr; + // ABC can return NOT gates that drive POs + if (!a_bit.wire->port_input) { + // If it's not a NOT gate that that comes from a PI directly, + // find the driver LUT and clone that to guarantee that we won't + // increase the max logic depth + // (TODO: Optimise by not cloning unless will increase depth) + RTLIL::IdString driver_name; + if (GetSize(a_bit.wire) == 1) + driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); + else + driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); + driver_lut = mapped_mod->cell(driver_name); + } + + if (!driver_lut) { + // If a driver couldn't be found (could be from PI or box CI) + // then implement using a LUT + cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), + RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), + RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), + RTLIL::Const::from_string("01")); + bit2sinks[cell->getPort(ID::A)].push_back(cell); + cell_stats[ID($lut)]++; + } + else + not2drivers[c] = driver_lut; + continue; + } + else + log_abort(); + if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + continue; + } + cell_stats[c->type]++; + + RTLIL::Cell *existing_cell = nullptr; + if (c->type == ID($lut)) { + if (GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { + SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID::A).as_wire()->name)); + SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID::Y).as_wire()->name)); + module->connect(my_y, my_a); + if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx; + log_abort(); + continue; + } + cell = module->addCell(remap_name(c->name), c->type); + } + else { + existing_cell = module->cell(c->name); + log_assert(existing_cell); + cell = module->addCell(remap_name(c->name), c->type); + } + + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + if (existing_cell) { + cell->parameters = existing_cell->parameters; + cell->attributes = existing_cell->attributes; + } + else { + cell->parameters = c->parameters; + cell->attributes = c->attributes; + } + for (auto &conn : c->connections()) { + RTLIL::SigSpec newsig; + for (auto c : conn.second.chunks()) { + if (c.width == 0) + continue; + //log_assert(c.width == 1); + if (c.wire) + c.wire = module->wires_.at(remap_name(c.wire->name)); + newsig.append(c); + } + cell->setPort(conn.first, newsig); + + if (cell->input(conn.first)) { + for (auto i : newsig) + bit2sinks[i].push_back(cell); + for (auto i : conn.second) + bit_users[i].insert(c->name); + } + if (cell->output(conn.first)) + for (auto i : conn.second) + bit_drivers[i].insert(c->name); + } + } + + for (auto existing_cell : boxes) { + Cell *cell = module->cell(remap_name(existing_cell->name)); + if (cell) { + for (auto &conn : existing_cell->connections()) { + if (!conn.second.is_wire()) + continue; + Wire *wire = conn.second.as_wire(); + if (!wire->get_bool_attribute(ID(abc9_padding))) + continue; + cell->unsetPort(conn.first); + log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second)); + } + module->swap_names(cell, existing_cell); + } + module->remove(existing_cell); + } + + // Copy connections (and rename) from mapped_mod to module + for (auto conn : mapped_mod->connections()) { + if (!conn.first.is_fully_const()) { + auto chunks = conn.first.chunks(); + for (auto &c : chunks) + c.wire = module->wires_.at(remap_name(c.wire->name)); + conn.first = std::move(chunks); + } + if (!conn.second.is_fully_const()) { + auto chunks = conn.second.chunks(); + for (auto &c : chunks) + if (c.wire) + c.wire = module->wires_.at(remap_name(c.wire->name)); + conn.second = std::move(chunks); + } + module->connect(conn); + } + + for (auto &it : cell_stats) + log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); + int in_wires = 0, out_wires = 0; + + // Stitch in mapped_mod's inputs/outputs into module + for (auto port : mapped_mod->ports) { + RTLIL::Wire *w = mapped_mod->wire(port); + RTLIL::Wire *wire = module->wire(port); + log_assert(wire); + RTLIL::Wire *remap_wire = module->wire(remap_name(port)); + RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); + log_assert(GetSize(signal) >= GetSize(remap_wire)); + + RTLIL::SigSig conn; + if (w->port_output) { + conn.first = signal; + conn.second = remap_wire; + out_wires++; + module->connect(conn); + } + else if (w->port_input) { + conn.first = remap_wire; + conn.second = signal; + in_wires++; + module->connect(conn); + } + } + + for (auto &it : bit_users) + if (bit_drivers.count(it.first)) + for (auto driver_cell : bit_drivers.at(it.first)) + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); + bool no_loops YS_ATTRIBUTE(unused) = toposort.sort(); + log_assert(no_loops); + + for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) { + RTLIL::Cell *not_cell = mapped_mod->cell(*ii); + log_assert(not_cell); + if (not_cell->type != ID($_NOT_)) + continue; + auto it = not2drivers.find(not_cell); + if (it == not2drivers.end()) + continue; + RTLIL::Cell *driver_lut = it->second; + RTLIL::SigBit a_bit = not_cell->getPort(ID::A); + RTLIL::SigBit y_bit = not_cell->getPort(ID::Y); + RTLIL::Const driver_mask; + + a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); + y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); + + auto jt = bit2sinks.find(a_bit); + if (jt == bit2sinks.end()) + goto clone_lut; + + for (auto sink_cell : jt->second) + if (sink_cell->type != ID($lut)) + goto clone_lut; + + // Push downstream LUTs past inverter + for (auto sink_cell : jt->second) { + SigSpec A = sink_cell->getPort(ID::A); + RTLIL::Const mask = sink_cell->getParam(ID(LUT)); + int index = 0; + for (; index < GetSize(A); index++) + if (A[index] == a_bit) + break; + log_assert(index < GetSize(A)); + int i = 0; + while (i < GetSize(mask)) { + for (int j = 0; j < (1 << index); j++) + std::swap(mask[i+j], mask[i+j+(1 << index)]); + i += 1 << (index+1); + } + A[index] = y_bit; + sink_cell->setPort(ID::A, A); + sink_cell->setParam(ID(LUT), mask); + } + + // Since we have rewritten all sinks (which we know + // to be only LUTs) to be after the inverter, we can + // go ahead and clone the LUT with the expectation + // that the original driving LUT will become dangling + // and get cleaned away +clone_lut: + driver_mask = driver_lut->getParam(ID(LUT)); + for (auto &b : driver_mask.bits) { + if (b == RTLIL::State::S0) b = RTLIL::State::S1; + else if (b == RTLIL::State::S1) b = RTLIL::State::S0; + } + auto cell = module->addLut(NEW_ID, + driver_lut->getPort(ID::A), + y_bit, + driver_mask); + for (auto &bit : cell->connections_.at(ID::A)) { + bit.wire = module->wires_.at(remap_name(bit.wire->name)); + bit2sinks[bit].push_back(cell); + } + } + + // Now 'unexpose' those wires by undoing + // the expose operation -- remove them from PO/PI + // and re-connecting them back together + for (auto wire : module->wires()) { + auto it = wire->attributes.find(ID(abc9_scc_break)); + if (it != wire->attributes.end()) { + wire->attributes.erase(it); + log_assert(wire->port_output); + wire->port_output = false; + std::string name = wire->name.str(); + RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5)); + log_assert(i_wire); + log_assert(i_wire->port_input); + i_wire->port_input = false; + module->connect(i_wire, wire); + } + } + module->fixup_ports(); + + //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); + log("ABC RESULTS: input signals: %8d\n", in_wires); + log("ABC RESULTS: output signals: %8d\n", out_wires); + + design->remove(mapped_mod); + } + else + { + log("Don't call ABC as there is nothing to map.\n"); + } + + if (cleanup) + { + log("Removing temp directory.\n"); + remove_directory(tempdir_name); + } + + log_pop(); +} + +struct Abc9Pass : public Pass { + Abc9Pass() : Pass("abc9", "use ABC9 for technology mapping") { } + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" abc9 [options] [selection]\n"); log("\n"); - log("This script pass performs a sequence of commands to facilitate the use of the ABC\n"); - log("tool [1] for technology mapping of the current design to a target FPGA\n"); - log("architecture. Only fully-selected modules are supported.\n"); - log("\n"); - log(" -run :\n"); - log(" only run the commands between the labels (see below). an empty\n"); - log(" from label is synonymous to 'begin', and empty to label is\n"); - log(" synonymous to the end of the command list.\n"); + log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); + log("library to a target architecture.\n"); log("\n"); log(" -exe \n"); #ifdef ABCEXTERNAL log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); #else - log(" use the specified command instead of \"/%syosys-abc\" to execute ABC.\n", proc_program_prefix().c_str()); + log(" use the specified command instead of \"/yosys-abc\" to execute ABC.\n"); #endif log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n"); log("\n"); @@ -113,17 +840,26 @@ struct Abc9Pass : public ScriptPass log(" replaced with blanks before the string is passed to ABC.\n"); log("\n"); log(" if no -script parameter is given, the following scripts are used:\n"); - log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos)).c_str()); + log("\n"); + log(" for -lut/-luts (only one LUT size):\n"); + log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); + log("\n"); + log(" for -lut/-luts (different LUT sizes):\n"); + log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); log("\n"); log(" -fast\n"); log(" use different default scripts that are slightly faster (at the cost\n"); log(" of output quality):\n"); - log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)).c_str()); + log("\n"); + log(" for -lut/-luts:\n"); + log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str()); log("\n"); log(" -D \n"); log(" set delay target. the string {D} in the default scripts above is\n"); log(" replaced by this option when used, and an empty string otherwise\n"); log(" (indicating best possible delay).\n"); +// log(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); +// log(" default scripts above.\n"); log("\n"); // log(" -S \n"); // log(" maximum number of LUT inputs shared.\n"); @@ -145,15 +881,19 @@ struct Abc9Pass : public ScriptPass log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); log(" 2, 3, .. inputs.\n"); log("\n"); - log(" -maxlut \n"); - log(" when auto-generating the lut library, discard all luts equal to or\n"); - log(" greater than this size (applicable when neither -lut nor -luts is\n"); - log(" specified).\n"); - log("\n"); - log(" -dff\n"); - log(" also pass $_DFF_[NP]_ cells through to ABC. modules with many clock\n"); - log(" domains are supported and automatically partitioned by ABC.\n"); - log("\n"); +// log(" -dff\n"); +// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); +// log(" clock domains are automatically partitioned in clock domains and each\n"); +// log(" domain is passed through ABC independently.\n"); +// log("\n"); +// log(" -clk [!][,[!]]\n"); +// log(" use only the specified clock domain. this is like -dff, but only FF\n"); +// log(" cells that belong to the specified clock domain are used.\n"); +// log("\n"); +// log(" -keepff\n"); +// log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); +// log(" them, for example for equivalence checking.)\n"); +// log("\n"); log(" -nocleanup\n"); log(" when this option is used, the temporary files created by this pass\n"); log(" are not removed. this is useful for debugging.\n"); @@ -162,290 +902,409 @@ struct Abc9Pass : public ScriptPass log(" print the temp dir name in log. usually this is suppressed so that the\n"); log(" command output is identical across runs.\n"); log("\n"); + log(" -markgroups\n"); + log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n"); + log(" this attribute is a unique integer for each ABC process started. This\n"); + log(" is useful for debugging the partitioning of clock domains.\n"); + log("\n"); log(" -box \n"); - log(" pass this file with box library to ABC.\n"); + log(" pass this file with box library to ABC. Use with -lut.\n"); log("\n"); log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); log("ABC on logic snippets extracted from your design. You will not get any useful\n"); log("output when passing an ABC script that writes a file. Instead write your full\n"); - log("design as an XAIGER file with `write_xaiger' and then load that into ABC\n"); - log("externally if you want to use ABC to convert your design into another format.\n"); + log("design as BLIF file with write_blif and then load that into ABC externally if\n"); + log("you want to use ABC to convert your design into another format.\n"); log("\n"); log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); log("\n"); - help_script(); - log("\n"); } - - std::stringstream exe_cmd; - bool dff_mode, cleanup; - bool lut_mode; - int maxlut; - std::string box_file; - - void clear_flags() override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - exe_cmd.str(""); - exe_cmd << "abc9_exe"; - dff_mode = false; - cleanup = true; - lut_mode = false; - maxlut = 0; - box_file = ""; - } + log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n"); + log_push(); - void execute(std::vector args, RTLIL::Design *design) override - { - std::string run_from, run_to; - clear_flags(); + assign_map.clear(); - // get arguments from scratchpad first, then override by command arguments - dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode); - cleanup = !design->scratchpad_get_bool("abc9.nocleanup", !cleanup); +#ifdef ABCEXTERNAL + std::string exe_file = ABCEXTERNAL; +#else + std::string exe_file = proc_self_dirname() + "yosys-abc"; +#endif + std::string script_file, clk_str, box_file, lut_file; + std::string delay_target, lutin_shared = "-S 1", wire_delay; + bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; + bool show_tempdir = false; + bool nomfs = false; + vector lut_costs; + markgroups = false; - if (design->scratchpad_get_bool("abc9.debug")) { - cleanup = false; - exe_cmd << " -showtmp"; - } +#if 0 + cleanup = false; + show_tempdir = true; +#endif + +#ifdef _WIN32 +#ifndef ABCEXTERNAL + if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) + exe_file = proc_self_dirname() + "..\\yosys-abc"; +#endif +#endif size_t argidx; + char pwd [PATH_MAX]; + if (!getcwd(pwd, sizeof(pwd))) { + log_cmd_error("getcwd failed: %s\n", strerror(errno)); + log_abort(); + } for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; - if ((arg == "-exe" || arg == "-script" || arg == "-D" || - /*arg == "-S" ||*/ arg == "-lut" || arg == "-luts" || - /*arg == "-box" ||*/ arg == "-W") && - argidx+1 < args.size()) { - if (arg == "-lut" || arg == "-luts") - lut_mode = true; - exe_cmd << " " << arg << " " << args[++argidx]; + if (arg == "-exe" && argidx+1 < args.size()) { + exe_file = args[++argidx]; continue; } - if (arg == "-fast" || /* arg == "-dff" || */ - /* arg == "-nocleanup" || */ arg == "-showtmp") { - exe_cmd << " " << arg; + if (arg == "-script" && argidx+1 < args.size()) { + script_file = args[++argidx]; + rewrite_filename(script_file); + if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+') + script_file = std::string(pwd) + "/" + script_file; continue; } - if (arg == "-dff") { - dff_mode = true; - exe_cmd << " " << arg; + if (arg == "-D" && argidx+1 < args.size()) { + delay_target = "-D " + args[++argidx]; continue; } + //if (arg == "-S" && argidx+1 < args.size()) { + // lutin_shared = "-S " + args[++argidx]; + // continue; + //} + if (arg == "-lut" && argidx+1 < args.size()) { + string arg = args[++argidx]; + size_t pos = arg.find_first_of(':'); + int lut_mode = 0, lut_mode2 = 0; + if (pos != string::npos) { + lut_mode = atoi(arg.substr(0, pos).c_str()); + lut_mode2 = atoi(arg.substr(pos+1).c_str()); + } else { + pos = arg.find_first_of('.'); + if (pos != string::npos) { + lut_file = arg; + rewrite_filename(lut_file); + if (!lut_file.empty() && !is_absolute_path(lut_file)) + lut_file = std::string(pwd) + "/" + lut_file; + } + else { + lut_mode = atoi(arg.c_str()); + lut_mode2 = lut_mode; + } + } + lut_costs.clear(); + for (int i = 0; i < lut_mode; i++) + lut_costs.push_back(1); + for (int i = lut_mode; i < lut_mode2; i++) + lut_costs.push_back(2 << (i - lut_mode)); + continue; + } + if (arg == "-luts" && argidx+1 < args.size()) { + lut_costs.clear(); + for (auto &tok : split_tokens(args[++argidx], ",")) { + auto parts = split_tokens(tok, ":"); + if (GetSize(parts) == 0 && !lut_costs.empty()) + lut_costs.push_back(lut_costs.back()); + else if (GetSize(parts) == 1) + lut_costs.push_back(atoi(parts.at(0).c_str())); + else if (GetSize(parts) == 2) + while (GetSize(lut_costs) < atoi(parts.at(0).c_str())) + lut_costs.push_back(atoi(parts.at(1).c_str())); + else + log_cmd_error("Invalid -luts syntax.\n"); + } + continue; + } + if (arg == "-fast") { + fast_mode = true; + continue; + } + //if (arg == "-dff") { + // dff_mode = true; + // continue; + //} + //if (arg == "-clk" && argidx+1 < args.size()) { + // clk_str = args[++argidx]; + // dff_mode = true; + // continue; + //} + //if (arg == "-keepff") { + // keepff = true; + // continue; + //} if (arg == "-nocleanup") { cleanup = false; continue; } + if (arg == "-showtmp") { + show_tempdir = true; + continue; + } + if (arg == "-markgroups") { + markgroups = true; + continue; + } if (arg == "-box" && argidx+1 < args.size()) { box_file = args[++argidx]; continue; } - if (arg == "-maxlut" && argidx+1 < args.size()) { - maxlut = atoi(args[++argidx].c_str()); + if (arg == "-W" && argidx+1 < args.size()) { + wire_delay = "-W " + args[++argidx]; continue; } - if (arg == "-run" && argidx+1 < args.size()) { - size_t pos = args[argidx+1].find(':'); - if (pos == std::string::npos) - break; - run_from = args[++argidx].substr(0, pos); - run_to = args[argidx].substr(pos+1); + if (arg == "-nomfs") { + nomfs = true; continue; } break; } extra_args(args, argidx, design); - if (maxlut && lut_mode) - log_cmd_error("abc9 '-maxlut' option only applicable without '-lut' nor '-luts'.\n"); - - log_assert(design); - if (design->selected_modules().empty()) { - log_warning("No modules selected for ABC9 techmapping.\n"); - return; - } - - log_header(design, "Executing ABC9 pass.\n"); - log_push(); - - run_script(design, run_from, run_to); + // ABC expects a box file for XAIG + if (box_file.empty()) + box_file = "+/dummy.box"; - log_pop(); - } + rewrite_filename(box_file); + if (!box_file.empty() && !is_absolute_path(box_file)) + box_file = std::string(pwd) + "/" + box_file; - void script() override - { - if (check_label("check")) { - if (help_mode) - run("abc9_ops -check [-dff]", "(option if -dff)"); - else - run(stringf("abc9_ops -check %s", dff_mode ? "-dff" : "")); - } + dict box_lookup; + for (auto m : design->modules()) { + auto it = m->attributes.find(ID(abc9_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 abc9_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); + log_assert(r.second); - if (check_label("map")) { - if (help_mode) - run("abc9_ops -prep_hier -prep_bypass [-prep_dff -dff]", "(option if -dff)"); - else - run(stringf("abc9_ops -prep_hier -prep_bypass %s", dff_mode ? "-prep_dff -dff" : "")); - if (dff_mode) { - run("design -copy-to $abc9_map @$abc9_flops", "(only if -dff)"); - run("select -unset $abc9_flops", " (only if -dff)"); - } - run("design -stash $abc9"); - run("design -load $abc9_map"); - run("proc"); - run("wbflip"); - run("techmap"); - run("opt"); - if (dff_mode || help_mode) { - if (!help_mode) - active_design->scratchpad_unset("abc9_ops.prep_dff_submod.did_something"); - run("abc9_ops -prep_dff_submod", " (only if -dff)"); // rewrite specify - bool did_something = help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_dff_submod.did_something"); - if (did_something) { - // select all $_DFF_[NP]_ - // then select all its fanins - // then select all fanouts of all that - // lastly remove $_DFF_[NP]_ cells - run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d", " (only if -dff)"); - run("submod", " (only if -dff)"); - run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop", "(only if -dff)"); - if (help_mode) { - run("foreach module in design"); - run(" rename _$abc9_flop _TECHMAP_REPLACE_", " (only if -dff)"); + RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; + for (auto p : m->ports) { + auto w = m->wire(p); + log_assert(w); + if (w->attributes.count(ID(abc9_carry))) { + if (w->port_input) { + if (carry_in) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + carry_in = w; } - else { - // Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs - for (auto module : active_design->selected_modules()) { - active_design->selected_active_module = module->name.str(); - if (module->cell(stringf("%s_$abc9_flop", module->name.c_str()))) - run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str())); - } - active_design->selected_active_module.clear(); + else if (w->port_output) { + if (carry_out) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + carry_out = w; + } + } + } + if (carry_in || carry_out) { + if (carry_in && !carry_out) + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); + if (!carry_in && carry_out) + log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); + // Make carry_in the last PI, and carry_out the last PO + // since ABC requires it this way + auto &ports = m->ports; + for (auto it = ports.begin(); it != ports.end(); ) { + RTLIL::Wire* w = m->wire(*it); + log_assert(w); + if (w == carry_in || w == carry_out) { + it = ports.erase(it); + continue; } - run("abc9_ops -prep_dff_unmap", " (only if -dff)"); - run("design -copy-to $abc9 =*_$abc9_flop", " (only if -dff)"); // copy submod out - run("delete =*_$abc9_flop", " (only if -dff)"); + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); + ++it; } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); } - run("design -stash $abc9_map"); - run("design -load $abc9"); - run("design -delete $abc9"); - if (help_mode) - run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v [-D DFF]", "(option if -dff)"); - else - run(stringf("techmap -wb -max_iter 1 -map %%$abc9_map -map +/abc9_map.v %s", dff_mode ? "-D DFF" : "")); - run("design -delete $abc9_map"); } - if (check_label("pre")) { - run("read_verilog -icells -lib -specify +/abc9_model.v"); - run("scc -set_attr abc9_scc_id {}"); - if (help_mode) - run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)"); - else - run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : "")); - if (help_mode) - run("abc9_ops -prep_lut ", "(skip if -lut or -luts)"); - else if (!lut_mode) - run(stringf("abc9_ops -prep_lut %d", maxlut)); - if (help_mode) - run("abc9_ops -prep_box", "(skip if -box)"); - else if (box_file.empty()) - run("abc9_ops -prep_box"); - if (saved_designs.count("$abc9_holes") || help_mode) { - run("design -stash $abc9"); - run("design -load $abc9_holes"); - run("techmap -wb -map %$abc9 -map +/techmap.v"); - run("opt -purge"); - run("aigmap"); - run("design -stash $abc9_holes"); - run("design -load $abc9"); - run("design -delete $abc9"); + for (auto mod : design->selected_modules()) + { + if (mod->attributes.count(ID(abc9_box_id))) + continue; + + if (mod->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(mod)); + continue; } - } - if (check_label("exe")) { - run("aigmap"); - if (help_mode) { - run("foreach module in selection"); - run(" abc9_ops -write_lut /input.lut", "(skip if '-lut' or '-luts')"); - run(" abc9_ops -write_box /input.box", "(skip if '-box')"); - run(" write_xaiger -map /input.sym [-dff] /input.xaig"); - run(" abc9_exe [options] -cwd -lut [/input.lut] -box [/input.box]"); - run(" read_aiger -xaiger -wideports -module_name $abc9 -map /input.sym /output.aig"); - run(" abc9_ops -reintegrate [-dff]"); + assign_map.set(mod); + + if (!dff_mode || !clk_str.empty()) { + abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, + delay_target, lutin_shared, fast_mode, show_tempdir, + box_file, lut_file, wire_delay, box_lookup, nomfs); + continue; } - else { - auto selected_modules = active_design->selected_modules(); - active_design->selection_stack.emplace_back(false); - for (auto mod : selected_modules) { - if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); - continue; - } + CellTypes ct(design); - log_push(); - active_design->selection().select(mod); - - if (!active_design->selected_whole_module(mod)) - log_error("Can't handle partially selected module %s!\n", log_id(mod)); - - std::string tempdir_name = "/tmp/" + proc_program_prefix() + "yosys-abc-XXXXXX"; - if (!cleanup) - tempdir_name[0] = tempdir_name[4] = '_'; - tempdir_name = make_temp_dir(tempdir_name); - - if (!lut_mode) - run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); - if (box_file.empty()) - run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str())); - run_nocheck(stringf("write_xaiger -map %s/input.sym %s %s/input.xaig", tempdir_name.c_str(), dff_mode ? "-dff" : "", tempdir_name.c_str())); - - int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); - - log("Extracted %d AND gates and %d wires from module `%s' to a netlist network with %d inputs and %d outputs.\n", - active_design->scratchpad_get_int("write_xaiger.num_ands"), - active_design->scratchpad_get_int("write_xaiger.num_wires"), - log_id(mod), - active_design->scratchpad_get_int("write_xaiger.num_inputs"), - num_outputs); - if (num_outputs) { - std::string abc9_exe_cmd; - abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str()); - if (!lut_mode) - abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str()); - if (box_file.empty()) - abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str()); - else - abc9_exe_cmd += stringf(" -box %s", box_file.c_str()); - run_nocheck(abc9_exe_cmd); - run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str())); - run_nocheck(stringf("abc9_ops -reintegrate %s", dff_mode ? "-dff" : "")); - } - else - log("Don't call ABC as there is nothing to map.\n"); + std::vector all_cells = mod->selected_cells(); + std::set unassigned_cells(all_cells.begin(), all_cells.end()); + + std::set expand_queue, next_expand_queue; + std::set expand_queue_up, next_expand_queue_up; + std::set expand_queue_down, next_expand_queue_down; + + typedef tuple clkdomain_t; + std::map> assigned_cells; + std::map assigned_cells_reverse; - if (cleanup) { - log("Removing temp directory.\n"); - remove_directory(tempdir_name); + std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + + for (auto cell : all_cells) + { + clkdomain_t key; + + for (auto &conn : cell->connections()) + for (auto bit : conn.second) { + bit = assign_map(bit); + if (bit.wire != nullptr) { + cell_to_bit[cell].insert(bit); + bit_to_cell[bit].insert(cell); + if (ct.cell_input(cell->type, conn.first)) { + cell_to_bit_up[cell].insert(bit); + bit_to_cell_down[bit].insert(cell); + } + if (ct.cell_output(cell->type, conn.first)) { + cell_to_bit_down[cell].insert(bit); + bit_to_cell_up[bit].insert(cell); + } } - mod->check(); - active_design->selection().selected_modules.clear(); - log_pop(); } - active_design->selection_stack.pop_back(); + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) + { + key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); + } + else + if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + { + bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); + bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E)))); + } + else + continue; + + unassigned_cells.erase(cell); + expand_queue.insert(cell); + expand_queue_up.insert(cell); + expand_queue_down.insert(cell); + + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; } - } - if (check_label("unmap")) { - run("techmap -wb -map %$abc9_unmap -map +/abc9_unmap.v"); // techmap user design from submod back to original cell - // ($_DFF_[NP]_ already shorted by -reintegrate) - run("design -delete $abc9_unmap"); - if (saved_designs.count("$abc9_holes") || help_mode) - run("design -delete $abc9_holes"); + while (!expand_queue_up.empty() || !expand_queue_down.empty()) + { + if (!expand_queue_up.empty()) + { + RTLIL::Cell *cell = *expand_queue_up.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_up.erase(cell); + + for (auto bit : cell_to_bit_up[cell]) + for (auto c : bit_to_cell_up[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (!expand_queue_down.empty()) + { + RTLIL::Cell *cell = *expand_queue_down.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_down.erase(cell); + + for (auto bit : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (expand_queue_up.empty() && expand_queue_down.empty()) { + expand_queue_up.swap(next_expand_queue_up); + expand_queue_down.swap(next_expand_queue_down); + } + } + + while (!expand_queue.empty()) + { + RTLIL::Cell *cell = *expand_queue.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue.erase(cell); + + for (auto bit : cell_to_bit.at(cell)) { + for (auto c : bit_to_cell[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + } + bit_to_cell[bit].clear(); + } + + if (expand_queue.empty()) + expand_queue.swap(next_expand_queue); + } + + clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); + for (auto cell : unassigned_cells) { + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; + } + + log_header(design, "Summary of detected clock domains:\n"); + for (auto &it : assigned_cells) + log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), + std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), + std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + + for (auto &it : assigned_cells) { + clk_polarity = std::get<0>(it.first); + clk_sig = assign_map(std::get<1>(it.first)); + en_polarity = std::get<2>(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(), "$", + keepff, delay_target, lutin_shared, fast_mode, show_tempdir, + box_file, lut_file, wire_delay, box_lookup, nomfs); + assign_map.set(mod); + } } + + assign_map.clear(); + + log_pop(); } } Abc9Pass; diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc deleted file mode 100644 index 7355840aa97..00000000000 --- a/passes/techmap/abc9_exe.cc +++ /dev/null @@ -1,549 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * 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. - * - */ - -// [[CITE]] ABC -// Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification -// http://www.eecs.berkeley.edu/~alanmi/abc/ - -#include "kernel/register.h" -#include "kernel/log.h" - -#ifndef _WIN32 -# include -# include -#endif - -#ifdef YOSYS_LINK_ABC -extern "C" int Abc_RealMain(int argc, char *argv[]); -#endif - -std::string fold_abc9_cmd(std::string str) -{ - std::string token, new_str = " "; - int char_counter = 10; - - for (size_t i = 0; i <= str.size(); i++) { - if (i < str.size()) - token += str[i]; - if (i == str.size() || str[i] == ';') { - if (char_counter + token.size() > 75) - new_str += "\n ", char_counter = 14; - new_str += token, char_counter += token.size(); - token.clear(); - } - } - - return new_str; -} - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -std::string add_echos_to_abc9_cmd(std::string str) -{ - std::string new_str, token; - for (size_t i = 0; i < str.size(); i++) { - token += str[i]; - if (str[i] == ';') { - while (i+1 < str.size() && str[i+1] == ' ') - i++; - new_str += "echo + " + token + " " + token + " "; - token.clear(); - } - } - - if (!token.empty()) { - if (!new_str.empty()) - new_str += "echo + " + token + "; "; - new_str += token; - } - - return new_str; -} - -std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) -{ - if (show_tempdir) - return text; - - while (1) { - size_t pos = text.find(tempdir_name); - if (pos == std::string::npos) - break; - text = text.substr(0, pos) + "" + text.substr(pos + GetSize(tempdir_name)); - } - - std::string selfdir_name = proc_self_dirname(); - if (selfdir_name != "/") { - while (1) { - size_t pos = text.find(selfdir_name); - if (pos == std::string::npos) - break; - text = text.substr(0, pos) + "/" + text.substr(pos + GetSize(selfdir_name)); - } - } - - return text; -} - -struct abc9_output_filter -{ - bool got_cr; - int escape_seq_state; - std::string linebuf; - std::string tempdir_name; - bool show_tempdir; - - abc9_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) - { - got_cr = false; - escape_seq_state = 0; - } - - void next_char(char ch) - { - if (escape_seq_state == 0 && ch == '\033') { - escape_seq_state = 1; - return; - } - if (escape_seq_state == 1) { - escape_seq_state = ch == '[' ? 2 : 0; - return; - } - if (escape_seq_state == 2) { - if ((ch < '0' || '9' < ch) && ch != ';') - escape_seq_state = 0; - return; - } - escape_seq_state = 0; - if (ch == '\r') { - got_cr = true; - return; - } - if (ch == '\n') { - log("ABC: %s\n", replace_tempdir(linebuf, tempdir_name, show_tempdir).c_str()); - got_cr = false, linebuf.clear(); - return; - } - if (got_cr) - got_cr = false, linebuf.clear(); - linebuf += ch; - } - - void next_line(const std::string &line) - { - //int pi, po; - //if (sscanf(line.c_str(), "Start-point = pi%d. End-point = po%d.", &pi, &po) == 2) { - // log("ABC: Start-point = pi%d (%s). End-point = po%d (%s).\n", - // pi, pi_map.count(pi) ? pi_map.at(pi).c_str() : "???", - // po, po_map.count(po) ? po_map.at(po).c_str() : "???"); - // return; - //} - - for (char ch : line) - next_char(ch); - } -}; - -void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe_file, - vector lut_costs, bool dff_mode, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, - bool show_tempdir, std::string box_file, std::string lut_file, - std::string wire_delay, std::string tempdir_name -) -{ - std::string abc9_script; - - if (!lut_costs.empty()) - abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); - else if (!lut_file.empty()) - abc9_script += stringf("read_lut %s; ", lut_file.c_str()); - else - log_abort(); - - log_assert(!box_file.empty()); - abc9_script += stringf("read_box %s; ", box_file.c_str()); - abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); - - if (!script_file.empty()) { - if (script_file[0] == '+') { - for (size_t i = 1; i < script_file.size(); i++) - if (script_file[i] == '\'') - abc9_script += "'\\''"; - else if (script_file[i] == ',') - abc9_script += " "; - else - abc9_script += script_file[i]; - } else - abc9_script += stringf("source %s", script_file.c_str()); - } else if (!lut_costs.empty() || !lut_file.empty()) { - abc9_script += fast_mode ? RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos) - : RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos); - } else - log_abort(); - - for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos)) - abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3); - - //for (size_t pos = abc9_script.find("{S}"); pos != std::string::npos; pos = abc9_script.find("{S}", pos)) - // abc9_script = abc9_script.substr(0, pos) + lutin_shared + abc9_script.substr(pos+3); - - for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos)) - abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3); - - std::string C; - if (design->scratchpad.count("abc9.if.C")) - C = "-C " + design->scratchpad_get_string("abc9.if.C"); - for (size_t pos = abc9_script.find("{C}"); pos != std::string::npos; pos = abc9_script.find("{C}", pos)) - abc9_script = abc9_script.substr(0, pos) + C + abc9_script.substr(pos+3); - - std::string R; - if (design->scratchpad.count("abc9.if.R")) - R = "-R " + design->scratchpad_get_string("abc9.if.R"); - for (size_t pos = abc9_script.find("{R}"); pos != std::string::npos; pos = abc9_script.find("{R}", pos)) - abc9_script = abc9_script.substr(0, pos) + R + abc9_script.substr(pos+3); - - if (design->scratchpad_get_bool("abc9.nomfs")) - for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) - abc9_script = abc9_script.erase(pos, strlen("&mfs")); - else { - auto s = stringf("&write -n %s/output.aig; ", tempdir_name.c_str()); - for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) { - abc9_script = abc9_script.insert(pos, s); - pos += GetSize(s) + strlen("&mfs"); - } - } - - abc9_script += stringf("; &ps -l; &write -n %s/output.aig", tempdir_name.c_str()); - if (design->scratchpad_get_bool("abc9.verify")) { - if (dff_mode) - abc9_script += "; &verify -s"; - else - abc9_script += "; &verify"; - } - abc9_script += "; time"; - abc9_script = add_echos_to_abc9_cmd(abc9_script); - - for (size_t i = 0; i+1 < abc9_script.size(); i++) - if (abc9_script[i] == ';' && abc9_script[i+1] == ' ') - abc9_script[i+1] = '\n'; - - FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); - fprintf(f, "%s\n", abc9_script.c_str()); - fclose(f); - - std::string buffer; - - log_header(design, "Executing ABC9.\n"); - - if (!lut_costs.empty()) { - buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); - f = fopen(buffer.c_str(), "wt"); - if (f == NULL) - log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); - for (int i = 0; i < GetSize(lut_costs); i++) - fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i)); - fclose(f); - } - - buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str()); - log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str()); - -#ifndef YOSYS_LINK_ABC - abc9_output_filter filt(tempdir_name, show_tempdir); - int ret = run_command(buffer, std::bind(&abc9_output_filter::next_line, filt, std::placeholders::_1)); -#else - // These needs to be mutable, supposedly due to getopt - char *abc9_argv[5]; - string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str()); - abc9_argv[0] = strdup(exe_file.c_str()); - abc9_argv[1] = strdup("-s"); - abc9_argv[2] = strdup("-f"); - abc9_argv[3] = strdup(tmp_script_name.c_str()); - abc9_argv[4] = 0; - int ret = Abc_RealMain(4, abc9_argv); - free(abc9_argv[0]); - free(abc9_argv[1]); - free(abc9_argv[2]); - free(abc9_argv[3]); -#endif - if (ret != 0) { - if (check_file_exists(stringf("%s/output.aig", tempdir_name.c_str()))) - log_warning("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); - else - log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); - } -} - -struct Abc9ExePass : public Pass { - Abc9ExePass() : Pass("abc9_exe", "use ABC9 for technology mapping") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" abc9_exe [options]\n"); - log("\n"); - log(" \n"); - log("This pass uses the ABC tool [1] for technology mapping of the top module\n"); - log("(according to the (* top *) attribute or if only one module is currently selected)\n"); - log("to a target FPGA architecture.\n"); - log("\n"); - log(" -exe \n"); -#ifdef ABCEXTERNAL - log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); -#else - log(" use the specified command instead of \"/%syosys-abc\" to execute ABC.\n", proc_program_prefix().c_str()); -#endif - log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n"); - log("\n"); - log(" -script \n"); - log(" use the specified ABC script file instead of the default script.\n"); - log("\n"); - log(" if starts with a plus sign (+), then the rest of the filename\n"); - log(" string is interpreted as the command string to be passed to ABC. The\n"); - log(" leading plus sign is removed and all commas (,) in the string are\n"); - log(" replaced with blanks before the string is passed to ABC.\n"); - log("\n"); - log(" if no -script parameter is given, the following scripts are used:\n"); - log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos)).c_str()); - log("\n"); - log(" -fast\n"); - log(" use different default scripts that are slightly faster (at the cost\n"); - log(" of output quality):\n"); - log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)).c_str()); - log("\n"); - log(" -D \n"); - log(" set delay target. the string {D} in the default scripts above is\n"); - log(" replaced by this option when used, and an empty string otherwise\n"); - log(" (indicating best possible delay).\n"); - log("\n"); -// log(" -S \n"); -// log(" maximum number of LUT inputs shared.\n"); -// log(" (replaces {S} in the default scripts above, default: -S 1)\n"); -// log("\n"); - log(" -lut \n"); - log(" generate netlist using luts of (max) the specified width.\n"); - log("\n"); - log(" -lut :\n"); - log(" generate netlist using luts of (max) the specified width . All\n"); - log(" luts with width <= have constant cost. for luts larger than \n"); - log(" the area cost doubles with each additional input bit. the delay cost\n"); - log(" is still constant for all lut widths.\n"); - log("\n"); - log(" -lut \n"); - log(" pass this file with lut library to ABC.\n"); - log("\n"); - log(" -luts ,,,:,..\n"); - log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); - log(" 2, 3, .. inputs.\n"); - log("\n"); - log(" -showtmp\n"); - log(" print the temp dir name in log. usually this is suppressed so that the\n"); - log(" command output is identical across runs.\n"); - log("\n"); - log(" -box \n"); - log(" pass this file with box library to ABC.\n"); - log("\n"); - log(" -cwd \n"); - log(" use this as the current working directory, inside which the 'input.xaig'\n"); - log(" file is expected. temporary files will be created in this directory, and\n"); - log(" the mapped result will be written to 'output.aig'.\n"); - log("\n"); - log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); - log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); - log("ABC on logic snippets extracted from your design. You will not get any useful\n"); - log("output when passing an ABC script that writes a file. Instead write your full\n"); - log("design as BLIF file with write_blif and then load that into ABC externally if\n"); - log("you want to use ABC to convert your design into another format.\n"); - log("\n"); - log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - log_header(design, "Executing ABC9_EXE pass (technology mapping using ABC9).\n"); - -#ifdef ABCEXTERNAL - std::string exe_file = ABCEXTERNAL; -#else - std::string exe_file = proc_self_dirname() + proc_program_prefix()+ "yosys-abc"; -#endif - std::string script_file, clk_str, box_file, lut_file; - std::string delay_target, lutin_shared = "-S 1", wire_delay; - std::string tempdir_name; - bool fast_mode = false, dff_mode = false; - bool show_tempdir = false; - vector lut_costs; - -#if 0 - cleanup = false; - show_tempdir = true; -#endif - -#ifdef _WIN32 -#ifndef ABCEXTERNAL - if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc.exe")) - exe_file = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc"; -#endif -#endif - - std::string lut_arg, luts_arg; - exe_file = design->scratchpad_get_string("abc9.exe", exe_file /* inherit default value if not set */); - script_file = design->scratchpad_get_string("abc9.script", script_file); - if (design->scratchpad.count("abc9.D")) { - delay_target = "-D " + design->scratchpad_get_string("abc9.D"); - } - lut_arg = design->scratchpad_get_string("abc9.lut", lut_arg); - luts_arg = design->scratchpad_get_string("abc9.luts", luts_arg); - fast_mode = design->scratchpad_get_bool("abc9.fast", fast_mode); - dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode); - show_tempdir = design->scratchpad_get_bool("abc9.showtmp", show_tempdir); - box_file = design->scratchpad_get_string("abc9.box", box_file); - if (design->scratchpad.count("abc9.W")) { - wire_delay = "-W " + design->scratchpad_get_string("abc9.W"); - } - - size_t argidx; -#if defined(__wasm) - const char *pwd = "."; -#else - char pwd [PATH_MAX]; - if (!getcwd(pwd, sizeof(pwd))) { - log_cmd_error("getcwd failed: %s\n", strerror(errno)); - log_abort(); - } -#endif - for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-exe" && argidx+1 < args.size()) { - exe_file = args[++argidx]; - continue; - } - if (arg == "-script" && argidx+1 < args.size()) { - script_file = args[++argidx]; - continue; - } - if (arg == "-D" && argidx+1 < args.size()) { - delay_target = "-D " + args[++argidx]; - continue; - } - //if (arg == "-S" && argidx+1 < args.size()) { - // lutin_shared = "-S " + args[++argidx]; - // continue; - //} - if (arg == "-lut" && argidx+1 < args.size()) { - lut_arg = args[++argidx]; - continue; - } - if (arg == "-luts" && argidx+1 < args.size()) { - lut_arg = args[++argidx]; - continue; - } - if (arg == "-fast") { - fast_mode = true; - continue; - } - if (arg == "-dff") { - dff_mode = true; - continue; - } - if (arg == "-showtmp") { - show_tempdir = true; - continue; - } - if (arg == "-box" && argidx+1 < args.size()) { - box_file = args[++argidx]; - continue; - } - if (arg == "-W" && argidx+1 < args.size()) { - wire_delay = "-W " + args[++argidx]; - continue; - } - if (arg == "-cwd" && argidx+1 < args.size()) { - tempdir_name = args[++argidx]; - continue; - } - break; - } - extra_args(args, argidx, design); - - rewrite_filename(script_file); - if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+') - script_file = std::string(pwd) + "/" + script_file; - - // handle -lut / -luts args - if (!lut_arg.empty()) { - string arg = lut_arg; - if (arg.find_first_not_of("0123456789:,") == std::string::npos) { - size_t pos = arg.find_first_of(':'); - int lut_mode = 0, lut_mode2 = 0; - if (pos != string::npos) { - lut_mode = atoi(arg.substr(0, pos).c_str()); - lut_mode2 = atoi(arg.substr(pos+1).c_str()); - } else { - lut_mode = atoi(arg.c_str()); - lut_mode2 = lut_mode; - } - lut_costs.clear(); - for (int i = 0; i < lut_mode; i++) - lut_costs.push_back(1); - for (int i = lut_mode; i < lut_mode2; i++) - lut_costs.push_back(2 << (i - lut_mode)); - } - else { - lut_file = arg; - rewrite_filename(lut_file); - if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+') - lut_file = std::string(pwd) + "/" + lut_file; - } - } - if (!luts_arg.empty()) { - lut_costs.clear(); - for (auto &tok : split_tokens(luts_arg, ",")) { - auto parts = split_tokens(tok, ":"); - if (GetSize(parts) == 0 && !lut_costs.empty()) - lut_costs.push_back(lut_costs.back()); - else if (GetSize(parts) == 1) - lut_costs.push_back(atoi(parts.at(0).c_str())); - else if (GetSize(parts) == 2) - while (GetSize(lut_costs) < atoi(parts.at(0).c_str())) - lut_costs.push_back(atoi(parts.at(1).c_str())); - else - log_cmd_error("Invalid -luts syntax.\n"); - } - } - - if (box_file.empty()) - log_cmd_error("abc9_exe '-box' option is mandatory.\n"); - - rewrite_filename(box_file); - if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+') - box_file = std::string(pwd) + "/" + box_file; - - if (tempdir_name.empty()) - log_cmd_error("abc9_exe '-cwd' option is mandatory.\n"); - - - abc9_module(design, script_file, exe_file, lut_costs, dff_mode, - delay_target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, tempdir_name); - } -} Abc9ExePass; - -PRIVATE_NAMESPACE_END diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc deleted file mode 100644 index 98d0207c4ce..00000000000 --- a/passes/techmap/abc9_ops.cc +++ /dev/null @@ -1,1769 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * 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/register.h" -#include "kernel/sigtools.h" -#include "kernel/utils.h" -#include "kernel/celltypes.h" -#include "kernel/timinginfo.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -int map_autoidx; - -inline std::string remap_name(RTLIL::IdString abc9_name) -{ - return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); -} - -void check(RTLIL::Design *design, bool dff_mode) -{ - dict box_lookup; - for (auto m : design->modules()) { - auto flop = m->get_bool_attribute(ID::abc9_flop); - auto it = m->attributes.find(ID::abc9_box_id); - if (!flop) { - if (it == m->attributes.end()) - continue; - auto id = it->second.as_int(); - auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); - if (!r.second) - log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - log_id(m), id, log_id(r.first->second)); - } - - // Make carry in the last PI, and carry out the last PO - // since ABC requires it this way - IdString carry_in, carry_out; - for (const auto &port_name : m->ports) { - auto w = m->wire(port_name); - log_assert(w); - if (w->get_bool_attribute(ID::abc9_carry)) { - if (w->port_input) { - if (carry_in != IdString()) - log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", log_id(m)); - carry_in = port_name; - } - if (w->port_output) { - if (carry_out != IdString()) - log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", log_id(m)); - carry_out = port_name; - } - } - } - - if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", log_id(m)); - if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", log_id(m)); - - if (flop) { - int num_outputs = 0; - for (auto port_name : m->ports) { - auto wire = m->wire(port_name); - if (wire->port_output) num_outputs++; - } - if (num_outputs != 1) - log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs); - } - } - - if (dff_mode) { - static pool unsupported{ - ID($adff), ID($dlatch), ID($dlatchsr), ID($sr), - ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), - ID($_DLATCH_N_), ID($_DLATCH_P_), - ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_), - ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), - ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_) - }; - pool processed; - for (auto module : design->selected_modules()) - for (auto cell : module->cells()) { - auto inst_module = design->module(cell->type); - if (!inst_module) - continue; - IdString derived_type; - Module *derived_module; - if (cell->parameters.empty()) { - derived_type = cell->type; - derived_module = inst_module; - } - else { - // Check potential (since its value may depend on a parameter, - // but not its existence) - if (!inst_module->has_attribute(ID::abc9_flop)) - continue; - derived_type = inst_module->derive(design, cell->parameters); - derived_module = design->module(derived_type); - log_assert(derived_module); - } - if (!derived_module->get_bool_attribute(ID::abc9_flop)) - continue; - if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) - log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type)); - - if (derived_module->has_processes()) - Pass::call_on_module(design, derived_module, "proc"); - - bool found = false; - for (auto derived_cell : derived_module->cells()) { - if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) { - if (found) - log_error("Whitebox '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module)); - found = true; - - SigBit Q = derived_cell->getPort(ID::Q); - log_assert(GetSize(Q.wire) == 1); - - if (!Q.wire->port_output) - log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell where its 'Q' port does not drive a module output.\n", log_id(derived_module), log_id(derived_cell->type)); - - Const init = Q.wire->attributes.at(ID::init, State::Sx); - log_assert(GetSize(init) == 1); - } - else if (unsupported.count(derived_cell->type)) - log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type)); - } - } - } -} - -void prep_hier(RTLIL::Design *design, bool dff_mode) -{ - auto r = saved_designs.emplace("$abc9_unmap", nullptr); - if (r.second) - r.first->second = new Design; - Design *unmap_design = r.first->second; - - static const pool seq_types{ - ID($dff), ID($dffsr), ID($adff), - ID($dlatch), ID($dlatchsr), ID($sr), - ID($mem), - ID($_DFF_N_), ID($_DFF_P_), - ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), - ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), - ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), - ID($_DLATCH_N_), ID($_DLATCH_P_), - ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_), - ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), - ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_) - }; - - for (auto module : design->selected_modules()) - for (auto cell : module->cells()) { - auto inst_module = design->module(cell->type); - if (!inst_module) - continue; - IdString derived_type; - Module *derived_module; - if (cell->parameters.empty()) { - derived_type = cell->type; - derived_module = inst_module; - } - else { - // Check potential for any one of those three - // (since its value may depend on a parameter, but not its existence) - if (!inst_module->has_attribute(ID::abc9_flop) && !inst_module->has_attribute(ID::abc9_box) && !inst_module->get_bool_attribute(ID::abc9_bypass)) - continue; - derived_type = inst_module->derive(design, cell->parameters); - derived_module = design->module(derived_type); - } - if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) - continue; - - if (derived_module->get_bool_attribute(ID::abc9_flop)) { - if (!dff_mode) - continue; - } - else { - if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_bypass)) - continue; - } - - if (!unmap_design->module(derived_type)) { - if (derived_module->has_processes()) - Pass::call_on_module(design, derived_module, "proc"); - - if (derived_module->get_bool_attribute(ID::abc9_flop)) { - for (auto derived_cell : derived_module->cells()) - if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) { - SigBit Q = derived_cell->getPort(ID::Q); - Const init = Q.wire->attributes.at(ID::init, State::Sx); - log_assert(GetSize(init) == 1); - - // Block sequential synthesis on cells with (* init *) != 1'b0 - // because ABC9 doesn't support them - if (init != State::S0) { - log_warning("Whitebox '%s' with (* abc9_flop *) contains a %s cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type)); - derived_module->set_bool_attribute(ID::abc9_flop, false); - } - break; - } - } - else if (derived_module->get_bool_attribute(ID::abc9_box)) { - for (auto derived_cell : derived_module->cells()) - if (seq_types.count(derived_cell->type)) { - derived_module->set_bool_attribute(ID::abc9_box, false); - derived_module->set_bool_attribute(ID::abc9_bypass); - break; - } - } - - if (derived_type != cell->type) { - auto unmap_module = unmap_design->addModule(derived_type); - for (auto port : derived_module->ports) { - auto w = unmap_module->addWire(port, derived_module->wire(port)); - // Do not propagate (* init *) values into the box, - // in fact, remove it from outside too - if (w->port_output) - w->attributes.erase(ID::init); - } - unmap_module->ports = derived_module->ports; - unmap_module->check(); - - auto replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, cell->type); - for (const auto &conn : cell->connections()) { - auto w = unmap_module->wire(conn.first); - log_assert(w); - replace_cell->setPort(conn.first, w); - } - replace_cell->parameters = cell->parameters; - } - } - - cell->type = derived_type; - cell->parameters.clear(); - } -} - -void prep_bypass(RTLIL::Design *design) -{ - auto r = saved_designs.emplace("$abc9_map", nullptr); - if (r.second) - r.first->second = new Design; - Design *map_design = r.first->second; - - r = saved_designs.emplace("$abc9_unmap", nullptr); - if (r.second) - r.first->second = new Design; - Design *unmap_design = r.first->second; - - pool processed; - for (auto module : design->selected_modules()) - for (auto cell : module->cells()) { - if (!processed.insert(cell->type).second) - continue; - auto inst_module = design->module(cell->type); - if (!inst_module) - continue; - if (!inst_module->get_bool_attribute(ID::abc9_bypass)) - continue; - log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */)); - log_assert(cell->parameters.empty()); - - - // The idea is to create two techmap designs, one which maps: - // - // box u0 (.i(i), .o(o)); - // - // to - // - // wire $abc9$o; - // box u0 (.i(i), .o($abc9_byp$o)); - // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o)); - // - // the purpose being to move the (* abc9_box *) status from 'box' - // (which is stateful) to 'box_$abc9_byp' (which becomes a new - // combinatorial black- (not white-) box with all state elements - // removed). This has the effect of preserving any combinatorial - // paths through an otherwise sequential primitive -- e.g. LUTRAMs. - // - // The unmap design performs the reverse: - // - // wire $abc9$o; - // box u0 (.i(i), .o($abc9_byp$o)); - // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o)); - // - // to: - // - // wire $abc9$o; - // box u0 (.i(i), .o($abc9_byp$o)); - // assign o = $abc9_byp$o; - - - // Copy inst_module into map_design, with the same interface - // and duplicate $abc9$* wires for its output ports - auto map_module = map_design->addModule(cell->type); - for (auto port_name : inst_module->ports) { - auto w = map_module->addWire(port_name, inst_module->wire(port_name)); - if (w->port_output) - w->attributes.erase(ID::init); - } - map_module->ports = inst_module->ports; - map_module->check(); - map_module->set_bool_attribute(ID::whitebox); - - // Create the bypass module in the user design, which has the same - // interface as the derived module but with additional input - // ports driven by the outputs of the replaced cell - auto bypass_module = design->addModule(cell->type.str() + "_$abc9_byp"); - for (auto port_name : inst_module->ports) { - auto port = inst_module->wire(port_name); - if (!port->port_output) - continue; - auto dst = bypass_module->addWire(port_name, port); - auto src = bypass_module->addWire("$abc9byp$" + port_name.str(), GetSize(port)); - src->port_input = true; - // For these new input ports driven by the replaced - // cell, then create a new simple-path specify entry: - // (input => output) = 0 - auto specify = bypass_module->addCell(NEW_ID, ID($specify2)); - specify->setPort(ID::EN, State::S1); - specify->setPort(ID::SRC, src); - specify->setPort(ID::DST, dst); - specify->setParam(ID::FULL, 0); - specify->setParam(ID::SRC_WIDTH, GetSize(src)); - specify->setParam(ID::DST_WIDTH, GetSize(dst)); - specify->setParam(ID::SRC_DST_PEN, 0); - specify->setParam(ID::SRC_DST_POL, 0); - specify->setParam(ID::T_RISE_MIN, 0); - specify->setParam(ID::T_RISE_TYP, 0); - specify->setParam(ID::T_RISE_MAX, 0); - specify->setParam(ID::T_FALL_MIN, 0); - specify->setParam(ID::T_FALL_TYP, 0); - specify->setParam(ID::T_FALL_MAX, 0); - } - bypass_module->set_bool_attribute(ID::blackbox); - bypass_module->set_bool_attribute(ID::abc9_box); - - // Copy any 'simple' (combinatorial) specify paths from - // the derived module into the bypass module, if EN - // is not false and SRC/DST are driven only by - // module ports; create new input port if one doesn't - // already exist - for (auto cell : inst_module->cells()) { - if (cell->type != ID($specify2)) - continue; - auto EN = cell->getPort(ID::EN).as_bit(); - SigBit newEN; - if (!EN.wire && EN != State::S1) - continue; - auto SRC = cell->getPort(ID::SRC); - for (const auto &c : SRC.chunks()) - if (c.wire && !c.wire->port_input) { - SRC = SigSpec(); - break; - } - if (SRC.empty()) - continue; - auto DST = cell->getPort(ID::DST); - for (const auto &c : DST.chunks()) - if (c.wire && !c.wire->port_output) { - DST = SigSpec(); - break; - } - if (DST.empty()) - continue; - auto rw = [bypass_module](RTLIL::SigSpec &sig) - { - SigSpec new_sig; - for (auto c : sig.chunks()) { - if (c.wire) { - auto port = bypass_module->wire(c.wire->name); - if (!port) - port = bypass_module->addWire(c.wire->name, c.wire); - c.wire = port; - } - new_sig.append(std::move(c)); - } - sig = std::move(new_sig); - }; - auto specify = bypass_module->addCell(NEW_ID, cell); - specify->rewrite_sigspecs(rw); - } - bypass_module->fixup_ports(); - - // Create an _TECHMAP_REPLACE_ cell identical to the original cell, - // and a bypass cell that has the same inputs/outputs as the - // original cell, but with additional inputs taken from the - // replaced cell - auto replace_cell = map_module->addCell(ID::_TECHMAP_REPLACE_, cell->type); - auto bypass_cell = map_module->addCell(NEW_ID, cell->type.str() + "_$abc9_byp"); - for (const auto &conn : cell->connections()) { - auto port = map_module->wire(conn.first); - if (cell->input(conn.first)) { - replace_cell->setPort(conn.first, port); - if (bypass_module->wire(conn.first)) - bypass_cell->setPort(conn.first, port); - } - if (cell->output(conn.first)) { - bypass_cell->setPort(conn.first, port); - auto n = "$abc9byp$" + conn.first.str(); - auto w = map_module->addWire(n, GetSize(conn.second)); - replace_cell->setPort(conn.first, w); - bypass_cell->setPort(n, w); - } - } - - - // Lastly, create a new module in the unmap_design that shorts - // out the bypass cell back to leave the replace cell behind - // driving the outputs - auto unmap_module = unmap_design->addModule(cell->type.str() + "_$abc9_byp"); - for (auto port_name : inst_module->ports) { - auto w = unmap_module->addWire(port_name, inst_module->wire(port_name)); - if (w->port_output) { - w->attributes.erase(ID::init); - auto w2 = unmap_module->addWire("$abc9byp$" + port_name.str(), GetSize(w)); - w2->port_input = true; - unmap_module->connect(w, w2); - } - } - unmap_module->fixup_ports(); - } -} - -void prep_dff(RTLIL::Design *design) -{ - auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false))); - auto &modules_sel = r.first->second; - - for (auto module : design->selected_modules()) - for (auto cell : module->cells()) { - if (modules_sel.selected_whole_module(cell->type)) - continue; - auto inst_module = design->module(cell->type); - if (!inst_module) - continue; - if (!inst_module->get_bool_attribute(ID::abc9_flop)) - continue; - log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */)); - log_assert(cell->parameters.empty()); - modules_sel.select(inst_module); - } -} - -void prep_dff_submod(RTLIL::Design *design) -{ - for (auto module : design->modules()) { - vector specify_cells; - SigBit Q; - Cell* dff_cell = nullptr; - - if (!module->get_bool_attribute(ID::abc9_flop)) - continue; - - for (auto cell : module->cells()) - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { - log_assert(!dff_cell); - dff_cell = cell; - Q = cell->getPort(ID::Q); - log_assert(GetSize(Q.wire) == 1); - } - else if (cell->type.in(ID($specify3), ID($specrule))) - specify_cells.emplace_back(cell); - log_assert(dff_cell); - - // Add an always-enabled CE mux that drives $_DFF_[NP]_.D so that: - // (a) flop box will have an output - // (b) $_DFF_[NP]_.Q will be present as an input - SigBit D = module->addWire(NEW_ID); - module->addMuxGate(NEW_ID, dff_cell->getPort(ID::D), Q, State::S0, D); - dff_cell->setPort(ID::D, D); - - // Rewrite $specify cells that end with $_DFF_[NP]_.Q - // to $_DFF_[NP]_.D since it will be moved into - // the submodule - for (auto cell : specify_cells) { - auto DST = cell->getPort(ID::DST); - DST.replace(Q, D); - cell->setPort(ID::DST, DST); - } - - design->scratchpad_set_bool("abc9_ops.prep_dff_submod.did_something", true); - } -} - -void prep_dff_unmap(RTLIL::Design *design) -{ - Design *unmap_design = saved_designs.at("$abc9_unmap"); - - for (auto module : design->modules()) { - if (!module->get_bool_attribute(ID::abc9_flop) || module->get_bool_attribute(ID::abc9_box)) - continue; - - // Make sure the box module has all the same ports present on flop cell - auto replace_cell = module->cell(ID::_TECHMAP_REPLACE_); - log_assert(replace_cell); - auto box_module = design->module(module->name.str() + "_$abc9_flop"); - log_assert(box_module); - for (auto port_name : module->ports) { - auto port = module->wire(port_name); - auto box_port = box_module->wire(port_name); - if (box_port) { - // Do not propagate init -- already captured by box - box_port->attributes.erase(ID::init); - continue; - } - log_assert(port->port_input); - box_module->addWire(port_name, port); - replace_cell->setPort(port_name, port); - } - box_module->fixup_ports(); - - auto unmap_module = unmap_design->addModule(box_module->name); - replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, module->name); - for (auto port_name : box_module->ports) { - auto w = unmap_module->addWire(port_name, box_module->wire(port_name)); - if (module->wire(port_name)) - replace_cell->setPort(port_name, w); - } - unmap_module->ports = box_module->ports; - unmap_module->check(); - } -} - -void mark_scc(RTLIL::Module *module) -{ - // For every unique SCC found, (arbitrarily) find the first - // cell in the component, and replace its output connections - // with a new wire driven by the old connection but with a - // special (* abc9_keep *) attribute set (which is used by - // write_xaiger to break this wire into PI and POs) - pool ids_seen; - for (auto cell : module->cells()) { - auto it = cell->attributes.find(ID::abc9_scc_id); - if (it == cell->attributes.end()) - continue; - auto id = it->second; - auto r = ids_seen.insert(id); - cell->attributes.erase(it); - if (!r.second) - continue; - for (auto &c : cell->connections_) { - if (c.second.is_fully_const()) continue; - if (cell->output(c.first)) { - Wire *w = module->addWire(NEW_ID, GetSize(c.second)); - w->set_bool_attribute(ID::abc9_keep); - module->connect(w, c.second); - c.second = w; - } - } - } -} - -void prep_delays(RTLIL::Design *design, bool dff_mode) -{ - TimingInfo timing; - - // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes - // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations - std::vector cells; - for (auto module : design->selected_modules()) { - if (module->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(module)); - continue; - } - - for (auto cell : module->cells()) { - if (cell->type.in(ID($_AND_), ID($_NOT_), ID($_DFF_N_), ID($_DFF_P_))) - continue; - log_assert(!cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")); - - RTLIL::Module* inst_module = design->module(cell->type); - if (!inst_module) - continue; - if (!inst_module->get_blackbox_attribute()) - continue; - if (!cell->parameters.empty()) - continue; - - if (inst_module->get_bool_attribute(ID::abc9_box)) - continue; - if (inst_module->get_bool_attribute(ID::abc9_bypass)) - continue; - - if (dff_mode && inst_module->get_bool_attribute(ID::abc9_flop)) { - continue; // do not add $__ABC9_DELAY boxes to flops - // as delays will be captured in the flop box - } - - if (!timing.count(cell->type)) - timing.setup_module(inst_module); - - cells.emplace_back(cell); - } - } - - // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes - // (or bypassed white-boxes with required times) - dict box_cache; - Module *delay_module = design->module(ID($__ABC9_DELAY)); - log_assert(delay_module); - for (auto cell : cells) { - auto module = cell->module; - auto inst_module = design->module(cell->type); - log_assert(inst_module); - - auto &t = timing.at(cell->type).required; - for (auto &conn : cell->connections_) { - auto port_wire = inst_module->wire(conn.first); - if (!port_wire) - log_error("Port %s in cell %s (type %s) from module %s does not actually exist", - log_id(conn.first), log_id(cell), log_id(cell->type), log_id(module)); - if (!port_wire->port_input) - continue; - if (conn.second.is_fully_const()) - continue; - - SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); - for (int i = 0; i < GetSize(conn.second); i++) { - auto d = t.at(TimingInfo::NameBit(conn.first,i), 0); - if (d == 0) - continue; - -#ifndef NDEBUG - if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(cell->type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n", - log_id(cell->type), log_id(conn.first), i, d); - } -#endif - auto r = box_cache.insert(d); - if (r.second) { - r.first->second = delay_module->derive(design, {{ID::DELAY, d}}); - log_assert(r.first->second.begins_with("$paramod$__ABC9_DELAY\\DELAY=")); - } - auto box = module->addCell(NEW_ID, r.first->second); - box->setPort(ID::I, conn.second[i]); - box->setPort(ID::O, O[i]); - conn.second[i] = O[i]; - } - } - } -} - -void prep_xaiger(RTLIL::Module *module, bool dff) -{ - auto design = module->design; - log_assert(design); - - SigMap sigmap(module); - - dict> bit_drivers, bit_users; - TopoSort toposort; - dict> box_ports; - - for (auto cell : module->cells()) { - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - continue; - if (cell->has_keep_attr()) - continue; - - auto inst_module = design->module(cell->type); - bool abc9_flop = inst_module && inst_module->get_bool_attribute(ID::abc9_flop); - if (abc9_flop && !dff) - continue; - - if (inst_module && inst_module->get_bool_attribute(ID::abc9_box)) { - auto r = box_ports.insert(cell->type); - if (r.second) { - // Make carry in the last PI, and carry out the last PO - // since ABC requires it this way - IdString carry_in, carry_out; - for (const auto &port_name : inst_module->ports) { - auto w = inst_module->wire(port_name); - log_assert(w); - if (w->get_bool_attribute(ID::abc9_carry)) { - log_assert(w->port_input != w->port_output); - if (w->port_input) - carry_in = port_name; - else if (w->port_output) - carry_out = port_name; - } - else - r.first->second.push_back(port_name); - } - if (carry_in != IdString()) { - r.first->second.push_back(carry_in); - r.first->second.push_back(carry_out); - } - } - } - else if (!yosys_celltypes.cell_known(cell->type)) - continue; - - // TODO: Speed up toposort -- we care about box ordering only - for (auto conn : cell->connections()) { - if (cell->input(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - - if (cell->output(conn.first) && !abc9_flop) - for (const auto &chunk : conn.second.chunks()) - if (!chunk.wire->get_bool_attribute(ID::abc9_keep)) - for (auto b : sigmap(SigSpec(chunk))) - bit_drivers[b].insert(cell->name); - } - toposort.node(cell->name); - } - - if (box_ports.empty()) - return; - - for (auto &it : bit_users) - if (bit_drivers.count(it.first)) - for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); - - if (ys_debug(1)) - toposort.analyze_loops = true; - - bool no_loops = toposort.sort(); - - if (ys_debug(1)) { - unsigned i = 0; - for (auto &it : toposort.loops) { - log(" loop %d\n", i++); - for (auto cell_name : it) { - auto cell = module->cell(cell_name); - log_assert(cell); - log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str()); - } - } - } - - log_assert(no_loops); - - auto r = saved_designs.emplace("$abc9_holes", nullptr); - if (r.second) - r.first->second = new Design; - RTLIL::Design *holes_design = r.first->second; - log_assert(holes_design); - RTLIL::Module *holes_module = holes_design->addModule(module->name); - log_assert(holes_module); - - dict cell_cache; - TimingInfo timing; - - int port_id = 1, box_count = 0; - for (auto cell_name : toposort.sorted) { - RTLIL::Cell *cell = module->cell(cell_name); - log_assert(cell); - - RTLIL::Module* box_module = design->module(cell->type); - if (!box_module) - continue; - if (!box_module->get_bool_attribute(ID::abc9_box)) - continue; - log_assert(cell->parameters.empty()); - log_assert(box_module->get_blackbox_attribute()); - - cell->attributes[ID::abc9_box_seq] = box_count++; - - auto r = cell_cache.insert(cell->type); - auto &holes_cell = r.first->second; - if (r.second) { - if (box_module->get_bool_attribute(ID::whitebox)) { - holes_cell = holes_module->addCell(cell->name, cell->type); - - if (box_module->has_processes()) - Pass::call_on_module(design, box_module, "proc"); - - int box_inputs = 0; - for (auto port_name : box_ports.at(cell->type)) { - RTLIL::Wire *w = box_module->wire(port_name); - log_assert(w); - log_assert(!w->port_input || !w->port_output); - auto &conn = holes_cell->connections_[port_name]; - if (w->port_input) { - for (int i = 0; i < GetSize(w); i++) { - box_inputs++; - RTLIL::Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - conn.append(holes_wire); - } - } - else if (w->port_output) - conn = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), log_id(port_name)), GetSize(w)); - } - } - else // box_module is a blackbox - log_assert(holes_cell == nullptr); - } - - for (auto port_name : box_ports.at(cell->type)) { - RTLIL::Wire *w = box_module->wire(port_name); - log_assert(w); - if (!w->port_output) - continue; - Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name.c_str(), log_id(port_name)), GetSize(w)); - holes_wire->port_output = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - if (holes_cell) // whitebox - holes_module->connect(holes_wire, holes_cell->getPort(port_name)); - else // blackbox - holes_module->connect(holes_wire, Const(State::S0, GetSize(w))); - } - } -} - -void prep_lut(RTLIL::Design *design, int maxlut) -{ - TimingInfo timing; - - struct t_lut { - IdString name; - int area; - std::vector delays; - }; - std::map table; - for (auto module : design->modules()) { - auto it = module->attributes.find(ID::abc9_lut); - if (it == module->attributes.end()) - continue; - - auto &t = timing.setup_module(module); - - TimingInfo::NameBit o; - std::vector delays; - for (const auto &i : t.comb) { - auto &d = i.first.second; - if (o == TimingInfo::NameBit()) - o = d; - else if (o != d) - log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", log_id(module)); - delays.push_back(i.second); - } - - if (GetSize(delays) == 0) - log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", log_id(module)); - if (maxlut && GetSize(delays) > maxlut) - continue; - // ABC requires non-decreasing LUT input delays - std::sort(delays.begin(), delays.end()); - - int K = GetSize(delays); - auto entry = t_lut{module->name, it->second.as_int(), std::move(delays)}; - auto r = table.emplace(K, entry); - if (!r.second) { - if (r.first->second.area != entry.area) - log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", log_id(module), log_id(r.first->second.name)); - if (r.first->second.delays != entry.delays) - log_error("Modules '%s' and '%s' have conflicting specify entries.\n", log_id(module), log_id(r.first->second.name)); - } - } - - if (table.empty()) - log_error("Design does not contain any modules with (* abc9_lut *).\n"); - - std::stringstream ss; - const auto &front = *table.begin(); - // If the first entry does not start from a 1-input LUT, - // (as ABC requires) crop the first entry to do so - for (int i = 1; i < front.first; i++) { - ss << "# $__ABC9_LUT" << i << std::endl; - ss << i << " " << front.second.area; - for (int j = 0; j < i; j++) - ss << " " << front.second.delays[j]; - ss << std::endl; - } - for (const auto &i : table) { - ss << "# " << log_id(i.second.name) << std::endl; - ss << i.first << " " << i.second.area; - for (const auto &j : i.second.delays) - ss << " " << j; - ss << std::endl; - } - design->scratchpad_set_string("abc9_ops.lut_library", ss.str()); -} - -void write_lut(RTLIL::Module *module, const std::string &dst) { - std::ofstream ofs(dst); - log_assert(ofs.is_open()); - ofs << module->design->scratchpad_get_string("abc9_ops.lut_library"); - ofs.close(); -} - -void prep_box(RTLIL::Design *design) -{ - TimingInfo timing; - - std::stringstream ss; - int abc9_box_id = 1; - for (auto module : design->modules()) { - auto it = module->attributes.find(ID::abc9_box_id); - if (it == module->attributes.end()) - continue; - abc9_box_id = std::max(abc9_box_id, it->second.as_int()); - } - - dict> box_ports; - for (auto module : design->modules()) { - auto it = module->attributes.find(ID::abc9_box); - if (it == module->attributes.end()) - continue; - bool box = it->second.as_bool(); - module->attributes.erase(it); - if (!box) - continue; - - auto r = module->attributes.insert(ID::abc9_box_id); - if (!r.second) - continue; - r.first->second = abc9_box_id++; - - if (module->get_bool_attribute(ID::abc9_flop)) { - int num_inputs = 0, num_outputs = 0; - for (auto port_name : module->ports) { - auto wire = module->wire(port_name); - log_assert(GetSize(wire) == 1); - if (wire->port_input) num_inputs++; - if (wire->port_output) num_outputs++; - } - log_assert(num_outputs == 1); - - ss << log_id(module) << " " << r.first->second.as_int(); - log_assert(module->get_bool_attribute(ID::whitebox)); - ss << " " << "1"; - ss << " " << num_inputs << " " << num_outputs << std::endl; - - ss << "#"; - bool first = true; - for (auto port_name : module->ports) { - auto wire = module->wire(port_name); - if (!wire->port_input) - continue; - if (first) - first = false; - else - ss << " "; - ss << log_id(wire); - } - ss << std::endl; - - auto &t = timing.setup_module(module).required; - if (t.empty()) - log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", log_id(module)); - - first = true; - for (auto port_name : module->ports) { - auto wire = module->wire(port_name); - if (!wire->port_input) - continue; - if (first) - first = false; - else - ss << " "; - log_assert(GetSize(wire) == 1); - auto it = t.find(TimingInfo::NameBit(port_name,0)); - if (it == t.end()) - // Assume no connectivity if no setup time - ss << "-"; - else { - ss << it->second; - -#ifndef NDEBUG - if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), - log_id(port_name), it->second); - } -#endif - } - } - ss << " # $_DFF_[NP]_.D" << std::endl; - ss << std::endl; - } - else { - auto r2 = box_ports.insert(module->name); - if (r2.second) { - // Make carry in the last PI, and carry out the last PO - // since ABC requires it this way - IdString carry_in, carry_out; - for (const auto &port_name : module->ports) { - auto w = module->wire(port_name); - log_assert(w); - if (w->get_bool_attribute(ID::abc9_carry)) { - log_assert(w->port_input != w->port_output); - if (w->port_input) - carry_in = port_name; - else if (w->port_output) - carry_out = port_name; - } - else - r2.first->second.push_back(port_name); - } - - if (carry_in != IdString()) { - r2.first->second.push_back(carry_in); - r2.first->second.push_back(carry_out); - } - } - - std::vector inputs, outputs; - for (auto port_name : r2.first->second) { - auto wire = module->wire(port_name); - if (wire->port_input) - for (int i = 0; i < GetSize(wire); i++) - inputs.emplace_back(wire, i); - if (wire->port_output) - for (int i = 0; i < GetSize(wire); i++) - outputs.emplace_back(wire, i); - } - - ss << log_id(module) << " " << module->attributes.at(ID::abc9_box_id).as_int(); - ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); - ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl; - - bool first = true; - ss << "#"; - for (const auto &i : inputs) { - if (first) - first = false; - else - ss << " "; - if (GetSize(i.wire) == 1) - ss << log_id(i.wire); - else - ss << log_id(i.wire) << "[" << i.offset << "]"; - } - ss << std::endl; - - auto &t = timing.setup_module(module); - if (t.comb.empty()) - log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", log_id(module)); - - for (const auto &o : outputs) { - first = true; - for (const auto &i : inputs) { - if (first) - first = false; - else - ss << " "; - auto jt = t.comb.find(TimingInfo::BitBit(i,o)); - if (jt == t.comb.end()) - ss << "-"; - else - ss << jt->second; - } - ss << " # "; - if (GetSize(o.wire) == 1) - ss << log_id(o.wire); - else - ss << log_id(o.wire) << "[" << o.offset << "]"; - ss << std::endl; - } - ss << std::endl; - } - } - - // ABC expects at least one box - if (ss.tellp() == 0) - ss << "(dummy) 1 0 0 0"; - - design->scratchpad_set_string("abc9_ops.box_library", ss.str()); -} - -void write_box(RTLIL::Module *module, const std::string &dst) { - std::ofstream ofs(dst); - log_assert(ofs.is_open()); - ofs << module->design->scratchpad_get_string("abc9_ops.box_library"); - ofs.close(); -} - -void reintegrate(RTLIL::Module *module, bool dff_mode) -{ - auto design = module->design; - log_assert(design); - - map_autoidx = autoidx++; - - RTLIL::Module *mapped_mod = design->module(stringf("%s$abc9", module->name.c_str())); - if (mapped_mod == NULL) - log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module)); - - for (auto w : mapped_mod->wires()) { - auto nw = module->addWire(remap_name(w->name), GetSize(w)); - nw->start_offset = w->start_offset; - // Remove all (* init *) since they only exist on $_DFF_[NP]_ - w->attributes.erase(ID::init); - } - - dict> box_ports; - - for (auto m : design->modules()) { - if (!m->attributes.count(ID::abc9_box_id)) - continue; - - auto r = box_ports.insert(m->name); - if (!r.second) - continue; - - // Make carry in the last PI, and carry out the last PO - // since ABC requires it this way - IdString carry_in, carry_out; - for (const auto &port_name : m->ports) { - auto w = m->wire(port_name); - log_assert(w); - if (w->get_bool_attribute(ID::abc9_carry)) { - log_assert(w->port_input != w->port_output); - if (w->port_input) - carry_in = port_name; - else if (w->port_output) - carry_out = port_name; - } - else - r.first->second.push_back(port_name); - } - - if (carry_in != IdString()) { - r.first->second.push_back(carry_in); - r.first->second.push_back(carry_out); - } - } - - SigMap initmap; - if (dff_mode) { - // Build a sigmap prioritising bits with (* init *) - initmap.set(module); - for (auto w : module->wires()) { - auto it = w->attributes.find(ID::init); - if (it == w->attributes.end()) - continue; - for (auto i = 0; i < GetSize(w); i++) - if (it->second[i] == State::S0 || it->second[i] == State::S1) - initmap.add(w); - } - } - - std::vector boxes; - for (auto cell : module->cells().to_vector()) { - if (cell->has_keep_attr()) - continue; - - // Short out (so that existing name can be preserved) and remove - // $_DFF_[NP]_ cells since flop box already has all the information - // we need to reconstruct them - if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep)) { - SigBit Q = cell->getPort(ID::Q); - module->connect(Q, cell->getPort(ID::D)); - module->remove(cell); - auto Qi = initmap(Q); - auto it = Qi.wire->attributes.find(ID::init); - if (it != Qi.wire->attributes.end()) - it->second[Qi.offset] = State::Sx; - } - else if (cell->type.in(ID($_AND_), ID($_NOT_))) - module->remove(cell); - else if (cell->attributes.erase(ID::abc9_box_seq)) - boxes.emplace_back(cell); - } - - dict> bit_drivers, bit_users; - TopoSort toposort; - dict not2drivers; - dict> bit2sinks; - - std::map cell_stats; - for (auto mapped_cell : mapped_mod->cells()) - { - // Short out $_FF_ cells since the flop box already has - // all the information we need to reconstruct cell - if (dff_mode && mapped_cell->type == ID($_FF_)) { - SigBit D = mapped_cell->getPort(ID::D); - SigBit Q = mapped_cell->getPort(ID::Q); - if (D.wire) - D.wire = module->wires_.at(remap_name(D.wire->name)); - Q.wire = module->wires_.at(remap_name(Q.wire->name)); - module->connect(Q, D); - continue; - } - - // TODO: Speed up toposort -- we care about NOT ordering only - toposort.node(mapped_cell->name); - - if (mapped_cell->type == ID($_NOT_)) { - RTLIL::SigBit a_bit = mapped_cell->getPort(ID::A); - RTLIL::SigBit y_bit = mapped_cell->getPort(ID::Y); - bit_users[a_bit].insert(mapped_cell->name); - // Ignore inouts for topo ordering - if (y_bit.wire && !(y_bit.wire->port_input && y_bit.wire->port_output)) - bit_drivers[y_bit].insert(mapped_cell->name); - - if (!a_bit.wire) { - mapped_cell->setPort(ID::Y, module->addWire(NEW_ID)); - RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); - log_assert(wire); - module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1); - } - else { - RTLIL::Cell* driver_lut = nullptr; - // ABC can return NOT gates that drive POs - if (!a_bit.wire->port_input) { - // If it's not a NOT gate that that comes from a PI directly, - // find the driver LUT and clone that to guarantee that we won't - // increase the max logic depth - // (TODO: Optimise by not cloning unless will increase depth) - RTLIL::IdString driver_name; - if (GetSize(a_bit.wire) == 1) - driver_name = stringf("$lut%s", a_bit.wire->name.c_str()); - else - driver_name = stringf("$lut%s[%d]", a_bit.wire->name.c_str(), a_bit.offset); - driver_lut = mapped_mod->cell(driver_name); - } - - if (!driver_lut) { - // If a driver couldn't be found (could be from PI or box CI) - // then implement using a LUT - RTLIL::Cell *cell = module->addLut(remap_name(stringf("$lut%s", mapped_cell->name.c_str())), - RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), - RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), - RTLIL::Const::from_string("01")); - bit2sinks[cell->getPort(ID::A)].push_back(cell); - cell_stats[ID($lut)]++; - } - else - not2drivers[mapped_cell] = driver_lut; - } - continue; - } - - if (mapped_cell->type == ID($lut)) { - RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); - cell->parameters = mapped_cell->parameters; - cell->attributes = mapped_cell->attributes; - - for (auto &mapped_conn : mapped_cell->connections()) { - RTLIL::SigSpec newsig; - for (auto c : mapped_conn.second.chunks()) { - if (c.width == 0) - continue; - //log_assert(c.width == 1); - if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); - newsig.append(c); - } - cell->setPort(mapped_conn.first, newsig); - - if (cell->input(mapped_conn.first)) { - for (auto i : newsig) - bit2sinks[i].push_back(cell); - for (auto i : mapped_conn.second) - bit_users[i].insert(mapped_cell->name); - } - if (cell->output(mapped_conn.first)) - for (auto i : mapped_conn.second) - // Ignore inouts for topo ordering - if (i.wire && !(i.wire->port_input && i.wire->port_output)) - bit_drivers[i].insert(mapped_cell->name); - } - } - else { - RTLIL::Cell *existing_cell = module->cell(mapped_cell->name); - if (!existing_cell) - log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell)); - - if (existing_cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) { - SigBit I = mapped_cell->getPort(ID(i)); - SigBit O = mapped_cell->getPort(ID(o)); - if (I.wire) - I.wire = module->wires_.at(remap_name(I.wire->name)); - log_assert(O.wire); - O.wire = module->wires_.at(remap_name(O.wire->name)); - module->connect(O, I); - continue; - } - - RTLIL::Module* box_module = design->module(existing_cell->type); - log_assert(existing_cell->parameters.empty()); - log_assert(mapped_cell->type == stringf("$__boxid%d", box_module->attributes.at(ID::abc9_box_id).as_int())); - mapped_cell->type = existing_cell->type; - - RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); - cell->parameters = existing_cell->parameters; - cell->attributes = existing_cell->attributes; - module->swap_names(cell, existing_cell); - - auto jt = mapped_cell->connections_.find(ID(i)); - log_assert(jt != mapped_cell->connections_.end()); - SigSpec inputs = std::move(jt->second); - mapped_cell->connections_.erase(jt); - jt = mapped_cell->connections_.find(ID(o)); - log_assert(jt != mapped_cell->connections_.end()); - SigSpec outputs = std::move(jt->second); - mapped_cell->connections_.erase(jt); - - auto abc9_flop = box_module->get_bool_attribute(ID::abc9_flop); - if (abc9_flop) { - // Link this sole flop box output to the output of the existing - // flop box, so that any (public) signal it drives will be - // preserved - SigBit old_q; - for (const auto &port_name : box_ports.at(existing_cell->type)) { - RTLIL::Wire *w = box_module->wire(port_name); - log_assert(w); - if (!w->port_output) - continue; - log_assert(old_q == SigBit()); - log_assert(GetSize(w) == 1); - old_q = existing_cell->getPort(port_name); - } - auto new_q = outputs[0]; - new_q.wire = module->wires_.at(remap_name(new_q.wire->name)); - module->connect(old_q, new_q); - } - else { - for (const auto &i : inputs) - bit_users[i].insert(mapped_cell->name); - for (const auto &i : outputs) - // Ignore inouts for topo ordering - if (i.wire && !(i.wire->port_input && i.wire->port_output)) - bit_drivers[i].insert(mapped_cell->name); - } - - int input_count = 0, output_count = 0; - for (const auto &port_name : box_ports.at(existing_cell->type)) { - RTLIL::Wire *w = box_module->wire(port_name); - log_assert(w); - - SigSpec sig; - if (w->port_input) { - sig = inputs.extract(input_count, GetSize(w)); - input_count += GetSize(w); - } - if (w->port_output) { - sig = outputs.extract(output_count, GetSize(w)); - output_count += GetSize(w); - } - - SigSpec newsig; - for (auto c : sig.chunks()) { - if (c.width == 0) - continue; - //log_assert(c.width == 1); - if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); - newsig.append(c); - } - - if (w->port_input && !abc9_flop) - for (const auto &i : newsig) - bit2sinks[i].push_back(cell); - - cell->setPort(port_name, std::move(newsig)); - } - } - - cell_stats[mapped_cell->type]++; - } - - for (auto cell : boxes) - module->remove(cell); - - // Copy connections (and rename) from mapped_mod to module - for (auto conn : mapped_mod->connections()) { - if (!conn.first.is_fully_const()) { - auto chunks = conn.first.chunks(); - for (auto &c : chunks) - c.wire = module->wires_.at(remap_name(c.wire->name)); - conn.first = std::move(chunks); - } - if (!conn.second.is_fully_const()) { - auto chunks = conn.second.chunks(); - for (auto &c : chunks) - if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); - conn.second = std::move(chunks); - } - module->connect(conn); - } - - for (auto &it : cell_stats) - log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); - int in_wires = 0, out_wires = 0; - - // Stitch in mapped_mod's inputs/outputs into module - for (auto port : mapped_mod->ports) { - RTLIL::Wire *mapped_wire = mapped_mod->wire(port); - RTLIL::Wire *wire = module->wire(port); - log_assert(wire); - wire->attributes.erase(ID::abc9_keep); - - RTLIL::Wire *remap_wire = module->wire(remap_name(port)); - RTLIL::SigSpec signal(wire, remap_wire->start_offset-wire->start_offset, GetSize(remap_wire)); - log_assert(GetSize(signal) >= GetSize(remap_wire)); - - RTLIL::SigSig conn; - if (mapped_wire->port_output) { - conn.first = signal; - conn.second = remap_wire; - out_wires++; - module->connect(conn); - } - else if (mapped_wire->port_input) { - conn.first = remap_wire; - conn.second = signal; - in_wires++; - module->connect(conn); - } - } - - // ABC9 will return $_NOT_ gates in its mapping (since they are - // treated as being "free"), in particular driving primary - // outputs (real primary outputs, or cells treated as blackboxes) - // or driving box inputs. - // Instead of just mapping those $_NOT_ gates into 1-input $lut-s - // at an area and delay cost, see if it is possible to push - // this $_NOT_ into the driving LUT, or into all sink LUTs. - // When this is not possible, (i.e. this signal drives two primary - // outputs, only one of which is complemented) and when the driver - // is a LUT, then clone the LUT so that it can be inverted without - // increasing depth/delay. - for (auto &it : bit_users) - if (bit_drivers.count(it.first)) - for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); - bool no_loops = toposort.sort(); - log_assert(no_loops); - - for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) { - RTLIL::Cell *not_cell = mapped_mod->cell(*ii); - log_assert(not_cell); - if (not_cell->type != ID($_NOT_)) - continue; - auto it = not2drivers.find(not_cell); - if (it == not2drivers.end()) - continue; - RTLIL::Cell *driver_lut = it->second; - RTLIL::SigBit a_bit = not_cell->getPort(ID::A); - RTLIL::SigBit y_bit = not_cell->getPort(ID::Y); - RTLIL::Const driver_mask; - - a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); - y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); - - auto jt = bit2sinks.find(a_bit); - if (jt == bit2sinks.end()) - goto clone_lut; - - for (auto sink_cell : jt->second) - if (sink_cell->type != ID($lut)) - goto clone_lut; - - // Push downstream LUTs past inverter - for (auto sink_cell : jt->second) { - SigSpec A = sink_cell->getPort(ID::A); - RTLIL::Const mask = sink_cell->getParam(ID::LUT); - int index = 0; - for (; index < GetSize(A); index++) - if (A[index] == a_bit) - break; - log_assert(index < GetSize(A)); - int i = 0; - while (i < GetSize(mask)) { - for (int j = 0; j < (1 << index); j++) - std::swap(mask[i+j], mask[i+j+(1 << index)]); - i += 1 << (index+1); - } - A[index] = y_bit; - sink_cell->setPort(ID::A, A); - sink_cell->setParam(ID::LUT, mask); - } - - // Since we have rewritten all sinks (which we know - // to be only LUTs) to be after the inverter, we can - // go ahead and clone the LUT with the expectation - // that the original driving LUT will become dangling - // and get cleaned away -clone_lut: - driver_mask = driver_lut->getParam(ID::LUT); - for (auto &b : driver_mask.bits) { - if (b == RTLIL::State::S0) b = RTLIL::State::S1; - else if (b == RTLIL::State::S1) b = RTLIL::State::S0; - } - auto cell = module->addLut(NEW_ID, - driver_lut->getPort(ID::A), - y_bit, - driver_mask); - for (auto &bit : cell->connections_.at(ID::A)) { - bit.wire = module->wires_.at(remap_name(bit.wire->name)); - bit2sinks[bit].push_back(cell); - } - } - - //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); - log("ABC RESULTS: input signals: %8d\n", in_wires); - log("ABC RESULTS: output signals: %8d\n", out_wires); - - design->remove(mapped_mod); -} - -struct Abc9OpsPass : public Pass { - Abc9OpsPass() : Pass("abc9_ops", "helper functions for ABC9") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" abc9_ops [options] [selection]\n"); - log("\n"); - log("This pass contains a set of supporting operations for use during ABC technology\n"); - log("mapping, and is expected to be called in conjunction with other operations from\n"); - log("the `abc9' script pass. Only fully-selected modules are supported.\n"); - log("\n"); - log(" -check\n"); - log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n"); - log(" (* abc9_carry *) is only given for one input/output port, etc.\n"); - log("\n"); - log(" -prep_hier\n"); - log(" derive all used (* abc9_box *) or (* abc9_flop *) (if -dff option)\n"); - log(" whitebox modules. with (* abc9_flop *) modules, only those containing\n"); - log(" $dff/$_DFF_[NP]_ cells with zero initial state -- due to an ABC limitation\n"); - log(" -- will be derived.\n"); - log("\n"); - log(" -prep_bypass\n"); - log(" create techmap rules in the '$abc9_map' and '$abc9_unmap' designs for\n"); - log(" bypassing sequential (* abc9_box *) modules using a combinatorial box\n"); - log(" (named *_$abc9_byp). bypassing is necessary if sequential elements (e.g.\n"); - log(" $dff, $mem, etc.) are discovered inside so that any combinatorial paths\n"); - log(" will be correctly captured. this bypass box will only contain ports that\n"); - log(" are referenced by a simple path declaration ($specify2 cell) inside a\n"); - log(" specify block.\n"); - log("\n"); - log(" -prep_dff\n"); - log(" select all (* abc9_flop *) modules instantiated in the design and store\n"); - log(" in the named selection '$abc9_flops'.\n"); - log("\n"); - log(" -prep_dff_submod\n"); - log(" within (* abc9_flop *) modules, rewrite all edge-sensitive path\n"); - log(" declarations and $setup() timing checks ($specify3 and $specrule cells)\n"); - log(" that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port to\n"); - log(" the DFF's 'D' port. this is to prepare such specify cells to be moved\n"); - log(" into the flop box.\n"); - log("\n"); - log(" -prep_dff_unmap\n"); - log(" populate the '$abc9_unmap' design with techmap rules for mapping *_$abc9_flop\n"); - log(" cells back into their derived cell types (where the rules created by\n"); - log(" -prep_hier will then map back to the original cell with parameters).\n"); - log("\n"); - log(" -prep_delays\n"); - log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n"); - log(" certain required times.\n"); - log("\n"); - log(" -mark_scc\n"); - log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n"); - log(" (tagged with an (* abc9_scc_id = *) attribute), temporarily mark all\n"); - log(" wires driven by this cell's outputs with a (* keep *) attribute in order\n"); - log(" to break the SCC. this temporary attribute will be removed on -reintegrate.\n"); - log("\n"); - log(" -prep_xaiger\n"); - log(" prepare the design for XAIGER output. this includes computing the\n"); - log(" topological ordering of ABC9 boxes, as well as preparing the '$abc9_holes'\n"); - log(" design that contains the logic behaviour of ABC9 whiteboxes.\n"); - log("\n"); - log(" -dff\n"); - log(" consider flop cells (those instantiating modules marked with (* abc9_flop *))\n"); - log(" during -prep_{delays,xaiger,box}.\n"); - log("\n"); - log(" -prep_lut \n"); - log(" pre-compute the lut library by analysing all modules marked with\n"); - log(" (* abc9_lut= *).\n"); - log("\n"); - log(" -write_lut \n"); - log(" write the pre-computed lut library to .\n"); - log("\n"); - log(" -prep_box\n"); - log(" pre-compute the box library by analysing all modules marked with\n"); - log(" (* abc9_box *).\n"); - log("\n"); - log(" -write_box \n"); - log(" write the pre-computed box library to .\n"); - log("\n"); - log(" -reintegrate\n"); - log(" for each selected module, re-intergrate the module '$abc9'\n"); - log(" by first recovering ABC9 boxes, and then stitching in the remaining primary\n"); - log(" inputs and outputs.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n"); - - bool check_mode = false; - bool prep_delays_mode = false; - bool mark_scc_mode = false; - bool prep_hier_mode = false; - bool prep_bypass_mode = false; - bool prep_dff_mode = false, prep_dff_submod_mode = false, prep_dff_unmap_mode = false; - bool prep_xaiger_mode = false; - bool prep_lut_mode = false; - bool prep_box_mode = false; - bool reintegrate_mode = false; - bool dff_mode = false; - std::string write_lut_dst; - int maxlut = 0; - std::string write_box_dst; - - bool valid = false; - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-check") { - check_mode = true; - valid = true; - continue; - } - if (arg == "-mark_scc") { - mark_scc_mode = true; - valid = true; - continue; - } - if (arg == "-prep_hier") { - prep_hier_mode = true; - valid = true; - continue; - } - if (arg == "-prep_bypass") { - prep_bypass_mode = true; - valid = true; - continue; - } - if (arg == "-prep_dff") { - prep_dff_mode = true; - valid = true; - continue; - } - if (arg == "-prep_dff_submod") { - prep_dff_submod_mode = true; - valid = true; - continue; - } - if (arg == "-prep_dff_unmap") { - prep_dff_unmap_mode = true; - valid = true; - continue; - } - if (arg == "-prep_xaiger") { - prep_xaiger_mode = true; - valid = true; - continue; - } - if (arg == "-prep_delays") { - prep_delays_mode = true; - valid = true; - continue; - } - if (arg == "-prep_lut" && argidx+1 < args.size()) { - prep_lut_mode = true; - maxlut = atoi(args[++argidx].c_str()); - valid = true; - continue; - } - if (arg == "-write_lut" && argidx+1 < args.size()) { - write_lut_dst = args[++argidx]; - rewrite_filename(write_lut_dst); - valid = true; - continue; - } - if (arg == "-prep_box") { - prep_box_mode = true; - valid = true; - continue; - } - if (arg == "-write_box" && argidx+1 < args.size()) { - write_box_dst = args[++argidx]; - rewrite_filename(write_box_dst); - valid = true; - continue; - } - if (arg == "-reintegrate") { - reintegrate_mode = true; - valid = true; - continue; - } - if (arg == "-dff") { - dff_mode = true; - continue; - } - break; - } - extra_args(args, argidx, design); - - if (!valid) - log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); - - if (dff_mode && !check_mode && !prep_hier_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode) - log_cmd_error("'-dff' option is only relevant for -prep_{hier,delay,xaiger} or -reintegrate.\n"); - - if (check_mode) - check(design, dff_mode); - if (prep_hier_mode) - prep_hier(design, dff_mode); - if (prep_bypass_mode) - prep_bypass(design); - if (prep_dff_mode) - prep_dff(design); - if (prep_dff_submod_mode) - prep_dff_submod(design); - if (prep_dff_unmap_mode) - prep_dff_unmap(design); - if (prep_delays_mode) - prep_delays(design, dff_mode); - if (prep_lut_mode) - prep_lut(design, maxlut); - if (prep_box_mode) - prep_box(design); - - for (auto mod : design->selected_modules()) { - if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); - continue; - } - - if (!design->selected_whole_module(mod)) - log_error("Can't handle partially selected module %s!\n", log_id(mod)); - - if (!write_lut_dst.empty()) - write_lut(mod, write_lut_dst); - if (!write_box_dst.empty()) - write_box(mod, write_box_dst); - if (mark_scc_mode) - mark_scc(mod); - if (prep_xaiger_mode) - prep_xaiger(mod, dff_mode); - if (reintegrate_mode) - reintegrate(mod, dff_mode); - } - } -} Abc9OpsPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc index ce151c7f3d2..2ecb2f35abc 100644 --- a/passes/techmap/aigmap.cc +++ b/passes/techmap/aigmap.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct AigmapPass : public Pass { AigmapPass() : Pass("aigmap", "map logic to and-inverter-graph circuit") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -43,7 +43,7 @@ struct AigmapPass : public Pass { log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool nand_mode = false, select_mode = false; diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index b16e9750e73..034731b87c1 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -72,7 +72,7 @@ struct AlumaccWorker RTLIL::SigSpec get_eq() { if (GetSize(cached_eq) == 0) - cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort(ID::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; } @@ -84,7 +84,7 @@ struct AlumaccWorker RTLIL::SigSpec get_cf() { if (GetSize(cached_cf) == 0) { - cached_cf = alu_cell->getPort(ID::CO); + cached_cf = alu_cell->getPort(ID(CO)); log_assert(GetSize(cached_cf) >= 1); cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[GetSize(cached_cf)-1], false, alu_cell->get_src_attribute()); } @@ -93,7 +93,7 @@ struct AlumaccWorker RTLIL::SigSpec get_of() { if (GetSize(cached_of) == 0) { - cached_of = {alu_cell->getPort(ID::CO), alu_cell->getPort(ID::CI)}; + cached_of = {alu_cell->getPort(ID(CO)), alu_cell->getPort(ID(CI))}; log_assert(GetSize(cached_of) >= 2); cached_of = alu_cell->module->Xor(NEW_ID, cached_of[GetSize(cached_of)-1], cached_of[GetSize(cached_of)-2]); } @@ -154,7 +154,7 @@ struct AlumaccWorker if (cell->type.in(ID($pos), ID($neg))) { new_port.in_a = sigmap(cell->getPort(ID::A)); - new_port.is_signed = cell->getParam(ID::A_SIGNED).as_bool(); + new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); new_port.do_subtract = cell->type == ID($neg); n->macc.ports.push_back(new_port); } @@ -162,12 +162,12 @@ struct AlumaccWorker if (cell->type.in(ID($add), ID($sub))) { new_port.in_a = sigmap(cell->getPort(ID::A)); - new_port.is_signed = cell->getParam(ID::A_SIGNED).as_bool(); + new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); new_port.do_subtract = false; n->macc.ports.push_back(new_port); new_port.in_a = sigmap(cell->getPort(ID::B)); - new_port.is_signed = cell->getParam(ID::B_SIGNED).as_bool(); + new_port.is_signed = cell->getParam(ID(B_SIGNED)).as_bool(); new_port.do_subtract = cell->type == ID($sub); n->macc.ports.push_back(new_port); } @@ -176,7 +176,7 @@ struct AlumaccWorker { new_port.in_a = sigmap(cell->getPort(ID::A)); new_port.in_b = sigmap(cell->getPort(ID::B)); - new_port.is_signed = cell->getParam(ID::A_SIGNED).as_bool(); + new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); new_port.do_subtract = false; n->macc.ports.push_back(new_port); } @@ -399,7 +399,7 @@ struct AlumaccWorker bool cmp_less = cell->type.in(ID($lt), ID($le)); bool cmp_equal = cell->type.in(ID($le), ID($ge)); - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); RTLIL::SigSpec A = sigmap(cell->getPort(ID::A)); RTLIL::SigSpec B = sigmap(cell->getPort(ID::B)); @@ -439,7 +439,7 @@ struct AlumaccWorker for (auto cell : eq_cells) { bool cmp_equal = cell->type.in(ID($eq), ID($eqx)); - bool is_signed = cell->getParam(ID::A_SIGNED).as_bool(); + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); RTLIL::SigSpec A = sigmap(cell->getPort(ID::A)); RTLIL::SigSpec B = sigmap(cell->getPort(ID::B)); @@ -495,11 +495,11 @@ struct AlumaccWorker n->alu_cell->setPort(ID::A, n->a); n->alu_cell->setPort(ID::B, n->b); - n->alu_cell->setPort(ID::CI, GetSize(n->c) ? n->c : State::S0); - n->alu_cell->setPort(ID::BI, n->invert_b ? State::S1 : State::S0); + n->alu_cell->setPort(ID(CI), GetSize(n->c) ? n->c : State::S0); + n->alu_cell->setPort(ID(BI), n->invert_b ? State::S1 : State::S0); n->alu_cell->setPort(ID::Y, n->y); - n->alu_cell->setPort(ID::X, module->addWire(NEW_ID, GetSize(n->y))); - n->alu_cell->setPort(ID::CO, module->addWire(NEW_ID, GetSize(n->y))); + n->alu_cell->setPort(ID(X), module->addWire(NEW_ID, GetSize(n->y))); + n->alu_cell->setPort(ID(CO), module->addWire(NEW_ID, GetSize(n->y))); n->alu_cell->fixup_parameters(n->is_signed, n->is_signed); for (auto &it : n->cmp) @@ -550,7 +550,7 @@ struct AlumaccWorker struct AlumaccPass : public Pass { AlumaccPass() : Pass("alumacc", "extract ALU and MACC cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -560,7 +560,7 @@ struct AlumaccPass : public Pass { log("and $macc cells.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ALUMACC pass (create $alu and $macc cells).\n"); diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc index 8643543c8ce..5f30817d4ae 100644 --- a/passes/techmap/attrmap.cc +++ b/passes/techmap/attrmap.cc @@ -81,7 +81,7 @@ struct AttrmapAction { struct AttrmapTocase : AttrmapAction { string name; - bool apply(IdString &id, Const&) override { + bool apply(IdString &id, Const&) YS_OVERRIDE { if (match_name(name, id, true)) id = RTLIL::escape_id(name); return true; @@ -90,7 +90,7 @@ struct AttrmapTocase : AttrmapAction { struct AttrmapRename : AttrmapAction { string old_name, new_name; - bool apply(IdString &id, Const&) override { + bool apply(IdString &id, Const&) YS_OVERRIDE { if (match_name(old_name, id)) id = RTLIL::escape_id(new_name); return true; @@ -101,7 +101,7 @@ struct AttrmapMap : AttrmapAction { bool imap; string old_name, new_name; string old_value, new_value; - bool apply(IdString &id, Const &val) override { + bool apply(IdString &id, Const &val) YS_OVERRIDE { if (match_name(old_name, id) && match_value(old_value, val, true)) { id = RTLIL::escape_id(new_name); val = make_value(new_value); @@ -113,7 +113,7 @@ struct AttrmapMap : AttrmapAction { struct AttrmapRemove : AttrmapAction { bool has_value; string name, value; - bool apply(IdString &id, Const &val) override { + bool apply(IdString &id, Const &val) YS_OVERRIDE { return !(match_name(name, id) && (!has_value || match_value(value, val))); } }; @@ -221,7 +221,7 @@ bool parse_attrmap_paramap_options(size_t &argidx, std::vector &arg struct AttrmapPass : public Pass { AttrmapPass() : Pass("attrmap", "renaming attributes") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -241,7 +241,7 @@ struct AttrmapPass : public Pass { log(" -imap keep=\"false\" keep=0 -remove keep=0\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ATTRMAP pass (move or copy attributes).\n"); @@ -301,7 +301,7 @@ struct AttrmapPass : public Pass { struct ParamapPass : public Pass { ParamapPass() : Pass("paramap", "renaming cell parameters") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -317,7 +317,7 @@ struct ParamapPass : public Pass { log(" paramap -tocase INIT t:LUT4\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing PARAMAP pass (move or copy cell parameters).\n"); diff --git a/passes/techmap/attrmvcp.cc b/passes/techmap/attrmvcp.cc index b3202c587f7..e59aa651896 100644 --- a/passes/techmap/attrmvcp.cc +++ b/passes/techmap/attrmvcp.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct AttrmvcpPass : public Pass { AttrmvcpPass() : Pass("attrmvcp", "move or copy attributes from wires to driving cells") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" attrmvcp [options] [selection]\n"); @@ -53,7 +53,7 @@ struct AttrmvcpPass : public Pass { log(" multiple times.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ATTRMVCP pass (move or copy attributes).\n"); diff --git a/passes/techmap/clkbufmap.cc b/passes/techmap/clkbufmap.cc index 451325fee45..b9cd68883d8 100644 --- a/passes/techmap/clkbufmap.cc +++ b/passes/techmap/clkbufmap.cc @@ -35,7 +35,7 @@ void split_portname_pair(std::string &port1, std::string &port2) struct ClkbufmapPass : public Pass { ClkbufmapPass() : Pass("clkbufmap", "insert global buffers on clock networks") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -76,7 +76,7 @@ struct ClkbufmapPass : public Pass { modules_processed.insert(module); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing CLKBUFMAP pass (inserting global clock buffers).\n"); @@ -129,13 +129,13 @@ struct ClkbufmapPass : public Pass { if (module->get_blackbox_attribute()) { for (auto port : module->ports) { auto wire = module->wire(port); - if (wire->get_bool_attribute(ID::clkbuf_driver)) + if (wire->get_bool_attribute("\\clkbuf_driver")) for (int i = 0; i < GetSize(wire); i++) buf_ports.insert(make_pair(module->name, make_pair(wire->name, i))); - if (wire->get_bool_attribute(ID::clkbuf_sink)) + if (wire->get_bool_attribute("\\clkbuf_sink")) for (int i = 0; i < GetSize(wire); i++) sink_ports.insert(make_pair(module->name, make_pair(wire->name, i))); - auto it = wire->attributes.find(ID::clkbuf_inv); + auto it = wire->attributes.find("\\clkbuf_inv"); if (it != wire->attributes.end()) { IdString in_name = RTLIL::escape_id(it->second.decode_string()); for (int i = 0; i < GetSize(wire); i++) { @@ -215,7 +215,7 @@ struct ClkbufmapPass : public Pass { if (wire->port_input && wire->port_output) continue; bool process_wire = module->selected(wire); - if (!select && wire->get_bool_attribute(ID::clkbuf_inhibit)) + if (!select && wire->get_bool_attribute("\\clkbuf_inhibit")) process_wire = false; if (!process_wire) { // This wire is supposed to be bypassed, so make sure we don't buffer it in @@ -238,7 +238,7 @@ struct ClkbufmapPass : public Pass { buf_ports.insert(make_pair(module->name, make_pair(wire->name, i))); } else if (!sink_wire_bits.count(mapped_wire_bit)) { // Nothing to do. - } else if (driven_wire_bits.count(wire_bit) || (wire->port_input && module->get_bool_attribute(ID::top))) { + } else if (driven_wire_bits.count(wire_bit) || (wire->port_input && module->get_bool_attribute("\\top"))) { // Clock network not yet buffered, driven by one of // our cells or a top-level input -- buffer it. @@ -247,7 +247,7 @@ struct ClkbufmapPass : public Pass { Wire *iwire = module->addWire(NEW_ID); cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit); cell->setPort(RTLIL::escape_id(buf_portname2), iwire); - if (wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute(ID::top)) { + if (wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute("\\top")) { log("Inserting %s on %s.%s[%d].\n", inpad_celltype.c_str(), log_id(module), log_id(wire), i); RTLIL::Cell *cell2 = module->addCell(NEW_ID, RTLIL::escape_id(inpad_celltype)); cell2->setPort(RTLIL::escape_id(inpad_portname), iwire); diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc index 9a23cb90e35..b976b401b0d 100644 --- a/passes/techmap/deminout.cc +++ b/passes/techmap/deminout.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct DeminoutPass : public Pass { DeminoutPass() : Pass("deminout", "demote inout ports to input or output") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" deminout [options] [selection]\n"); @@ -33,7 +33,7 @@ struct DeminoutPass : public Pass { log("\"Demote\" inout ports to input or output ports, if possible.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing DEMINOUT pass (demote inout ports to input or output).\n"); @@ -113,7 +113,7 @@ struct DeminoutPass : public Pass { { if (bits_numports[bit] > 1 || bits_inout.count(bit)) new_input = true, new_output = true; - if (!bit.wire) + if (bit == State::S0 || bit == State::S1) new_output = true; if (bits_written.count(bit)) { new_output = true; @@ -121,7 +121,8 @@ struct DeminoutPass : public Pass { goto tribuf_bit; } else { tribuf_bit: - new_input = true; + if (bits_used.count(bit)) + new_input = true; } } diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc index 62ee3fea640..0242256e571 100644 --- a/passes/techmap/dff2dffe.cc +++ b/passes/techmap/dff2dffe.cc @@ -88,7 +88,7 @@ struct Dff2dffeWorker cell_int_t mux_cell_int = bit2mux.at(d); RTLIL::SigSpec sig_a = sigmap(mux_cell_int.first->getPort(ID::A)); RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort(ID::B)); - RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort(ID::S)); + RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort(ID(S))); int width = GetSize(sig_a), index = mux_cell_int.second; for (int i = 0; i < GetSize(sig_s); i++) @@ -185,8 +185,8 @@ struct Dff2dffeWorker void handle_dff_cell(RTLIL::Cell *dff_cell) { - RTLIL::SigSpec sig_d = sigmap(dff_cell->getPort(ID::D)); - RTLIL::SigSpec sig_q = sigmap(dff_cell->getPort(ID::Q)); + RTLIL::SigSpec sig_d = sigmap(dff_cell->getPort(ID(D))); + RTLIL::SigSpec sig_q = sigmap(dff_cell->getPort(ID(Q))); std::map> grouped_patterns; std::set remaining_indices; @@ -208,15 +208,15 @@ struct Dff2dffeWorker } if (!direct_dict.empty()) { log(" converting %s cell %s to %s for %s -> %s.\n", log_id(dff_cell->type), log_id(dff_cell), log_id(direct_dict.at(dff_cell->type)), log_signal(new_sig_d), log_signal(new_sig_q)); - dff_cell->setPort(ID::E, make_patterns_logic(it.first, true)); + dff_cell->setPort(ID(E), make_patterns_logic(it.first, true)); dff_cell->type = direct_dict.at(dff_cell->type); } else if (dff_cell->type == ID($dff)) { - RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort(ID::CLK), make_patterns_logic(it.first, false), - new_sig_d, new_sig_q, dff_cell->getParam(ID::CLK_POLARITY).as_bool(), true); + RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort(ID(CLK)), make_patterns_logic(it.first, false), + new_sig_d, new_sig_q, dff_cell->getParam(ID(CLK_POLARITY)).as_bool(), true); log(" created $dffe cell %s for %s -> %s.\n", log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q)); } else { - RTLIL::Cell *new_cell = module->addDffeGate(NEW_ID, dff_cell->getPort(ID::C), make_patterns_logic(it.first, true), + RTLIL::Cell *new_cell = module->addDffeGate(NEW_ID, dff_cell->getPort(ID(C)), make_patterns_logic(it.first, true), new_sig_d, new_sig_q, dff_cell->type == ID($_DFF_P_), true); log(" created %s cell %s for %s -> %s.\n", log_id(new_cell->type), log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q)); } @@ -235,9 +235,9 @@ struct Dff2dffeWorker new_sig_d.append(sig_d[i]); new_sig_q.append(sig_q[i]); } - dff_cell->setPort(ID::D, new_sig_d); - dff_cell->setPort(ID::Q, new_sig_q); - dff_cell->setParam(ID::WIDTH, GetSize(remaining_indices)); + dff_cell->setPort(ID(D), new_sig_d); + dff_cell->setPort(ID(Q), new_sig_q); + dff_cell->setParam(ID(WIDTH), GetSize(remaining_indices)); } } @@ -253,7 +253,7 @@ struct Dff2dffeWorker struct Dff2dffePass : public Pass { Dff2dffePass() : Pass("dff2dffe", "transform $dff cells to $dffe cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -282,13 +282,13 @@ struct Dff2dffePass : public Pass { log("\n"); log(" -direct-match \n"); log(" like -direct for all DFF cell types matching the expression.\n"); - log(" this will use $_DFFE_* as matching the\n"); - log(" internal gate type $_DFF_*_, and $_SDFFE_* for those matching\n"); - log(" $_SDFF_*_, except for $_DFF_[NP]_, which is converted to \n"); + log(" this will use $__DFFE_* as matching the\n"); + log(" internal gate type $_DFF_*_, and $__DFFSE_* for those matching\n"); + log(" $_DFFS_*_, except for $_DFF_[NP]_, which is converted to \n"); log(" $_DFFE_[NP]_.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n"); @@ -318,23 +318,23 @@ struct Dff2dffePass : public Pass { const char *pattern = args[++argidx].c_str(); if (patmatch(pattern, "$_DFF_P_" )) found_match = true, direct_dict[ID($_DFF_P_) ] = ID($_DFFE_PP_); if (patmatch(pattern, "$_DFF_N_" )) found_match = true, direct_dict[ID($_DFF_N_) ] = ID($_DFFE_NP_); - if (patmatch(pattern, "$_DFF_NN0_")) found_match = true, direct_dict[ID($_DFF_NN0_)] = ID($_DFFE_NN0P_); - if (patmatch(pattern, "$_DFF_NN1_")) found_match = true, direct_dict[ID($_DFF_NN1_)] = ID($_DFFE_NN1P_); - if (patmatch(pattern, "$_DFF_NP0_")) found_match = true, direct_dict[ID($_DFF_NP0_)] = ID($_DFFE_NP0P_); - if (patmatch(pattern, "$_DFF_NP1_")) found_match = true, direct_dict[ID($_DFF_NP1_)] = ID($_DFFE_NP1P_); - if (patmatch(pattern, "$_DFF_PN0_")) found_match = true, direct_dict[ID($_DFF_PN0_)] = ID($_DFFE_PN0P_); - if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict[ID($_DFF_PN1_)] = ID($_DFFE_PN1P_); - if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict[ID($_DFF_PP0_)] = ID($_DFFE_PP0P_); - if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict[ID($_DFF_PP1_)] = ID($_DFFE_PP1P_); - - if (patmatch(pattern, "$_SDFF_NN0_")) found_match = true, direct_dict[ID($_SDFF_NN0_)] = ID($_SDFFE_NN0P_); - if (patmatch(pattern, "$_SDFF_NN1_")) found_match = true, direct_dict[ID($_SDFF_NN1_)] = ID($_SDFFE_NN1P_); - if (patmatch(pattern, "$_SDFF_NP0_")) found_match = true, direct_dict[ID($_SDFF_NP0_)] = ID($_SDFFE_NP0P_); - if (patmatch(pattern, "$_SDFF_NP1_")) found_match = true, direct_dict[ID($_SDFF_NP1_)] = ID($_SDFFE_NP1P_); - if (patmatch(pattern, "$_SDFF_PN0_")) found_match = true, direct_dict[ID($_SDFF_PN0_)] = ID($_SDFFE_PN0P_); - if (patmatch(pattern, "$_SDFF_PN1_")) found_match = true, direct_dict[ID($_SDFF_PN1_)] = ID($_SDFFE_PN1P_); - if (patmatch(pattern, "$_SDFF_PP0_")) found_match = true, direct_dict[ID($_SDFF_PP0_)] = ID($_SDFFE_PP0P_); - if (patmatch(pattern, "$_SDFF_PP1_")) found_match = true, direct_dict[ID($_SDFF_PP1_)] = ID($_SDFFE_PP1P_); + if (patmatch(pattern, "$_DFF_NN0_")) found_match = true, direct_dict[ID($_DFF_NN0_)] = ID($__DFFE_NN0); + if (patmatch(pattern, "$_DFF_NN1_")) found_match = true, direct_dict[ID($_DFF_NN1_)] = ID($__DFFE_NN1); + if (patmatch(pattern, "$_DFF_NP0_")) found_match = true, direct_dict[ID($_DFF_NP0_)] = ID($__DFFE_NP0); + if (patmatch(pattern, "$_DFF_NP1_")) found_match = true, direct_dict[ID($_DFF_NP1_)] = ID($__DFFE_NP1); + if (patmatch(pattern, "$_DFF_PN0_")) found_match = true, direct_dict[ID($_DFF_PN0_)] = ID($__DFFE_PN0); + if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict[ID($_DFF_PN1_)] = ID($__DFFE_PN1); + if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict[ID($_DFF_PP0_)] = ID($__DFFE_PP0); + if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict[ID($_DFF_PP1_)] = ID($__DFFE_PP1); + + if (patmatch(pattern, "$__DFFS_NN0_")) found_match = true, direct_dict[ID($__DFFS_NN0_)] = ID($__DFFSE_NN0); + if (patmatch(pattern, "$__DFFS_NN1_")) found_match = true, direct_dict[ID($__DFFS_NN1_)] = ID($__DFFSE_NN1); + if (patmatch(pattern, "$__DFFS_NP0_")) found_match = true, direct_dict[ID($__DFFS_NP0_)] = ID($__DFFSE_NP0); + if (patmatch(pattern, "$__DFFS_NP1_")) found_match = true, direct_dict[ID($__DFFS_NP1_)] = ID($__DFFSE_NP1); + if (patmatch(pattern, "$__DFFS_PN0_")) found_match = true, direct_dict[ID($__DFFS_PN0_)] = ID($__DFFSE_PN0); + if (patmatch(pattern, "$__DFFS_PN1_")) found_match = true, direct_dict[ID($__DFFS_PN1_)] = ID($__DFFSE_PN1); + if (patmatch(pattern, "$__DFFS_PP0_")) found_match = true, direct_dict[ID($__DFFS_PP0_)] = ID($__DFFSE_PP0); + if (patmatch(pattern, "$__DFFS_PP1_")) found_match = true, direct_dict[ID($__DFFS_PP1_)] = ID($__DFFSE_PP1); if (!found_match) log_cmd_error("No cell types matched pattern '%s'.\n", pattern); continue; @@ -361,19 +361,19 @@ struct Dff2dffePass : public Pass { for (auto cell_other : mod->selected_cells()) { if (cell_other->type != cell->type) continue; - if (sigmap(cell->getPort(ID::EN)) == sigmap(cell_other->getPort(ID::EN))) + if (sigmap(cell->getPort(ID(EN))) == sigmap(cell_other->getPort(ID(EN)))) ce_use++; } if (ce_use >= min_ce_use) continue; } - RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort(ID::D))); - mod->addDff(NEW_ID, cell->getPort(ID::CLK), tmp, cell->getPort(ID::Q), cell->getParam(ID::CLK_POLARITY).as_bool()); - if (cell->getParam(ID::EN_POLARITY).as_bool()) - mod->addMux(NEW_ID, cell->getPort(ID::Q), cell->getPort(ID::D), cell->getPort(ID::EN), tmp); + RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort(ID(D)))); + mod->addDff(NEW_ID, cell->getPort(ID(CLK)), tmp, cell->getPort(ID(Q)), cell->getParam(ID(CLK_POLARITY)).as_bool()); + if (cell->getParam(ID(EN_POLARITY)).as_bool()) + mod->addMux(NEW_ID, cell->getPort(ID(Q)), cell->getPort(ID(D)), cell->getPort(ID(EN)), tmp); else - mod->addMux(NEW_ID, cell->getPort(ID::D), cell->getPort(ID::Q), cell->getPort(ID::EN), tmp); + mod->addMux(NEW_ID, cell->getPort(ID(D)), cell->getPort(ID(Q)), cell->getPort(ID(EN)), tmp); mod->remove(cell); continue; } @@ -383,7 +383,7 @@ struct Dff2dffePass : public Pass { for (auto cell_other : mod->selected_cells()) { if (cell_other->type != cell->type) continue; - if (sigmap(cell->getPort(ID::E)) == sigmap(cell_other->getPort(ID::E))) + if (sigmap(cell->getPort(ID(E))) == sigmap(cell_other->getPort(ID(E)))) ce_use++; } if (ce_use >= min_ce_use) @@ -393,11 +393,11 @@ struct Dff2dffePass : public Pass { bool clk_pol = cell->type.compare(7, 1, "P") == 0; bool en_pol = cell->type.compare(8, 1, "P") == 0; RTLIL::SigSpec tmp = mod->addWire(NEW_ID); - mod->addDff(NEW_ID, cell->getPort(ID::C), tmp, cell->getPort(ID::Q), clk_pol); + mod->addDff(NEW_ID, cell->getPort(ID(C)), tmp, cell->getPort(ID(Q)), clk_pol); if (en_pol) - mod->addMux(NEW_ID, cell->getPort(ID::Q), cell->getPort(ID::D), cell->getPort(ID::E), tmp); + mod->addMux(NEW_ID, cell->getPort(ID(Q)), cell->getPort(ID(D)), cell->getPort(ID(E)), tmp); else - mod->addMux(NEW_ID, cell->getPort(ID::D), cell->getPort(ID::Q), cell->getPort(ID::E), tmp); + mod->addMux(NEW_ID, cell->getPort(ID(D)), cell->getPort(ID(Q)), cell->getPort(ID(E)), tmp); mod->remove(cell); continue; } diff --git a/passes/techmap/dff2dffs.cc b/passes/techmap/dff2dffs.cc index 6c2cca4bc5c..3fa1ed5cfbc 100644 --- a/passes/techmap/dff2dffs.cc +++ b/passes/techmap/dff2dffs.cc @@ -26,12 +26,12 @@ PRIVATE_NAMESPACE_BEGIN struct Dff2dffsPass : public Pass { Dff2dffsPass() : Pass("dff2dffs", "process sync set/reset with SR over CE priority") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" dff2dffs [options] [selection]\n"); log("\n"); - log("Merge synchronous set/reset $_MUX_ cells to create $_SDFF_[NP][NP][01]_, to be run before\n"); + log("Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before\n"); log("dff2dffe for SR over CE priority.\n"); log("\n"); log(" -match-init\n"); @@ -39,7 +39,7 @@ struct Dff2dffsPass : public Pass { log(" output wire's init attribute (if any).\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing dff2dffs pass (merge synchronous set/reset into FF cells).\n"); @@ -90,7 +90,7 @@ struct Dff2dffsPass : public Pass { for (auto cell : ff_cells) { - SigSpec sig_d = cell->getPort(ID::D); + SigSpec sig_d = cell->getPort(ID(D)); if (GetSize(sig_d) < 1) continue; @@ -103,7 +103,7 @@ struct Dff2dffsPass : public Pass { Cell *mux_cell = sr_muxes.at(bit_d); SigBit bit_a = sigmap(mux_cell->getPort(ID::A)); SigBit bit_b = sigmap(mux_cell->getPort(ID::B)); - SigBit bit_s = sigmap(mux_cell->getPort(ID::S)); + SigBit bit_s = sigmap(mux_cell->getPort(ID(S))); SigBit sr_val, sr_sig; bool invert_sr; @@ -120,9 +120,9 @@ struct Dff2dffsPass : public Pass { } if (match_init) { - SigBit bit_q = cell->getPort(ID::Q); + SigBit bit_q = cell->getPort(ID(Q)); if (bit_q.wire) { - auto it = bit_q.wire->attributes.find(ID::init); + auto it = bit_q.wire->attributes.find(ID(init)); if (it != bit_q.wire->attributes.end()) { auto init_val = it->second[bit_q.offset]; if (init_val == State::S1 && sr_val != State::S1) @@ -138,25 +138,25 @@ struct Dff2dffsPass : public Pass { if (sr_val == State::S1) { if (cell->type == ID($_DFF_N_)) { - if (invert_sr) cell->type = ID($_SDFF_NN1_); - else cell->type = ID($_SDFF_NP1_); + if (invert_sr) cell->type = ID($__DFFS_NN1_); + else cell->type = ID($__DFFS_NP1_); } else { log_assert(cell->type == ID($_DFF_P_)); - if (invert_sr) cell->type = ID($_SDFF_PN1_); - else cell->type = ID($_SDFF_PP1_); + if (invert_sr) cell->type = ID($__DFFS_PN1_); + else cell->type = ID($__DFFS_PP1_); } } else { if (cell->type == ID($_DFF_N_)) { - if (invert_sr) cell->type = ID($_SDFF_NN0_); - else cell->type = ID($_SDFF_NP0_); + if (invert_sr) cell->type = ID($__DFFS_NN0_); + else cell->type = ID($__DFFS_NP0_); } else { log_assert(cell->type == ID($_DFF_P_)); - if (invert_sr) cell->type = ID($_SDFF_PN0_); - else cell->type = ID($_SDFF_PP0_); + if (invert_sr) cell->type = ID($__DFFS_PN0_); + else cell->type = ID($__DFFS_PP0_); } } - cell->setPort(ID::R, sr_sig); - cell->setPort(ID::D, bit_d); + cell->setPort(ID(R), sr_sig); + cell->setPort(ID(D), bit_d); } } } diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc index c60a901c1a7..cf9301442dd 100644 --- a/passes/techmap/dffinit.cc +++ b/passes/techmap/dffinit.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct DffinitPass : public Pass { DffinitPass() : Pass("dffinit", "set INIT param on FF cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -54,7 +54,7 @@ struct DffinitPass : public Pass { log(" the already defined initial value.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing DFFINIT pass (set INIT param on FF cells).\n"); @@ -99,8 +99,8 @@ struct DffinitPass : public Pass { pool used_bits; for (auto wire : module->selected_wires()) { - if (wire->attributes.count(ID::init)) { - Const value = wire->attributes.at(ID::init); + if (wire->attributes.count(ID(init))) { + Const value = wire->attributes.at(ID(init)); for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) if (value[i] != State::Sx) init_bits[sigmap(SigBit(wire, i))] = value[i]; @@ -154,17 +154,15 @@ struct DffinitPass : public Pass { value = Const(low_string); } - if (value.size() != 0) { - log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second), - log_id(it.first), log_signal(sig), log_signal(value)); - cell->setParam(it.second, value); - } + log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second), + log_id(it.first), log_signal(sig), log_signal(value)); + cell->setParam(it.second, value); } } for (auto wire : module->selected_wires()) - if (wire->attributes.count(ID::init)) { - Const &value = wire->attributes.at(ID::init); + if (wire->attributes.count(ID(init))) { + Const &value = wire->attributes.at(ID(init)); bool do_cleanup = true; for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) { SigBit bit = sigmap(SigBit(wire, i)); @@ -175,7 +173,7 @@ struct DffinitPass : public Pass { } if (do_cleanup) { log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire)); - wire->attributes.erase(ID::init); + wire->attributes.erase(ID(init)); } } } diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index c189d649b68..b15109cd31d 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -78,7 +78,7 @@ static void logmap_all() static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, bool &pin_pol) { - if (cell == nullptr || attr == nullptr || attr->value.empty()) + if (cell == NULL || attr == NULL || attr->value.empty()) return false; std::string value = attr->value; @@ -117,7 +117,7 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode) { - LibertyAst *best_cell = nullptr; + LibertyAst *best_cell = NULL; std::map best_cell_ports; int best_cell_pins = 0; bool best_cell_noninv = false; @@ -132,11 +132,11 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has continue; LibertyAst *dn = cell->find("dont_use"); - if (dn != nullptr && dn->value == "true") + if (dn != NULL && dn->value == "true") continue; LibertyAst *ff = cell->find("ff"); - if (ff == nullptr) + if (ff == NULL) continue; std::string cell_clk_pin, cell_rst_pin, cell_next_pin; @@ -163,7 +163,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has double area = 0; LibertyAst *ar = cell->find("area"); - if (ar != nullptr && !ar->value.empty()) + if (ar != NULL && !ar->value.empty()) area = atof(ar->value.c_str()); int num_pins = 0; @@ -175,7 +175,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has continue; LibertyAst *dir = pin->find("direction"); - if (dir == nullptr || dir->value == "internal") + if (dir == NULL || dir->value == "internal") continue; num_pins++; @@ -183,7 +183,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has goto continue_cell_loop; LibertyAst *func = pin->find("function"); - if (dir->value == "output" && func != nullptr) { + if (dir->value == "output" && func != NULL) { std::string value = func->value; for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t")) value.erase(pos, 1); @@ -205,10 +205,10 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has this_cell_ports[pin->args[0]] = 0; } - if (!found_output || (best_cell != nullptr && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output)))) + if (!found_output || (best_cell != NULL && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output)))) continue; - if (best_cell != nullptr && num_pins == best_cell_pins && area > best_cell_area) + if (best_cell != NULL && num_pins == best_cell_pins && area > best_cell_area) continue; best_cell = cell; @@ -219,7 +219,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has continue_cell_loop:; } - if (best_cell != nullptr) { + if (best_cell != NULL) { log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str()); if (prepare_mode) { @@ -238,7 +238,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode) { - LibertyAst *best_cell = nullptr; + LibertyAst *best_cell = NULL; std::map best_cell_ports; int best_cell_pins = 0; bool best_cell_noninv = false; @@ -253,11 +253,11 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool continue; LibertyAst *dn = cell->find("dont_use"); - if (dn != nullptr && dn->value == "true") + if (dn != NULL && dn->value == "true") continue; LibertyAst *ff = cell->find("ff"); - if (ff == nullptr) + if (ff == NULL) continue; std::string cell_clk_pin, cell_set_pin, cell_clr_pin, cell_next_pin; @@ -280,7 +280,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool double area = 0; LibertyAst *ar = cell->find("area"); - if (ar != nullptr && !ar->value.empty()) + if (ar != NULL && !ar->value.empty()) area = atof(ar->value.c_str()); int num_pins = 0; @@ -292,7 +292,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool continue; LibertyAst *dir = pin->find("direction"); - if (dir == nullptr || dir->value == "internal") + if (dir == NULL || dir->value == "internal") continue; num_pins++; @@ -300,7 +300,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool goto continue_cell_loop; LibertyAst *func = pin->find("function"); - if (dir->value == "output" && func != nullptr) { + if (dir->value == "output" && func != NULL) { std::string value = func->value; for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t")) value.erase(pos, 1); @@ -322,10 +322,10 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool this_cell_ports[pin->args[0]] = 0; } - if (!found_output || (best_cell != nullptr && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output)))) + if (!found_output || (best_cell != NULL && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output)))) continue; - if (best_cell != nullptr && num_pins == best_cell_pins && area > best_cell_area) + if (best_cell != NULL && num_pins == best_cell_pins && area > best_cell_area) continue; best_cell = cell; @@ -336,7 +336,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool continue_cell_loop:; } - if (best_cell != nullptr) { + if (best_cell != NULL) { log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str()); if (prepare_mode) { @@ -409,11 +409,11 @@ static void map_sr_to_arst(IdString from, IdString to) if (!cell_mappings.count(from) || cell_mappings.count(to) > 0) return; - char from_clk_pol = from[8]; + char from_clk_pol YS_ATTRIBUTE(unused) = from[8]; char from_set_pol = from[9]; char from_clr_pol = from[10]; - char to_clk_pol = to[6]; - char to_rst_pol = to[7]; + char to_clk_pol YS_ATTRIBUTE(unused) = to[6]; + char to_rst_pol YS_ATTRIBUTE(unused) = to[7]; char to_rst_val = to[8]; log_assert(from_clk_pol == to_clk_pol); @@ -455,9 +455,9 @@ static void map_adff_to_dff(IdString from, IdString to) if (!cell_mappings.count(from) || cell_mappings.count(to) > 0) return; - char from_clk_pol = from[6]; + char from_clk_pol YS_ATTRIBUTE(unused) = from[6]; char from_rst_pol = from[7]; - char to_clk_pol = to[6]; + char to_clk_pol YS_ATTRIBUTE(unused) = to[6]; log_assert(from_clk_pol == to_clk_pol); @@ -481,11 +481,11 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare SigMap sigmap(module); std::vector cell_list; - for (auto cell : module->cells()) { - if (design->selected(module, cell) && cell_mappings.count(cell->type) > 0) - cell_list.push_back(cell); - if (cell->type == ID($_NOT_)) - notmap[sigmap(cell->getPort(ID::A))].insert(cell); + for (auto &it : module->cells_) { + if (design->selected(module, it.second) && cell_mappings.count(it.second->type) > 0) + cell_list.push_back(it.second); + if (it.second->type == ID($_NOT_)) + notmap[sigmap(it.second->getPort(ID::A))].insert(it.second); } std::map stats; @@ -549,7 +549,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare struct DfflibmapPass : public Pass { DfflibmapPass() : Pass("dfflibmap", "technology mapping of flip-flops") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" dfflibmap [-prepare] -liberty [selection]\n"); @@ -565,7 +565,7 @@ struct DfflibmapPass : public Pass { log("liberty file.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n"); @@ -663,9 +663,9 @@ struct DfflibmapPass : public Pass { log(" final dff cell mappings:\n"); logmap_all(); - for (auto module : design->selected_modules()) - if (!module->get_blackbox_attribute()) - dfflibmap(design, module, prepare_mode); + for (auto &it : design->modules_) + if (design->selected(it.second) && !it.second->get_blackbox_attribute()) + dfflibmap(design, it.second, prepare_mode); cell_mappings.clear(); } diff --git a/passes/techmap/dffsr2dff.cc b/passes/techmap/dffsr2dff.cc new file mode 100644 index 00000000000..61b06fdc1ca --- /dev/null +++ b/passes/techmap/dffsr2dff.cc @@ -0,0 +1,213 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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 + +void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell) +{ + if (cell->type == ID($dffsr)) + { + int width = cell->getParam(ID(WIDTH)).as_int(); + bool setpol = cell->getParam(ID(SET_POLARITY)).as_bool(); + bool clrpol = cell->getParam(ID(CLR_POLARITY)).as_bool(); + + SigBit setunused = setpol ? State::S0 : State::S1; + SigBit clrunused = clrpol ? State::S0 : State::S1; + + SigSpec setsig = sigmap(cell->getPort(ID(SET))); + SigSpec clrsig = sigmap(cell->getPort(ID(CLR))); + + Const reset_val; + SigSpec setctrl, clrctrl; + + for (int i = 0; i < width; i++) + { + SigBit setbit = setsig[i], clrbit = clrsig[i]; + + if (setbit == setunused) { + clrctrl.append(clrbit); + reset_val.bits.push_back(State::S0); + continue; + } + + if (clrbit == clrunused) { + setctrl.append(setbit); + reset_val.bits.push_back(State::S1); + continue; + } + + return; + } + + setctrl.sort_and_unify(); + clrctrl.sort_and_unify(); + + if (GetSize(setctrl) > 1 || GetSize(clrctrl) > 1) + return; + + if (GetSize(setctrl) == 0 && GetSize(clrctrl) == 0) + return; + + if (GetSize(setctrl) == 1 && GetSize(clrctrl) == 1) { + if (setpol != clrpol) + return; + if (setctrl != clrctrl) + return; + } + + log("Converting %s cell %s.%s to $adff.\n", log_id(cell->type), log_id(module), log_id(cell)); + + if (GetSize(setctrl) == 1) { + cell->setPort(ID(ARST), setctrl); + cell->setParam(ID(ARST_POLARITY), setpol); + } else { + cell->setPort(ID(ARST), clrctrl); + cell->setParam(ID(ARST_POLARITY), clrpol); + } + + cell->type = ID($adff); + cell->unsetPort(ID(SET)); + cell->unsetPort(ID(CLR)); + cell->setParam(ID(ARST_VALUE), reset_val); + cell->unsetParam(ID(SET_POLARITY)); + cell->unsetParam(ID(CLR_POLARITY)); + + return; + } + + if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), + ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_))) + { + char clkpol = cell->type.c_str()[8]; + char setpol = cell->type.c_str()[9]; + char clrpol = cell->type.c_str()[10]; + + SigBit setbit = sigmap(cell->getPort(ID(S))); + SigBit clrbit = sigmap(cell->getPort(ID(R))); + + SigBit setunused = setpol == 'P' ? State::S0 : State::S1; + SigBit clrunused = clrpol == 'P' ? State::S0 : State::S1; + + IdString oldtype = cell->type; + + if (setbit == setunused) { + cell->type = stringf("$_DFF_%c%c0_", clkpol, clrpol); + cell->unsetPort(ID(S)); + goto converted_gate; + } + + if (clrbit == clrunused) { + cell->type = stringf("$_DFF_%c%c1_", clkpol, setpol); + cell->setPort(ID(R), cell->getPort(ID(S))); + cell->unsetPort(ID(S)); + goto converted_gate; + } + + return; + + converted_gate: + log("Converting %s cell %s.%s to %s.\n", log_id(oldtype), log_id(module), log_id(cell), log_id(cell->type)); + return; + } +} + +void adff_worker(SigMap &sigmap, Module *module, Cell *cell) +{ + if (cell->type == ID($adff)) + { + bool rstpol = cell->getParam(ID(ARST_POLARITY)).as_bool(); + SigBit rstunused = rstpol ? State::S0 : State::S1; + SigSpec rstsig = sigmap(cell->getPort(ID(ARST))); + + if (rstsig != rstunused) + return; + + log("Converting %s cell %s.%s to $dff.\n", log_id(cell->type), log_id(module), log_id(cell)); + + cell->type = ID($dff); + cell->unsetPort(ID(ARST)); + cell->unsetParam(ID(ARST_VALUE)); + cell->unsetParam(ID(ARST_POLARITY)); + + return; + } + + if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), + ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_))) + { + char clkpol = cell->type.c_str()[6]; + char rstpol = cell->type.c_str()[7]; + + SigBit rstbit = sigmap(cell->getPort(ID(R))); + SigBit rstunused = rstpol == 'P' ? State::S0 : State::S1; + + if (rstbit != rstunused) + return; + + IdString newtype = stringf("$_DFF_%c_", clkpol); + log("Converting %s cell %s.%s to %s.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(newtype)); + + cell->type = newtype; + cell->unsetPort(ID(R)); + + return; + } +} + +struct Dffsr2dffPass : public Pass { + Dffsr2dffPass() : Pass("dffsr2dff", "convert DFFSR cells to simpler FF cell types") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" dffsr2dff [options] [selection]\n"); + log("\n"); + log("This pass converts DFFSR cells ($dffsr, $_DFFSR_???_) and ADFF cells ($adff,\n"); + log("$_DFF_???_) to simpler FF cell types when any of the set/reset inputs is unused.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing DFFSR2DFF pass (mapping DFFSR cells to simpler FFs).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-v") { + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) { + SigMap sigmap(module); + for (auto cell : module->selected_cells()) { + dffsr_worker(sigmap, module, cell); + adff_worker(sigmap, module, cell); + } + } + } +} Dffsr2dffPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index 7278cb68096..f8798eea508 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -29,6 +29,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +using RTLIL::id2cstr; + class SubCircuitSolver : public SubCircuit::Solver { public: @@ -56,36 +58,36 @@ class SubCircuitSolver : public SubCircuit::Solver return value; #define param_bool(_n) if (param == _n) return value.as_bool(); - param_bool(ID::ARST_POLARITY); - param_bool(ID::A_SIGNED); - param_bool(ID::B_SIGNED); - param_bool(ID::CLK_ENABLE); - param_bool(ID::CLK_POLARITY); - param_bool(ID::CLR_POLARITY); - param_bool(ID::EN_POLARITY); - param_bool(ID::SET_POLARITY); - param_bool(ID::TRANSPARENT); + param_bool(ID(ARST_POLARITY)); + param_bool(ID(A_SIGNED)); + param_bool(ID(B_SIGNED)); + param_bool(ID(CLK_ENABLE)); + param_bool(ID(CLK_POLARITY)); + param_bool(ID(CLR_POLARITY)); + param_bool(ID(EN_POLARITY)); + param_bool(ID(SET_POLARITY)); + param_bool(ID(TRANSPARENT)); #undef param_bool #define param_int(_n) if (param == _n) return value.as_int(); - param_int(ID::ABITS) - param_int(ID::A_WIDTH) - param_int(ID::B_WIDTH) - param_int(ID::CTRL_IN_WIDTH) - param_int(ID::CTRL_OUT_WIDTH) - param_int(ID::OFFSET) - param_int(ID::PRIORITY) - param_int(ID::RD_PORTS) - param_int(ID::SIZE) - param_int(ID::STATE_BITS) - param_int(ID::STATE_NUM) - param_int(ID::STATE_NUM_LOG2) - param_int(ID::STATE_RST) - param_int(ID::S_WIDTH) - param_int(ID::TRANS_NUM) - param_int(ID::WIDTH) - param_int(ID::WR_PORTS) - param_int(ID::Y_WIDTH) + param_int(ID(ABITS)) + param_int(ID(A_WIDTH)) + param_int(ID(B_WIDTH)) + param_int(ID(CTRL_IN_WIDTH)) + param_int(ID(CTRL_OUT_WIDTH)) + param_int(ID(OFFSET)) + param_int(ID(PRIORITY)) + param_int(ID(RD_PORTS)) + param_int(ID(SIZE)) + param_int(ID(STATE_BITS)) + param_int(ID(STATE_NUM)) + param_int(ID(STATE_NUM_LOG2)) + param_int(ID(STATE_RST)) + param_int(ID(S_WIDTH)) + param_int(ID(TRANS_NUM)) + param_int(ID(WIDTH)) + param_int(ID(WR_PORTS)) + param_int(ID(Y_WIDTH)) #undef param_int return value; @@ -119,8 +121,8 @@ class SubCircuitSolver : public SubCircuit::Solver if (wire_attr.size() > 0) { - RTLIL::Wire *lastNeedleWire = nullptr; - RTLIL::Wire *lastHaystackWire = nullptr; + RTLIL::Wire *lastNeedleWire = NULL; + RTLIL::Wire *lastHaystackWire = NULL; dict emptyAttr; for (auto &conn : needleCell->connections()) @@ -147,27 +149,27 @@ struct bit_ref_t { int bit; }; -bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = nullptr, - int max_fanout = -1, std::set> *split = nullptr) +bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL, + int max_fanout = -1, std::set> *split = NULL) { SigMap sigmap(mod); std::map sig_bit_ref; if (sel && !sel->selected(mod)) { - log(" Skipping module %s as it is not selected.\n", log_id(mod->name)); + log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name)); return false; } if (mod->processes.size() > 0) { - log(" Skipping module %s as it contains unprocessed processes.\n", log_id(mod->name)); + log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name)); return false; } if (constports) { - graph.createNode("$const$0", "$const$0", nullptr, true); - graph.createNode("$const$1", "$const$1", nullptr, true); - graph.createNode("$const$x", "$const$x", nullptr, true); - graph.createNode("$const$z", "$const$z", nullptr, true); + graph.createNode("$const$0", "$const$0", NULL, true); + graph.createNode("$const$1", "$const$1", NULL, true); + graph.createNode("$const$x", "$const$x", NULL, true); + graph.createNode("$const$z", "$const$z", NULL, true); graph.createPort("$const$0", "\\Y", 1); graph.createPort("$const$1", "\\Y", 1); graph.createPort("$const$x", "\\Y", 1); @@ -180,26 +182,28 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, std::map, int> sig_use_count; if (max_fanout > 0) - for (auto cell : mod->cells()) + for (auto &cell_it : mod->cells_) { + RTLIL::Cell *cell = cell_it.second; if (!sel || sel->selected(mod, cell)) for (auto &conn : cell->connections()) { RTLIL::SigSpec conn_sig = conn.second; sigmap.apply(conn_sig); for (auto &bit : conn_sig) - if (bit.wire != nullptr) + if (bit.wire != NULL) sig_use_count[std::pair(bit.wire, bit.offset)]++; } } // create graph nodes from cells - for (auto cell : mod->cells()) + for (auto &cell_it : mod->cells_) { + RTLIL::Cell *cell = cell_it.second; if (sel && !sel->selected(mod, cell)) continue; std::string type = cell->type.str(); - if (sel == nullptr && type.compare(0, 2, "\\$") == 0) + if (sel == NULL && type.compare(0, 2, "\\$") == 0) type = type.substr(1); graph.createNode(cell->name.str(), type, (void*)cell); @@ -217,7 +221,7 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, { auto &bit = conn_sig[i]; - if (bit.wire == nullptr) { + if (bit.wire == NULL) { if (constports) { std::string node = "$const$x"; if (bit == RTLIL::State::S0) node = "$const$0"; @@ -249,8 +253,9 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, } // mark external signals (used in non-selected cells) - for (auto cell : mod->cells()) + for (auto &cell_it : mod->cells_) { + RTLIL::Cell *cell = cell_it.second; if (sel && !sel->selected(mod, cell)) for (auto &conn : cell->connections()) { @@ -266,8 +271,9 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, } // mark external signals (used in module ports) - for (auto wire : mod->wires()) + for (auto &wire_it : mod->wires_) { + RTLIL::Wire *wire = wire_it.second; if (wire->port_id > 0) { RTLIL::SigSpec conn_sig(wire); @@ -294,7 +300,8 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit: RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name); // create cell ports - for (auto wire : needle->wires()) { + for (auto &it : needle->wires_) { + RTLIL::Wire *wire = it.second; if (wire->port_id > 0) { for (int i = 0; i < wire->width; i++) sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair(wire->name, i)); @@ -309,7 +316,7 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit: RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData; RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData; - if (needle_cell == nullptr) + if (needle_cell == NULL) continue; for (auto &conn : needle_cell->connections()) { @@ -334,10 +341,10 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit: bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right) { int left_idx = 0, right_idx = 0; - if (left->attributes.count(ID::extract_order) > 0) - left_idx = left->attributes.at(ID::extract_order).as_int(); - if (right->attributes.count(ID::extract_order) > 0) - right_idx = right->attributes.at(ID::extract_order).as_int(); + if (left->attributes.count(ID(extract_order)) > 0) + left_idx = left->attributes.at(ID(extract_order)).as_int(); + if (right->attributes.count(ID(extract_order)) > 0) + right_idx = right->attributes.at(ID(extract_order)).as_int(); if (left_idx != right_idx) return left_idx < right_idx; return left->name < right->name; @@ -345,7 +352,7 @@ bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right) struct ExtractPass : public Pass { ExtractPass() : Pass("extract", "find subcircuits and replace them with cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -433,7 +440,7 @@ struct ExtractPass : public Pass { log("See 'help techmap' for a pass that does the opposite thing.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing EXTRACT pass (map subcircuits to cells).\n"); log_push(); @@ -580,7 +587,7 @@ struct ExtractPass : public Pass { if (map_filenames.empty() && mine_outfile.empty()) log_cmd_error("Missing option -map or -mine .\n"); - RTLIL::Design *map = nullptr; + RTLIL::Design *map = NULL; if (!mine_mode) { @@ -623,24 +630,24 @@ struct ExtractPass : public Pass { log_header(design, "Creating graphs for SubCircuit library.\n"); if (!mine_mode) - for (auto module : map->modules()) { + for (auto &mod_it : map->modules_) { SubCircuit::Graph mod_graph; - std::string graph_name = "needle_" + RTLIL::unescape_id(module->name); + std::string graph_name = "needle_" + RTLIL::unescape_id(mod_it.first); log("Creating needle graph %s.\n", graph_name.c_str()); - if (module2graph(mod_graph, module, constports)) { + if (module2graph(mod_graph, mod_it.second, constports)) { solver.addGraph(graph_name, mod_graph); - needle_map[graph_name] = module; - needle_list.push_back(module); + needle_map[graph_name] = mod_it.second; + needle_list.push_back(mod_it.second); } } - for (auto module : design->modules()) { + for (auto &mod_it : design->modules_) { SubCircuit::Graph mod_graph; - std::string graph_name = "haystack_" + RTLIL::unescape_id(module->name); + std::string graph_name = "haystack_" + RTLIL::unescape_id(mod_it.first); log("Creating haystack graph %s.\n", graph_name.c_str()); - if (module2graph(mod_graph, module, constports, design, mine_mode ? mine_max_fanout : -1, mine_mode ? &mine_split : nullptr)) { + if (module2graph(mod_graph, mod_it.second, constports, design, mine_mode ? mine_max_fanout : -1, mine_mode ? &mine_split : NULL)) { solver.addGraph(graph_name, mod_graph); - haystack_map[graph_name] = module; + haystack_map[graph_name] = mod_it.second; } } @@ -673,7 +680,7 @@ struct ExtractPass : public Pass { } RTLIL::Cell *new_cell = replace(needle_map.at(result.needleGraphId), haystack_map.at(result.haystackGraphId), result); design->select(haystack_map.at(result.haystackGraphId), new_cell); - log(" new cell: %s\n", log_id(new_cell->name)); + log(" new cell: %s\n", id2cstr(new_cell->name)); } } } @@ -690,12 +697,12 @@ struct ExtractPass : public Pass { for (auto &result: results) { log("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits); - log(" primary match in %s:", log_id(haystack_map.at(result.graphId)->name)); + log(" primary match in %s:", id2cstr(haystack_map.at(result.graphId)->name)); for (auto &node : result.nodes) log(" %s", RTLIL::unescape_id(node.nodeId).c_str()); log("\n"); for (auto &it : result.matchesPerGraph) - log(" matches in %s: %d\n", log_id(haystack_map.at(it.first)->name), it.second); + log(" matches in %s: %d\n", id2cstr(haystack_map.at(it.first)->name), it.second); RTLIL::Module *mod = haystack_map.at(result.graphId); std::set cells; @@ -710,12 +717,12 @@ struct ExtractPass : public Pass { for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = sigmap(conn.second); for (auto &chunk : sig.chunks()) - if (chunk.wire != nullptr) + if (chunk.wire != NULL) wires.insert(chunk.wire); } RTLIL::Module *newMod = new RTLIL::Module; - newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, log_id(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits); + newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, id2cstr(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits); map->add(newMod); for (auto wire : wires) { @@ -732,8 +739,8 @@ struct ExtractPass : public Pass { for (auto &conn : cell->connections()) { std::vector chunks = sigmap(conn.second); for (auto &chunk : chunks) - if (chunk.wire != nullptr) - chunk.wire = newMod->wire(chunk.wire->name); + if (chunk.wire != NULL) + chunk.wire = newMod->wires_.at(chunk.wire->name); newCell->setPort(conn.first, chunks); } } diff --git a/passes/techmap/extract_counter.cc b/passes/techmap/extract_counter.cc index 56b2ea5841b..17a99493d62 100644 --- a/passes/techmap/extract_counter.cc +++ b/passes/techmap/extract_counter.cc @@ -90,35 +90,22 @@ bool is_unconnected(const RTLIL::SigSpec& port, ModIndex& index) struct CounterExtraction { int width; //counter width - bool count_is_up; //count up (else down) RTLIL::Wire* rwire; //the register output bool has_reset; //true if we have a reset bool has_ce; //true if we have a clock enable - bool ce_inverted; //true if clock enable is active low RTLIL::SigSpec rst; //reset pin bool rst_inverted; //true if reset is active low bool rst_to_max; //true if we reset to max instead of 0 int count_value; //value we count from RTLIL::SigSpec ce; //clock signal RTLIL::SigSpec clk; //clock enable, if any - RTLIL::SigSpec outsig; //counter overflow output signal - RTLIL::SigSpec poutsig; //counter parallel output signal - bool has_pout; //whether parallel output is used + RTLIL::SigSpec outsig; //counter output signal RTLIL::Cell* count_mux; //counter mux RTLIL::Cell* count_reg; //counter register - RTLIL::Cell* overflow_cell; //cell for counter overflow (either inverter reduction or $eq) + RTLIL::Cell* underflow_inv; //inverter reduction for output-underflow detect pool pouts; //Ports that take a parallel output from us }; -struct CounterExtractionSettings -{ - pool& parallel_cells; - int maxwidth; - int minwidth; - bool allow_arst; - int allowed_dirs; //0 = down, 1 = up, 2 = both -}; - //attempt to extract a counter centered on the given adder cell //For now we only support DOWN counters. //TODO: up/down support @@ -126,131 +113,48 @@ int counter_tryextract( ModIndex& index, Cell *cell, CounterExtraction& extract, - CounterExtractionSettings settings) + pool& parallel_cells, + int maxwidth) { SigMap& sigmap = index.sigmap; + //A counter with less than 2 bits makes no sense + //TODO: configurable min threshold + int a_width = cell->getParam(ID(A_WIDTH)).as_int(); + extract.width = a_width; + if( (a_width < 2) || (a_width > maxwidth) ) + return 1; + + //Second input must be a single bit + int b_width = cell->getParam(ID(B_WIDTH)).as_int(); + if(b_width != 1) + return 2; + //Both inputs must be unsigned, so don't extract anything with a signed input - bool a_sign = cell->getParam(ID::A_SIGNED).as_bool(); - bool b_sign = cell->getParam(ID::B_SIGNED).as_bool(); + bool a_sign = cell->getParam(ID(A_SIGNED)).as_bool(); + bool b_sign = cell->getParam(ID(B_SIGNED)).as_bool(); if(a_sign || b_sign) return 3; - //CO and X must be unconnected (exactly one connection to each port) - if(!is_unconnected(sigmap(cell->getPort(ID::CO)), index)) - return 7; - if(!is_unconnected(sigmap(cell->getPort(ID::X)), index)) - return 8; + //To be a counter, one input of the ALU must be a constant 1 + //TODO: can A or B be swapped in synthesized RTL or is B always the 1? + const RTLIL::SigSpec b_port = sigmap(cell->getPort(ID::B)); + if(!b_port.is_fully_const() || (b_port.as_int() != 1) ) + return 4; - //true if $alu is performing A - B, else A + B - bool alu_is_subtract; - - //BI and CI must be both constant 0 or both constant 1 as well - const RTLIL::SigSpec bi_port = sigmap(cell->getPort(ID::BI)); - const RTLIL::SigSpec ci_port = sigmap(cell->getPort(ID::CI)); - if(bi_port.is_fully_const() && bi_port.as_int() == 1 && - ci_port.is_fully_const() && ci_port.as_int() == 1) - { - alu_is_subtract = true; - } - else if(bi_port.is_fully_const() && bi_port.as_int() == 0 && - ci_port.is_fully_const() && ci_port.as_int() == 0) - { - alu_is_subtract = false; - } - else - { + //BI and CI must be constant 1 as well + const RTLIL::SigSpec bi_port = sigmap(cell->getPort(ID(BI))); + if(!bi_port.is_fully_const() || (bi_port.as_int() != 1) ) return 5; - } + const RTLIL::SigSpec ci_port = sigmap(cell->getPort(ID(CI))); + if(!ci_port.is_fully_const() || (ci_port.as_int() != 1) ) + return 6; - //false -> port B connects to value - //true -> port A connects to value - bool alu_port_use_a = false; - - if(alu_is_subtract) - { - const int a_width = cell->getParam(ID::A_WIDTH).as_int(); - const int b_width = cell->getParam(ID::B_WIDTH).as_int(); - const RTLIL::SigSpec b_port = sigmap(cell->getPort(ID::B)); - - // down, cnt <= cnt - 1 - if (b_width == 1 && b_port.is_fully_const() && b_port.as_int() == 1) - { - // OK - alu_port_use_a = true; - extract.count_is_up = false; - } - - // up, cnt <= cnt - -1 - else if (b_width == a_width && b_port.is_fully_const() && b_port.is_fully_ones()) - { - // OK - alu_port_use_a = true; - extract.count_is_up = true; - } - - // ??? - else - { - return 2; - } - } - else - { - const int a_width = cell->getParam(ID::A_WIDTH).as_int(); - const int b_width = cell->getParam(ID::B_WIDTH).as_int(); - const RTLIL::SigSpec a_port = sigmap(cell->getPort(ID::A)); - const RTLIL::SigSpec b_port = sigmap(cell->getPort(ID::B)); - - // down, cnt <= cnt + -1 - if (b_width == a_width && b_port.is_fully_const() && b_port.is_fully_ones()) - { - // OK - alu_port_use_a = true; - extract.count_is_up = false; - } - else if (a_width == b_width && a_port.is_fully_const() && a_port.is_fully_ones()) - { - // OK - alu_port_use_a = false; - extract.count_is_up = false; - } - - // up, cnt <= cnt + 1 - else if (b_width == 1 && b_port.is_fully_const() && b_port.as_int() == 1) - { - // OK - alu_port_use_a = true; - extract.count_is_up = true; - } - else if (a_width == 1 && a_port.is_fully_const() && a_port.as_int() == 1) - { - // OK - alu_port_use_a = false; - extract.count_is_up = true; - } - - // ??? - else - { - return 2; - } - } - - if (extract.count_is_up && settings.allowed_dirs == 0) - return 26; - if (!extract.count_is_up && settings.allowed_dirs == 1) - return 26; - - //Check if counter is an appropriate size - int count_width; - if (alu_port_use_a) - count_width = cell->getParam(ID::A_WIDTH).as_int(); - else - count_width = cell->getParam(ID::B_WIDTH).as_int(); - extract.width = count_width; - if( (count_width < settings.minwidth) || (count_width > settings.maxwidth) ) - return 1; + //CO and X must be unconnected (exactly one connection to each port) + if(!is_unconnected(sigmap(cell->getPort(ID(CO))), index)) + return 7; + if(!is_unconnected(sigmap(cell->getPort(ID(X))), index)) + return 8; //Y must have exactly one connection, and it has to be a $mux cell. //We must have a direct bus connection from our Y to their A. @@ -265,43 +169,30 @@ int counter_tryextract( if(!is_full_bus(aluy, index, cell, ID::Y, count_mux, ID::A)) return 11; - if (extract.count_is_up) - { - //B connection of the mux must be 0 - const RTLIL::SigSpec underflow = sigmap(count_mux->getPort(ID::B)); - if(!(underflow.is_fully_const() && underflow.is_fully_zero())) - return 12; - } - else - { - //B connection of the mux is our underflow value - const RTLIL::SigSpec underflow = sigmap(count_mux->getPort(ID::B)); - if(!underflow.is_fully_const()) - return 12; - extract.count_value = underflow.as_int(); - } + //B connection of the mux is our underflow value + const RTLIL::SigSpec underflow = sigmap(count_mux->getPort(ID::B)); + if(!underflow.is_fully_const()) + return 12; + extract.count_value = underflow.as_int(); - //S connection of the mux must come from an inverter if down, eq if up - //(need not be the only load) - const RTLIL::SigSpec muxsel = sigmap(count_mux->getPort(ID::S)); + //S connection of the mux must come from an inverter (need not be the only load) + const RTLIL::SigSpec muxsel = sigmap(count_mux->getPort(ID(S))); extract.outsig = muxsel; pool muxsel_conns = get_other_cells(muxsel, index, count_mux); - Cell* overflow_cell = NULL; + Cell* underflow_inv = NULL; for(auto c : muxsel_conns) { - if(extract.count_is_up && c->type != ID($eq)) + if(c->type != ID($logic_not)) continue; - if(!extract.count_is_up && c->type != ID($logic_not)) - continue; - if(!is_full_bus(muxsel, index, c, ID::Y, count_mux, ID::S, true)) + if(!is_full_bus(muxsel, index, c, ID::Y, count_mux, ID(S), true)) continue; - overflow_cell = c; + underflow_inv = c; break; } - if(overflow_cell == NULL) + if(underflow_inv == NULL) return 13; - extract.overflow_cell = overflow_cell; + extract.underflow_inv = underflow_inv; //Y connection of the mux must have exactly one load, the counter's internal register, if there's no clock enable //If we have a clock enable, Y drives the B input of a mux. A of that mux must come from our register @@ -324,28 +215,18 @@ int counter_tryextract( return 24; count_reg = *cey_loads.begin(); - if(sigmap(cemux->getPort(ID::Y)) != sigmap(count_reg->getPort(ID::D))) - return 24; //Mux should have A driven by count Q, and B by muxy - //if A and B are swapped, CE polarity is inverted - if(sigmap(cemux->getPort(ID::B)) == muxy && - sigmap(cemux->getPort(ID::A)) == sigmap(count_reg->getPort(ID::Q))) - { - extract.ce_inverted = false; - } - else if(sigmap(cemux->getPort(ID::A)) == muxy && - sigmap(cemux->getPort(ID::B)) == sigmap(count_reg->getPort(ID::Q))) - { - extract.ce_inverted = true; - } - else - { + //TODO: if A and B are swapped, CE polarity is inverted + if(sigmap(cemux->getPort(ID::B)) != muxy) + return 24; + if(sigmap(cemux->getPort(ID::A)) != sigmap(count_reg->getPort(ID(Q)))) + return 24; + if(sigmap(cemux->getPort(ID::Y)) != sigmap(count_reg->getPort(ID(D)))) return 24; - } //Select of the mux is our clock enable extract.has_ce = true; - extract.ce = sigmap(cemux->getPort(ID::S)); + extract.ce = sigmap(cemux->getPort(ID(S))); } else extract.has_ce = false; @@ -355,16 +236,13 @@ int counter_tryextract( extract.has_reset = false; else if(count_reg->type == ID($adff)) { - if (!settings.allow_arst) - return 25; - extract.has_reset = true; //Check polarity of reset - we may have to add an inverter later on! - extract.rst_inverted = (count_reg->getParam(ID::ARST_POLARITY).as_int() != 1); + extract.rst_inverted = (count_reg->getParam(ID(ARST_POLARITY)).as_int() != 1); //Verify ARST_VALUE is zero or full scale - int rst_value = count_reg->getParam(ID::ARST_VALUE).as_int(); + int rst_value = count_reg->getParam(ID(ARST_VALUE)).as_int(); if(rst_value == 0) extract.rst_to_max = false; else if(rst_value == extract.count_value) @@ -373,7 +251,7 @@ int counter_tryextract( return 23; //Save the reset - extract.rst = sigmap(count_reg->getPort(ID::ARST)); + extract.rst = sigmap(count_reg->getPort(ID(ARST))); } //TODO: support synchronous reset else @@ -382,14 +260,12 @@ int counter_tryextract( //Sanity check that we use the ALU output properly if(extract.has_ce) { - if(!extract.ce_inverted && !is_full_bus(muxy, index, count_mux, ID::Y, cemux, ID::B)) - return 16; - if(extract.ce_inverted && !is_full_bus(muxy, index, count_mux, ID::Y, cemux, ID::A)) + if(!is_full_bus(muxy, index, count_mux, ID::Y, cemux, ID::B)) return 16; - if(!is_full_bus(cey, index, cemux, ID::Y, count_reg, ID::D)) + if(!is_full_bus(cey, index, cemux, ID::Y, count_reg, ID(D))) return 16; } - else if(!is_full_bus(muxy, index, count_mux, ID::Y, count_reg, ID::D)) + else if(!is_full_bus(muxy, index, count_mux, ID::Y, count_reg, ID(D))) return 16; //TODO: Verify count_reg CLK_POLARITY is 1 @@ -397,9 +273,7 @@ int counter_tryextract( //Register output must have exactly two loads, the inverter and ALU //(unless we have a parallel output!) //If we have a clock enable, 3 is OK - const RTLIL::SigSpec qport = count_reg->getPort(ID::Q); - extract.poutsig = qport; - extract.has_pout = false; + const RTLIL::SigSpec qport = count_reg->getPort(ID(Q)); const RTLIL::SigSpec cnout = sigmap(qport); pool cnout_loads = get_other_cells(cnout, index, count_reg); unsigned int max_loads = 2; @@ -409,7 +283,7 @@ int counter_tryextract( { for(auto c : cnout_loads) { - if(c == overflow_cell) + if(c == underflow_inv) continue; if(c == cell) continue; @@ -417,16 +291,15 @@ int counter_tryextract( continue; //If we specified a limited set of cells for parallel output, check that we only drive them - if(!settings.parallel_cells.empty()) + if(!parallel_cells.empty()) { //Make sure we're in the whitelist - if( settings.parallel_cells.find(c->type) == settings.parallel_cells.end()) + if( parallel_cells.find(c->type) == parallel_cells.end()) return 17; } //Figure out what port(s) are driven by it //TODO: this can probably be done more efficiently w/o multiple iterations over our whole net? - //TODO: For what purpose do we actually need extract.pouts? for(auto b : qport) { pool ports = index.query_ports(b); @@ -435,75 +308,25 @@ int counter_tryextract( if(x.cell != c) continue; extract.pouts.insert(ModIndex::PortInfo(c, x.port, 0)); - extract.has_pout = true; } } } } - for (auto b : qport) - { - if(index.query_is_output(b)) - { - // Parallel out goes out of module - extract.has_pout = true; - } - } - if(!extract.count_is_up) - { - if(!is_full_bus(cnout, index, count_reg, ID::Q, overflow_cell, ID::A, true)) - return 18; - } - else - { - if(is_full_bus(cnout, index, count_reg, ID::Q, overflow_cell, ID::A, true)) - { - // B must be the overflow value - const RTLIL::SigSpec overflow = sigmap(overflow_cell->getPort(ID::B)); - if(!overflow.is_fully_const()) - return 12; - extract.count_value = overflow.as_int(); - } - else if(is_full_bus(cnout, index, count_reg, ID::Q, overflow_cell, ID::B, true)) - { - // A must be the overflow value - const RTLIL::SigSpec overflow = sigmap(overflow_cell->getPort(ID::A)); - if(!overflow.is_fully_const()) - return 12; - extract.count_value = overflow.as_int(); - } - else - { - return 18; - } - } - if(alu_port_use_a && !is_full_bus(cnout, index, count_reg, ID::Q, cell, ID::A, true)) - return 19; - if(!alu_port_use_a && !is_full_bus(cnout, index, count_reg, ID::Q, cell, ID::B, true)) + if(!is_full_bus(cnout, index, count_reg, ID(Q), underflow_inv, ID::A, true)) + return 18; + if(!is_full_bus(cnout, index, count_reg, ID(Q), cell, ID::A, true)) return 19; //Look up the clock from the register - extract.clk = sigmap(count_reg->getPort(ID::CLK)); + extract.clk = sigmap(count_reg->getPort(ID(CLK))); - if(!extract.count_is_up) - { - //Register output net must have an INIT attribute equal to the count value - extract.rwire = cnout.as_wire(); - if(extract.rwire->attributes.find(ID::init) == extract.rwire->attributes.end()) - return 20; - int rinit = extract.rwire->attributes[ID::init].as_int(); - if(rinit != extract.count_value) - return 21; - } - else - { - //Register output net must not have an INIT attribute or it must be zero - extract.rwire = cnout.as_wire(); - if(extract.rwire->attributes.find(ID::init) == extract.rwire->attributes.end()) - return 0; - int rinit = extract.rwire->attributes[ID::init].as_int(); - if(rinit != 0) - return 21; - } + //Register output net must have an INIT attribute equal to the count value + extract.rwire = cnout.as_wire(); + if(extract.rwire->attributes.find(ID(init)) == extract.rwire->attributes.end()) + return 20; + int rinit = extract.rwire->attributes[ID(init)].as_int(); + if(rinit != extract.count_value) + return 21; return 0; } @@ -514,7 +337,8 @@ void counter_worker( unsigned int& total_counters, pool& cells_to_remove, pool>& cells_to_rename, - CounterExtractionSettings settings) + pool& parallel_cells, + int maxwidth) { SigMap& sigmap = index.sigmap; @@ -526,24 +350,20 @@ void counter_worker( //If it's not a wire, don't even try auto port = sigmap(cell->getPort(ID::A)); if(!port.is_wire()) - { - port = sigmap(cell->getPort(ID::B)); - if(!port.is_wire()) - return; - } - RTLIL::Wire* port_wire = port.as_wire(); + return; + RTLIL::Wire* a_wire = port.as_wire(); bool force_extract = false; bool never_extract = false; - string count_reg_src = port_wire->attributes[ID::src].decode_string().c_str(); - if(port_wire->attributes.find(ID(COUNT_EXTRACT)) != port_wire->attributes.end()) + string count_reg_src = a_wire->attributes[ID(src)].decode_string().c_str(); + if(a_wire->attributes.find(ID(COUNT_EXTRACT)) != a_wire->attributes.end()) { - pool sa = port_wire->get_strpool_attribute(ID(COUNT_EXTRACT)); + pool sa = a_wire->get_strpool_attribute(ID(COUNT_EXTRACT)); string extract_value; if(sa.size() >= 1) { extract_value = *sa.begin(); log(" Signal %s declared at %s has COUNT_EXTRACT = %s\n", - log_id(port_wire), + log_id(a_wire), count_reg_src.c_str(), extract_value.c_str()); @@ -565,21 +385,21 @@ void counter_worker( //Attempt to extract a counter CounterExtraction extract; - int reason = counter_tryextract(index, cell, extract, settings); + int reason = counter_tryextract(index, cell, extract, parallel_cells, maxwidth); //Nonzero code - we could not find a matchable counter. //Do nothing, unless extraction was forced in which case give an error if(reason != 0) { - static const char* reasons[]= + static const char* reasons[25]= { "no problem", //0 "counter is too large/small", //1 "counter does not count by one", //2 "counter uses signed math", //3 - "RESERVED, not implemented", //4 - "ALU is not an adder/subtractor", //5 - "RESERVED, not implemented", //6 + "counter does not count by one", //4 + "ALU is not a subtractor", //5 + "ALU is not a subtractor", //6 "ALU ports used outside counter", //7 "ALU ports used outside counter", //8 "ALU output used outside counter", //9 @@ -597,16 +417,14 @@ void counter_worker( "Underflow value is not equal to init value", //21 "RESERVED, not implemented", //22, kept for compatibility but not used anymore "Reset is not to zero or COUNT_TO", //23 - "Clock enable configuration is unsupported", //24 - "Async reset used but not permitted", //25 - "Count direction is not allowed" //26 + "Clock enable configuration is unsupported" //24 }; if(force_extract) { log_error( "Counter extraction is set to FORCE on register %s, but a counter could not be inferred (%s)\n", - log_id(port_wire), + log_id(a_wire), reasons[reason]); } return; @@ -618,16 +436,16 @@ void counter_worker( //Wipe all of the old connections to the ALU cell->unsetPort(ID::A); cell->unsetPort(ID::B); - cell->unsetPort(ID::BI); - cell->unsetPort(ID::CI); - cell->unsetPort(ID::CO); - cell->unsetPort(ID::X); + cell->unsetPort(ID(BI)); + cell->unsetPort(ID(CI)); + cell->unsetPort(ID(CO)); + cell->unsetPort(ID(X)); cell->unsetPort(ID::Y); - cell->unsetParam(ID::A_SIGNED); - cell->unsetParam(ID::A_WIDTH); - cell->unsetParam(ID::B_SIGNED); - cell->unsetParam(ID::B_WIDTH); - cell->unsetParam(ID::Y_WIDTH); + cell->unsetParam(ID(A_SIGNED)); + cell->unsetParam(ID(A_WIDTH)); + cell->unsetParam(ID(B_SIGNED)); + cell->unsetParam(ID(B_WIDTH)); + cell->unsetParam(ID(Y_WIDTH)); //Change the cell type cell->type = ID($__COUNT_); @@ -657,61 +475,44 @@ void counter_worker( //Hook up other stuff //cell->setParam(ID(CLKIN_DIVIDE), RTLIL::Const(1)); cell->setParam(ID(COUNT_TO), RTLIL::Const(extract.count_value)); - cell->setParam(ID::WIDTH, RTLIL::Const(extract.width)); - cell->setPort(ID::CLK, extract.clk); + cell->setParam(ID(WIDTH), RTLIL::Const(extract.width)); + cell->setPort(ID(CLK), extract.clk); cell->setPort(ID(OUT), extract.outsig); //Hook up clock enable if(extract.has_ce) { cell->setParam(ID(HAS_CE), RTLIL::Const(1)); - if(extract.ce_inverted) - { - auto realce = cell->module->addWire(NEW_ID); - cell->module->addNot(NEW_ID, extract.ce, RTLIL::SigSpec(realce)); - cell->setPort(ID(CE), realce); - } - else - cell->setPort(ID(CE), extract.ce); + cell->setPort(ID(CE), extract.ce); } else - { cell->setParam(ID(HAS_CE), RTLIL::Const(0)); - cell->setPort(ID(CE), RTLIL::Const(1)); - } - if(extract.count_is_up) - { - cell->setParam(ID(DIRECTION), RTLIL::Const("UP")); - //XXX: What is this supposed to do? - cell->setPort(ID(UP), RTLIL::Const(1)); - } - else - { - cell->setParam(ID(DIRECTION), RTLIL::Const("DOWN")); - cell->setPort(ID(UP), RTLIL::Const(0)); - } - - //Hook up hard-wired ports, default to no parallel output + //Hook up hard-wired ports (for now up/down are not supported), default to no parallel output cell->setParam(ID(HAS_POUT), RTLIL::Const(0)); cell->setParam(ID(RESET_TO_MAX), RTLIL::Const(0)); + cell->setParam(ID(DIRECTION), RTLIL::Const("DOWN")); + cell->setPort(ID(CE), RTLIL::Const(1)); + cell->setPort(ID(UP), RTLIL::Const(0)); //Hook up any parallel outputs for(auto load : extract.pouts) { log(" Counter has parallel output to cell %s port %s\n", log_id(load.cell->name), log_id(load.port)); - } - if(extract.has_pout) - { + + //Find the wire hooked to the old port + auto sig = load.cell->getPort(load.port); + //Connect it to our parallel output - cell->setPort(ID(POUT), extract.poutsig); + //(this is OK to do more than once b/c they all go to the same place) + cell->setPort(ID(POUT), sig); cell->setParam(ID(HAS_POUT), RTLIL::Const(1)); } //Delete the cells we've replaced (let opt_clean handle deleting the now-redundant wires) cells_to_remove.insert(extract.count_mux); cells_to_remove.insert(extract.count_reg); - cells_to_remove.insert(extract.overflow_cell); + cells_to_remove.insert(extract.underflow_inv); //Log it total_counters ++; @@ -726,19 +527,17 @@ void counter_worker( //TODO: support other kind of reset reset_type += " async resettable"; } - log(" Found %d-bit (%s) %s counter %s (counting %s %d) for register %s, declared at %s\n", + log(" Found %d-bit (%s) down counter %s (counting from %d) for register %s, declared at %s\n", extract.width, reset_type.c_str(), - extract.count_is_up ? "up" : "down", countname.c_str(), - extract.count_is_up ? "to" : "from", extract.count_value, log_id(extract.rwire->name), count_reg_src.c_str()); //Optimize the counter //If we have no parallel output, and we have redundant bits, shrink us - if(!extract.has_pout) + if(extract.pouts.empty()) { //TODO: Need to update this when we add support for counters with nonzero reset values //to make sure the reset value fits in our bit space too @@ -747,7 +546,7 @@ void counter_worker( int newbits = ceil(log2(extract.count_value)); if(extract.width != newbits) { - cell->setParam(ID::WIDTH, RTLIL::Const(newbits)); + cell->setParam(ID(WIDTH), RTLIL::Const(newbits)); log(" Optimizing out %d unused high-order bits (new width is %d)\n", extract.width - newbits, newbits); @@ -760,7 +559,7 @@ void counter_worker( struct ExtractCounterPass : public Pass { ExtractCounterPass() : Pass("extract_counter", "Extract GreenPak4 counter cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -771,16 +570,7 @@ struct ExtractCounterPass : public Pass { log("to the actual target cells.\n"); log("\n"); log(" -maxwidth N\n"); - log(" Only extract counters up to N bits wide (default 64)\n"); - log("\n"); - log(" -minwidth N\n"); - log(" Only extract counters at least N bits wide (default 2)\n"); - log("\n"); - log(" -allow_arst yes|no\n"); - log(" Allow counters to have async reset (default yes)\n"); - log("\n"); - log(" -dir up|down|both\n"); - log(" Look for up-counters, down-counters, or both (default down)\n"); + log(" Only extract counters up to N bits wide\n"); log("\n"); log(" -pout X,Y,...\n"); log(" Only allow parallel output from the counter to the listed cell types\n"); @@ -788,21 +578,13 @@ struct ExtractCounterPass : public Pass { log("\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing EXTRACT_COUNTER pass (find counters in netlist).\n"); - pool _parallel_cells; - CounterExtractionSettings settings - { - _parallel_cells, // parallel_cells - 64, // maxwidth - 2, // minwidth - true, // allow_arst - 0, // allowed_dirs - }; - + int maxwidth = 64; size_t argidx; + pool parallel_cells; for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-pout") @@ -819,63 +601,24 @@ struct ExtractCounterPass : public Pass { { if(pouts[i] == ',') { - settings.parallel_cells.insert(RTLIL::escape_id(tmp)); + parallel_cells.insert(RTLIL::escape_id(tmp)); tmp = ""; } else tmp += pouts[i]; } - settings.parallel_cells.insert(RTLIL::escape_id(tmp)); + parallel_cells.insert(RTLIL::escape_id(tmp)); continue; } if (args[argidx] == "-maxwidth" && argidx+1 < args.size()) { - settings.maxwidth = atoi(args[++argidx].c_str()); - continue; - } - - if (args[argidx] == "-minwidth" && argidx+1 < args.size()) - { - settings.minwidth = atoi(args[++argidx].c_str()); - continue; - } - - if (args[argidx] == "-allow_arst" && argidx+1 < args.size()) - { - auto arg = args[++argidx]; - if (arg == "yes") - settings.allow_arst = true; - else if (arg == "no") - settings.allow_arst = false; - else - log_error("Invalid -allow_arst value \"%s\"\n", arg.c_str()); - continue; - } - - if (args[argidx] == "-dir" && argidx+1 < args.size()) - { - auto arg = args[++argidx]; - if (arg == "up") - settings.allowed_dirs = 1; - else if (arg == "down") - settings.allowed_dirs = 0; - else if (arg == "both") - settings.allowed_dirs = 2; - else - log_error("Invalid -dir value \"%s\"\n", arg.c_str()); + maxwidth = atoi(args[++argidx].c_str()); continue; } } extra_args(args, argidx, design); - if (settings.minwidth < 2) - { - //A counter with less than 2 bits makes no sense - log_warning("Minimum counter width is 2 bits wide\n"); - settings.minwidth = 2; - } - //Extract all of the counters we could find unsigned int total_counters = 0; for (auto module : design->selected_modules()) @@ -885,7 +628,7 @@ struct ExtractCounterPass : public Pass { ModIndex index(module); for (auto cell : module->selected_cells()) - counter_worker(index, cell, total_counters, cells_to_remove, cells_to_rename, settings); + counter_worker(index, cell, total_counters, cells_to_remove, cells_to_rename, parallel_cells, maxwidth); for(auto cell : cells_to_remove) { diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc index 3fcff01c307..9f3bb525bdd 100644 --- a/passes/techmap/extract_fa.cc +++ b/passes/techmap/extract_fa.cc @@ -262,7 +262,7 @@ struct ExtractFaWorker pool new_leaves = leaves; new_leaves.erase(bit); - for (auto port : {ID::A, ID::B, ID::C, ID::D}) { + for (auto port : {ID::A, ID::B, ID(C), ID(D)}) { if (!cell->hasPort(port)) continue; auto bit = sigmap(SigBit(cell->getPort(port))); @@ -395,18 +395,18 @@ struct ExtractFaWorker else { Cell *cell = module->addCell(NEW_ID, ID($fa)); - cell->setParam(ID::WIDTH, 1); + cell->setParam(ID(WIDTH), 1); log(" Created $fa cell %s.\n", log_id(cell)); cell->setPort(ID::A, f3i.inv_a ? module->NotGate(NEW_ID, A) : A); cell->setPort(ID::B, f3i.inv_b ? module->NotGate(NEW_ID, B) : B); - cell->setPort(ID::C, f3i.inv_c ? module->NotGate(NEW_ID, C) : C); + cell->setPort(ID(C), f3i.inv_c ? module->NotGate(NEW_ID, C) : C); X = module->addWire(NEW_ID); Y = module->addWire(NEW_ID); - cell->setPort(ID::X, X); + cell->setPort(ID(X), X); cell->setPort(ID::Y, Y); facache[fakey] = make_tuple(X, Y, cell); @@ -501,18 +501,18 @@ struct ExtractFaWorker else { Cell *cell = module->addCell(NEW_ID, ID($fa)); - cell->setParam(ID::WIDTH, 1); + cell->setParam(ID(WIDTH), 1); log(" Created $fa cell %s.\n", log_id(cell)); cell->setPort(ID::A, f2i.inv_a ? module->NotGate(NEW_ID, A) : A); cell->setPort(ID::B, f2i.inv_b ? module->NotGate(NEW_ID, B) : B); - cell->setPort(ID::C, State::S0); + cell->setPort(ID(C), State::S0); X = module->addWire(NEW_ID); Y = module->addWire(NEW_ID); - cell->setPort(ID::X, X); + cell->setPort(ID(X), X); cell->setPort(ID::Y, Y); } @@ -539,7 +539,7 @@ struct ExtractFaWorker struct ExtractFaPass : public Pass { ExtractFaPass() : Pass("extract_fa", "find and extract full/half adders") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -561,7 +561,7 @@ struct ExtractFaPass : public Pass { log(" Verbose output\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { ExtractFaConfig config; diff --git a/passes/techmap/extract_reduce.cc b/passes/techmap/extract_reduce.cc index 07b4200cc54..11cfddcd9c3 100644 --- a/passes/techmap/extract_reduce.cc +++ b/passes/techmap/extract_reduce.cc @@ -34,7 +34,7 @@ struct ExtractReducePass : public Pass ExtractReducePass() : Pass("extract_reduce", "converts gate chains into $reduce_* cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -63,7 +63,7 @@ struct ExtractReducePass : public Pass (cell->type == ID($_XOR_) && gt == GateType::Xor); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing EXTRACT_REDUCE pass.\n"); log_push(); @@ -286,7 +286,7 @@ struct ExtractReducePass : public Pass SigSpec input; for (auto b : input_pool) if (input_pool_intermed.count(b) == 0) - input.append(b); + input.append_bit(b); SigBit output = sigmap(head_cell->getPort(ID::Y)[0]); @@ -294,9 +294,9 @@ struct ExtractReducePass : public Pass gt == GateType::And ? ID($reduce_and) : gt == GateType::Or ? ID($reduce_or) : gt == GateType::Xor ? ID($reduce_xor) : ""); - new_reduce_cell->setParam(ID::A_SIGNED, 0); - new_reduce_cell->setParam(ID::A_WIDTH, input.size()); - new_reduce_cell->setParam(ID::Y_WIDTH, 1); + new_reduce_cell->setParam(ID(A_SIGNED), 0); + new_reduce_cell->setParam(ID(A_WIDTH), input.size()); + new_reduce_cell->setParam(ID(Y_WIDTH), 1); new_reduce_cell->setPort(ID::A, input); new_reduce_cell->setPort(ID::Y, output); diff --git a/passes/techmap/extractinv.cc b/passes/techmap/extractinv.cc index 9b350456f01..dda71f12a22 100644 --- a/passes/techmap/extractinv.cc +++ b/passes/techmap/extractinv.cc @@ -35,7 +35,7 @@ void split_portname_pair(std::string &port1, std::string &port2) struct ExtractinvPass : public Pass { ExtractinvPass() : Pass("extractinv", "extract explicit inverter cells for invertible cell pins") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -57,7 +57,7 @@ struct ExtractinvPass : public Pass { log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing EXTRACTINV pass (extracting pin inverters).\n"); @@ -90,7 +90,7 @@ struct ExtractinvPass : public Pass { auto cell_wire = cell_module->wire(port.first); if (!cell_wire) continue; - auto it = cell_wire->attributes.find(ID::invertible_pin); + auto it = cell_wire->attributes.find("\\invertible_pin"); if (it == cell_wire->attributes.end()) continue; IdString param_name = RTLIL::escape_id(it->second.decode_string()); diff --git a/passes/techmap/flatten.cc b/passes/techmap/flatten.cc deleted file mode 100644 index b5f55cffaf8..00000000000 --- a/passes/techmap/flatten.cc +++ /dev/null @@ -1,333 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * 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/utils.h" -#include "kernel/sigtools.h" - -#include -#include -#include - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -IdString concat_name(RTLIL::Cell *cell, IdString object_name) -{ - if (object_name[0] == '\\') - return stringf("%s.%s", cell->name.c_str(), object_name.c_str() + 1); - else { - std::string object_name_str = object_name.str(); - if (object_name_str.substr(0, 8) == "$flatten") - object_name_str.erase(0, 8); - return stringf("$flatten%s.%s", cell->name.c_str(), object_name_str.c_str()); - } -} - -template -IdString map_name(RTLIL::Cell *cell, T *object) -{ - return cell->module->uniquify(concat_name(cell, object->name)); -} - -template -void map_attributes(RTLIL::Cell *cell, T *object, IdString orig_object_name) -{ - if (object->has_attribute(ID::src)) - object->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - - // Preserve original names via the hdlname attribute, but only for objects with a fully public name. - if (cell->name[0] == '\\' && (object->has_attribute(ID::hdlname) || orig_object_name[0] == '\\')) { - std::vector hierarchy; - if (object->has_attribute(ID::hdlname)) - hierarchy = object->get_hdlname_attribute(); - else - hierarchy.push_back(orig_object_name.str().substr(1)); - hierarchy.insert(hierarchy.begin(), cell->name.str().substr(1)); - object->set_hdlname_attribute(hierarchy); - } -} - -void map_sigspec(const dict &map, RTLIL::SigSpec &sig, RTLIL::Module *into = nullptr) -{ - vector chunks = sig; - for (auto &chunk : chunks) - if (chunk.wire != nullptr && chunk.wire->module != into) - chunk.wire = map.at(chunk.wire); - sig = chunks; -} - -struct FlattenWorker -{ - bool ignore_wb = false; - - void flatten_cell(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, std::vector &new_cells) - { - // Copy the contents of the flattened cell - - dict memory_map; - for (auto &tpl_memory_it : tpl->memories) { - RTLIL::Memory *new_memory = module->addMemory(map_name(cell, tpl_memory_it.second), tpl_memory_it.second); - map_attributes(cell, new_memory, tpl_memory_it.second->name); - memory_map[tpl_memory_it.first] = new_memory->name; - design->select(module, new_memory); - } - - dict wire_map; - dict positional_ports; - for (auto tpl_wire : tpl->wires()) { - if (tpl_wire->port_id > 0) - positional_ports.emplace(stringf("$%d", tpl_wire->port_id), tpl_wire->name); - - RTLIL::Wire *new_wire = nullptr; - if (tpl_wire->name[0] == '\\') { - RTLIL::Wire *hier_wire = module->wire(concat_name(cell, tpl_wire->name)); - if (hier_wire != nullptr && hier_wire->get_bool_attribute(ID::hierconn)) { - hier_wire->attributes.erase(ID::hierconn); - if (GetSize(hier_wire) < GetSize(tpl_wire)) { - log_warning("Widening signal %s.%s to match size of %s.%s (via %s.%s).\n", - log_id(module), log_id(hier_wire), log_id(tpl), log_id(tpl_wire), log_id(module), log_id(cell)); - hier_wire->width = GetSize(tpl_wire); - } - new_wire = hier_wire; - } - } - if (new_wire == nullptr) { - new_wire = module->addWire(map_name(cell, tpl_wire), tpl_wire); - new_wire->port_input = new_wire->port_output = false; - new_wire->port_id = false; - } - - map_attributes(cell, new_wire, tpl_wire->name); - wire_map[tpl_wire] = new_wire; - design->select(module, new_wire); - } - - for (auto &tpl_proc_it : tpl->processes) { - RTLIL::Process *new_proc = module->addProcess(map_name(cell, tpl_proc_it.second), tpl_proc_it.second); - map_attributes(cell, new_proc, tpl_proc_it.second->name); - auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec(wire_map, sig); }; - new_proc->rewrite_sigspecs(rewriter); - design->select(module, new_proc); - } - - for (auto tpl_cell : tpl->cells()) { - RTLIL::Cell *new_cell = module->addCell(map_name(cell, tpl_cell), tpl_cell); - map_attributes(cell, new_cell, tpl_cell->name); - if (new_cell->type.in(ID($memrd), ID($memwr), ID($meminit))) { - IdString memid = new_cell->getParam(ID::MEMID).decode_string(); - new_cell->setParam(ID::MEMID, Const(memory_map.at(memid).str())); - } else if (new_cell->type == ID($mem)) { - IdString memid = new_cell->getParam(ID::MEMID).decode_string(); - new_cell->setParam(ID::MEMID, Const(concat_name(cell, memid).str())); - } - auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec(wire_map, sig); }; - new_cell->rewrite_sigspecs(rewriter); - design->select(module, new_cell); - new_cells.push_back(new_cell); - } - - for (auto &tpl_conn_it : tpl->connections()) { - RTLIL::SigSig new_conn = tpl_conn_it; - map_sigspec(wire_map, new_conn.first); - map_sigspec(wire_map, new_conn.second); - module->connect(new_conn); - } - - // Attach port connections of the flattened cell - - SigMap tpl_sigmap(tpl); - pool tpl_driven; - for (auto tpl_cell : tpl->cells()) - for (auto &tpl_conn : tpl_cell->connections()) - if (tpl_cell->output(tpl_conn.first)) - for (auto bit : tpl_sigmap(tpl_conn.second)) - tpl_driven.insert(bit); - for (auto &tpl_conn : tpl->connections()) - for (auto bit : tpl_sigmap(tpl_conn.first)) - tpl_driven.insert(bit); - - SigMap sigmap(module); - for (auto &port_it : cell->connections()) - { - IdString port_name = port_it.first; - if (positional_ports.count(port_name) > 0) - port_name = positional_ports.at(port_name); - if (tpl->wire(port_name) == nullptr || tpl->wire(port_name)->port_id == 0) { - if (port_name.begins_with("$")) - log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", - port_name.c_str(), cell->name.c_str(), tpl->name.c_str()); - continue; - } - - if (GetSize(port_it.second) == 0) - continue; - - RTLIL::Wire *tpl_wire = tpl->wire(port_name); - RTLIL::SigSig new_conn; - if (tpl_wire->port_output && !tpl_wire->port_input) { - new_conn.first = port_it.second; - new_conn.second = tpl_wire; - } else if (!tpl_wire->port_output && tpl_wire->port_input) { - new_conn.first = tpl_wire; - new_conn.second = port_it.second; - } else { - SigSpec sig_tpl = tpl_wire, sig_mod = port_it.second; - for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) { - if (tpl_driven.count(tpl_sigmap(sig_tpl[i]))) { - new_conn.first.append(sig_mod[i]); - new_conn.second.append(sig_tpl[i]); - } else { - new_conn.first.append(sig_tpl[i]); - new_conn.second.append(sig_mod[i]); - } - } - } - map_sigspec(wire_map, new_conn.first, module); - map_sigspec(wire_map, new_conn.second, module); - - if (new_conn.second.size() > new_conn.first.size()) - new_conn.second.remove(new_conn.first.size(), new_conn.second.size() - new_conn.first.size()); - if (new_conn.second.size() < new_conn.first.size()) - new_conn.second.append(RTLIL::SigSpec(RTLIL::State::S0, new_conn.first.size() - new_conn.second.size())); - log_assert(new_conn.first.size() == new_conn.second.size()); - - if (sigmap(new_conn.first).has_const()) - log_error("Mismatch in directionality for cell port %s.%s.%s: %s <= %s\n", - log_id(module), log_id(cell), log_id(port_it.first), log_signal(new_conn.first), log_signal(new_conn.second)); - - module->connect(new_conn); - } - - module->remove(cell); - } - - void flatten_module(RTLIL::Design *design, RTLIL::Module *module, pool &used_modules) - { - if (!design->selected(module) || module->get_blackbox_attribute(ignore_wb)) - return; - - std::vector worklist = module->selected_cells(); - while (!worklist.empty()) - { - RTLIL::Cell *cell = worklist.back(); - worklist.pop_back(); - - if (!design->has(cell->type)) - continue; - - RTLIL::Module *tpl = design->module(cell->type); - if (tpl->get_blackbox_attribute(ignore_wb)) - continue; - - if (cell->get_bool_attribute(ID::keep_hierarchy) || tpl->get_bool_attribute(ID::keep_hierarchy)) { - log("Keeping %s.%s (found keep_hierarchy attribute).\n", log_id(module), log_id(cell)); - used_modules.insert(tpl); - continue; - } - - log_debug("Flattening %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); - // If a design is fully selected and has a top module defined, topological sorting ensures that all cells - // added during flattening are black boxes, and flattening is finished in one pass. However, when flattening - // individual modules, this isn't the case, and the newly added cells might have to be flattened further. - flatten_cell(design, module, cell, tpl, worklist); - } - } -}; - -struct FlattenPass : public Pass { - FlattenPass() : Pass("flatten", "flatten design") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" flatten [options] [selection]\n"); - log("\n"); - log("This pass flattens the design by replacing cells by their implementation. This\n"); - log("pass is very similar to the 'techmap' pass. The only difference is that this\n"); - log("pass is using the current design as mapping library.\n"); - log("\n"); - log("Cells and/or modules with the 'keep_hierarchy' attribute set will not be\n"); - log("flattened by this command.\n"); - log("\n"); - log(" -wb\n"); - log(" Ignore the 'whitebox' attribute on cell implementations.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - log_header(design, "Executing FLATTEN pass (flatten design).\n"); - log_push(); - - FlattenWorker worker; - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-wb") { - worker.ignore_wb = true; - continue; - } - break; - } - extra_args(args, argidx, design); - - RTLIL::Module *top = nullptr; - if (design->full_selection()) - for (auto module : design->modules()) - if (module->get_bool_attribute(ID::top)) - top = module; - - pool used_modules; - if (top == nullptr) - used_modules = design->modules(); - else - used_modules.insert(top); - - TopoSort> topo_modules; - pool worklist = used_modules; - while (!worklist.empty()) { - RTLIL::Module *module = worklist.pop(); - for (auto cell : module->selected_cells()) { - RTLIL::Module *tpl = design->module(cell->type); - if (tpl != nullptr) { - if (topo_modules.database.count(tpl) == 0) - worklist.insert(tpl); - topo_modules.edge(tpl, module); - } - } - } - - if (!topo_modules.sort()) - log_error("Cannot flatten a design containing recursive instantiations.\n"); - - for (auto module : topo_modules.sorted) - worker.flatten_module(design, module, used_modules); - - if (top != nullptr) - for (auto module : design->modules().to_vector()) - if (!used_modules[module] && !module->get_blackbox_attribute(worker.ignore_wb)) { - log("Deleting now unused module %s.\n", log_id(module)); - design->remove(module); - } - - log_pop(); - } -} FlattenPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc index dfdbe6b88fb..a2ad87f7d27 100644 --- a/passes/techmap/flowmap.cc +++ b/passes/techmap/flowmap.cc @@ -1405,7 +1405,7 @@ struct FlowmapWorker RTLIL::SigSpec lut_a, lut_y = node; for (auto input_node : input_nodes) - lut_a.append(input_node); + lut_a.append_bit(input_node); lut_a.append(RTLIL::Const(State::Sx, minlut - input_nodes.size())); RTLIL::Cell *lut = module->addLut(NEW_ID, lut_a, lut_y, lut_table); @@ -1413,7 +1413,7 @@ struct FlowmapWorker for (auto gate_node : lut_gates[node]) { auto gate_origin = node_origins[gate_node]; - lut->add_strpool_attribute(ID::src, gate_origin.cell->get_strpool_attribute(ID::src)); + lut->add_strpool_attribute(ID(src), gate_origin.cell->get_strpool_attribute(ID(src))); packed_count++; } lut_count++; @@ -1470,7 +1470,7 @@ static void split(std::vector &tokens, const std::string &text, cha struct FlowmapPass : public Pass { FlowmapPass() : Pass("flowmap", "pack LUTs with FlowMap") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1511,7 +1511,7 @@ struct FlowmapPass : public Pass { log(" explain decisions performed during depth relaxation.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { int order = 3; int minlut = 1; diff --git a/passes/techmap/hilomap.cc b/passes/techmap/hilomap.cc index b808a8d8e6f..9ec651aefb2 100644 --- a/passes/techmap/hilomap.cc +++ b/passes/techmap/hilomap.cc @@ -55,7 +55,7 @@ void hilomap_worker(RTLIL::SigSpec &sig) struct HilomapPass : public Pass { HilomapPass() : Pass("hilomap", "technology mapping of constant hi- and/or lo-drivers") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" hilomap [options] [selection]\n"); @@ -74,7 +74,7 @@ struct HilomapPass : public Pass { log(" each constant bit.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing HILOMAP pass (mapping to constant drivers).\n"); @@ -105,9 +105,13 @@ struct HilomapPass : public Pass { } extra_args(args, argidx, design); - for (auto mod : design->selected_modules()) + for (auto &it : design->modules_) { - module = mod; + module = it.second; + + if (!design->selected(module)) + continue; + last_hi = RTLIL::State::Sm; last_lo = RTLIL::State::Sm; diff --git a/passes/techmap/insbuf.cc b/passes/techmap/insbuf.cc index a3b5b698d5d..2173049b4db 100644 --- a/passes/techmap/insbuf.cc +++ b/passes/techmap/insbuf.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct InsbufPass : public Pass { InsbufPass() : Pass("insbuf", "insert buffer cells for connected wires") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" insbuf [options] [selection]\n"); @@ -37,20 +37,20 @@ struct InsbufPass : public Pass { log(" call to \"clean\" will remove all $_BUF_ in the design.)\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing INSBUF pass (insert buffer cells for connected wires).\n"); - IdString celltype = ID($_BUF_), in_portname = ID::A, out_portname = ID::Y; + std::string celltype = "$_BUF_", in_portname = "\\A", out_portname = "\\Y"; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; if (arg == "-buf" && argidx+3 < args.size()) { - celltype = RTLIL::escape_id(args[++argidx]); - in_portname = RTLIL::escape_id(args[++argidx]); - out_portname = RTLIL::escape_id(args[++argidx]); + celltype = args[++argidx]; + in_portname = args[++argidx]; + out_portname = args[++argidx]; continue; } break; @@ -76,9 +76,9 @@ struct InsbufPass : public Pass { continue; } - Cell *cell = module->addCell(NEW_ID, celltype); - cell->setPort(in_portname, rhs); - cell->setPort(out_portname, lhs); + Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype)); + cell->setPort(RTLIL::escape_id(in_portname), rhs); + cell->setPort(RTLIL::escape_id(out_portname), lhs); log("Added %s.%s: %s -> %s\n", log_id(module), log_id(cell), log_signal(rhs), log_signal(lhs)); } diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index e8530a0347d..90cfef71e70 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -34,7 +34,7 @@ void split_portname_pair(std::string &port1, std::string &port2) struct IopadmapPass : public Pass { IopadmapPass() : Pass("iopadmap", "technology mapping of i/o pads (or buffers)") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" iopadmap [options] [selection]\n"); @@ -83,21 +83,7 @@ struct IopadmapPass : public Pass { log("Tristate PADS (-toutpad, -tinoutpad) always operate in -bits mode.\n"); log("\n"); } - - void module_queue(Design *design, Module *module, std::vector &modules_sorted, pool &modules_processed) { - if (modules_processed.count(module)) - return; - for (auto cell : module->cells()) { - Module *submodule = design->module(cell->type); - if (!submodule) - continue; - module_queue(design, submodule, modules_sorted, modules_processed); - } - modules_sorted.push_back(module); - modules_processed.insert(module); - } - - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n"); @@ -186,79 +172,31 @@ struct IopadmapPass : public Pass { if (!tinoutpad_portname_pad.empty()) ignore.insert(make_pair(RTLIL::escape_id(tinoutpad_celltype), RTLIL::escape_id(tinoutpad_portname_pad))); - // Recursively collect list of (module, port, bit) triples that already have buffers. - - pool>> buf_ports; + for (auto module : design->modules()) + if (module->get_blackbox_attribute()) + for (auto wire : module->wires()) + if (wire->get_bool_attribute("\\iopad_external_pin")) + ignore.insert(make_pair(module->name, wire->name)); - // Process submodules before module using them. - std::vector modules_sorted; - pool modules_processed; for (auto module : design->selected_modules()) - module_queue(design, module, modules_sorted, modules_processed); - - for (auto module : modules_sorted) { - pool buf_bits; - SigMap sigmap(module); - - // Collect explicitly-marked already-buffered SigBits. - for (auto wire : module->wires()) - if (wire->get_bool_attribute(ID::iopad_external_pin) || ignore.count(make_pair(module->name, wire->name))) - for (int i = 0; i < GetSize(wire); i++) - buf_bits.insert(sigmap(SigBit(wire, i))); + pool skip_wire_bits; + dict>> rewrite_bits; - // Collect SigBits connected to already-buffered ports. for (auto cell : module->cells()) for (auto port : cell->connections()) - for (int i = 0; i < port.second.size(); i++) - if (buf_ports.count(make_pair(cell->type, make_pair(port.first, i)))) - buf_bits.insert(sigmap(port.second[i])); - - // Now fill buf_ports. - for (auto wire : module->wires()) - if (wire->port_input || wire->port_output) - for (int i = 0; i < GetSize(wire); i++) - if (buf_bits.count(sigmap(SigBit(wire, i)))) { - buf_ports.insert(make_pair(module->name, make_pair(wire->name, i))); - log("Marking already mapped port: %s.%s[%d].\n", log_id(module), log_id(wire), i); - } - } - - // Now do the actual buffer insertion. - - for (auto module : design->selected_modules()) - { - dict>> rewrite_bits; - pool remove_conns; + if (ignore.count(make_pair(cell->type, port.first))) + for (auto bit : port.second) + skip_wire_bits.insert(bit); if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty()) { dict tbuf_bits; - pool driven_bits; - dict z_conns; - // Gather tristate buffers and always-on drivers. for (auto cell : module->cells()) if (cell->type == ID($_TBUF_)) { SigBit bit = cell->getPort(ID::Y).as_bit(); tbuf_bits[bit] = cell; - } else { - for (auto port : cell->connections()) - if (!cell->known() || cell->output(port.first)) - for (auto bit : port.second) - driven_bits.insert(bit); - } - - // If a wire is a target of an assignment, it is driven, unless the source is 'z. - for (auto &conn : module->connections()) - for (int i = 0; i < GetSize(conn.first); i++) { - SigBit dstbit = conn.first[i]; - SigBit srcbit = conn.second[i]; - if (!srcbit.wire && srcbit.data == State::Sz) { - z_conns[dstbit] = conn; - continue; - } - driven_bits.insert(dstbit); } for (auto wire : module->selected_wires()) @@ -266,92 +204,56 @@ struct IopadmapPass : public Pass { if (!wire->port_output) continue; - // Don't handle inout ports if we have no suitable buffer type. - if (wire->port_input && tinoutpad_celltype.empty()) - continue; - - // likewise for output ports. - if (!wire->port_input && toutpad_celltype.empty()) - continue; - for (int i = 0; i < GetSize(wire); i++) { SigBit wire_bit(wire, i); - Cell *tbuf_cell = nullptr; - if (buf_ports.count(make_pair(module->name, make_pair(wire->name, i)))) + if (tbuf_bits.count(wire_bit) == 0) continue; - if (tbuf_bits.count(wire_bit)) - tbuf_cell = tbuf_bits.at(wire_bit); - - SigBit en_sig; - SigBit data_sig; - bool is_driven = driven_bits.count(wire_bit); - - if (tbuf_cell != nullptr) { - // Found a tristate buffer — use it. - en_sig = tbuf_cell->getPort(ID::E).as_bit(); - data_sig = tbuf_cell->getPort(ID::A).as_bit(); - } else if (is_driven) { - // No tristate buffer, but an always-on driver is present. - // If this is an inout port, we're creating a tinoutpad - // anyway, just with a constant 1 as enable. - if (!wire->port_input) - continue; - en_sig = SigBit(State::S1); - data_sig = wire_bit; - } else { - // No driver on a wire. Create a tristate pad with always-0 - // enable. - en_sig = SigBit(State::S0); - data_sig = SigBit(State::Sx); - if (z_conns.count(wire_bit)) - remove_conns.insert(z_conns[wire_bit]); - } + Cell *tbuf_cell = tbuf_bits.at(wire_bit); + + if (tbuf_cell == nullptr) + continue; + + SigBit en_sig = tbuf_cell->getPort(ID(E)).as_bit(); + SigBit data_sig = tbuf_cell->getPort(ID::A).as_bit(); - if (wire->port_input) + if (wire->port_input && !tinoutpad_celltype.empty()) { log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype.c_str()); - Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), - RTLIL::escape_id(tinoutpad_celltype)); + Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(tinoutpad_celltype)); cell->setPort(RTLIL::escape_id(tinoutpad_portname_oe), en_sig); + cell->setPort(RTLIL::escape_id(tinoutpad_portname_o), wire_bit); + cell->setPort(RTLIL::escape_id(tinoutpad_portname_i), data_sig); cell->attributes[ID::keep] = RTLIL::Const(1); - if (tbuf_cell) { - module->remove(tbuf_cell); - cell->setPort(RTLIL::escape_id(tinoutpad_portname_o), wire_bit); - cell->setPort(RTLIL::escape_id(tinoutpad_portname_i), data_sig); - } else if (is_driven) { - cell->setPort(RTLIL::escape_id(tinoutpad_portname_i), wire_bit); - } else { - cell->setPort(RTLIL::escape_id(tinoutpad_portname_o), wire_bit); - cell->setPort(RTLIL::escape_id(tinoutpad_portname_i), data_sig); - } + module->remove(tbuf_cell); + skip_wire_bits.insert(wire_bit); if (!tinoutpad_portname_pad.empty()) rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(tinoutpad_portname_pad)); - } else { + continue; + } + + if (!wire->port_input && !toutpad_celltype.empty()) + { log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, toutpad_celltype.c_str()); - Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), - RTLIL::escape_id(toutpad_celltype)); + Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(toutpad_celltype)); cell->setPort(RTLIL::escape_id(toutpad_portname_oe), en_sig); cell->setPort(RTLIL::escape_id(toutpad_portname_i), data_sig); cell->attributes[ID::keep] = RTLIL::Const(1); - if (tbuf_cell) { - module->remove(tbuf_cell); - module->connect(wire_bit, data_sig); - } + module->remove(tbuf_cell); + module->connect(wire_bit, data_sig); + skip_wire_bits.insert(wire_bit); if (!toutpad_portname_pad.empty()) rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(toutpad_portname_pad)); + continue; } - buf_ports.insert(make_pair(module->name, make_pair(wire->name, i))); } } } @@ -365,7 +267,7 @@ struct IopadmapPass : public Pass { pool skip_bit_indices; for (int i = 0; i < GetSize(wire); i++) - if (buf_ports.count(make_pair(module->name, make_pair(wire->name, i)))) + if (skip_wire_bits.count(SigBit(wire, i))) skip_bit_indices.insert(i); if (GetSize(wire) == GetSize(skip_bit_indices)) @@ -416,9 +318,7 @@ struct IopadmapPass : public Pass { SigBit wire_bit(wire, i); - RTLIL::Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), - RTLIL::escape_id(celltype)); + RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype)); cell->setPort(RTLIL::escape_id(portname_int), wire_bit); if (!portname_pad.empty()) @@ -432,16 +332,12 @@ struct IopadmapPass : public Pass { } else { - RTLIL::Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), - RTLIL::escape_id(celltype)); + RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype)); cell->setPort(RTLIL::escape_id(portname_int), RTLIL::SigSpec(wire)); if (!portname_pad.empty()) { RTLIL::Wire *new_wire = NULL; - new_wire = module->addWire( - module->uniquify(stringf("$iopadmap$%s", log_id(wire))), - wire); + new_wire = module->addWire(NEW_ID, wire); module->swap_names(new_wire, wire); wire->attributes.clear(); cell->setPort(RTLIL::escape_id(portname_pad), RTLIL::SigSpec(new_wire)); @@ -460,19 +356,9 @@ struct IopadmapPass : public Pass { } } - if (!remove_conns.empty()) { - std::vector new_conns; - for (auto &conn : module->connections()) - if (!remove_conns.count(conn)) - new_conns.push_back(conn); - module->new_connections(new_conns); - } - for (auto &it : rewrite_bits) { RTLIL::Wire *wire = it.first; - RTLIL::Wire *new_wire = module->addWire( - module->uniquify(stringf("$iopadmap$%s", log_id(wire))), - wire); + RTLIL::Wire *new_wire = module->addWire(NEW_ID, wire); module->swap_names(new_wire, wire); wire->attributes.clear(); for (int i = 0; i < wire->width; i++) @@ -489,15 +375,6 @@ struct IopadmapPass : public Pass { } } - if (wire->port_output) { - auto jt = new_wire->attributes.find(ID::init); - // For output ports, move \init attributes from old wire to new wire - if (jt != new_wire->attributes.end()) { - wire->attributes[ID::init] = std::move(jt->second); - new_wire->attributes.erase(jt); - } - } - wire->port_id = 0; wire->port_input = false; wire->port_output = false; diff --git a/passes/techmap/lut2mux.cc b/passes/techmap/lut2mux.cc index f56eff3e5f7..c6618fc9dea 100644 --- a/passes/techmap/lut2mux.cc +++ b/passes/techmap/lut2mux.cc @@ -27,7 +27,7 @@ int lut2mux(Cell *cell) { SigSpec sig_a = cell->getPort(ID::A); SigSpec sig_y = cell->getPort(ID::Y); - Const lut = cell->getParam(ID::LUT); + Const lut = cell->getParam(ID(LUT)); int count = 1; if (GetSize(sig_a) == 1) @@ -56,7 +56,7 @@ int lut2mux(Cell *cell) struct Lut2muxPass : public Pass { Lut2muxPass() : Pass("lut2mux", "convert $lut to $_MUX_") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -65,7 +65,7 @@ struct Lut2muxPass : public Pass { log("This pass converts $lut cells to $_MUX_ gates.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing LUT2MUX pass (convert $lut to $_MUX_).\n"); diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc index 43f2d97f590..09f61927c03 100644 --- a/passes/techmap/maccmap.cc +++ b/passes/techmap/maccmap.cc @@ -112,12 +112,12 @@ struct MaccmapWorker RTLIL::Wire *w2 = module->addWire(NEW_ID, width); RTLIL::Cell *cell = module->addCell(NEW_ID, ID($fa)); - cell->setParam(ID::WIDTH, width); + cell->setParam(ID(WIDTH), width); cell->setPort(ID::A, in1); cell->setPort(ID::B, in2); - cell->setPort(ID::C, in3); + cell->setPort(ID(C), in3); cell->setPort(ID::Y, w1); - cell->setPort(ID::X, w2); + cell->setPort(ID(X), w2); out1 = {out_zeros_msb, w1, out_zeros_lsb}; out2 = {out_zeros_msb, w2, out_zeros_lsb}; @@ -240,15 +240,15 @@ struct MaccmapWorker RTLIL::Cell *c = module->addCell(NEW_ID, ID($alu)); c->setPort(ID::A, summands.front()); c->setPort(ID::B, summands.back()); - c->setPort(ID::CI, State::S0); - c->setPort(ID::BI, State::S0); + c->setPort(ID(CI), State::S0); + c->setPort(ID(BI), State::S0); c->setPort(ID::Y, module->addWire(NEW_ID, width)); - c->setPort(ID::X, module->addWire(NEW_ID, width)); - c->setPort(ID::CO, module->addWire(NEW_ID, width)); + c->setPort(ID(X), module->addWire(NEW_ID, width)); + c->setPort(ID(CO), module->addWire(NEW_ID, width)); c->fixup_parameters(); if (!tree_sum_bits.empty()) { - c->setPort(ID::CI, tree_sum_bits.back()); + c->setPort(ID(CI), tree_sum_bits.back()); tree_sum_bits.pop_back(); } log_assert(tree_sum_bits.empty()); @@ -365,7 +365,7 @@ PRIVATE_NAMESPACE_BEGIN struct MaccmapPass : public Pass { MaccmapPass() : Pass("maccmap", "mapping macc cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -375,7 +375,7 @@ struct MaccmapPass : public Pass { log("is used then the $macc cell is mapped to $add, $sub, etc. cells instead.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool unmap_mode = false; diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 24109b579bd..5541b6122c8 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -116,7 +116,7 @@ struct MuxcoverWorker if (!cell->input(conn.first)) continue; for (auto bit : sigmap(conn.second)) { - if (used_once.count(bit) || cell->type != ID($_MUX_) || conn.first == ID::S) + if (used_once.count(bit) || cell->type != ID($_MUX_) || conn.first == ID(S)) roots.insert(bit); used_once.insert(bit); } @@ -519,7 +519,7 @@ struct MuxcoverWorker Cell *cell = module->addCell(NEW_ID, ID($_MUX_)); cell->setPort(ID::A, mux.inputs[0]); cell->setPort(ID::B, mux.inputs[1]); - cell->setPort(ID::S, mux.selects[0]); + cell->setPort(ID(S), mux.selects[0]); cell->setPort(ID::Y, bit); return; } @@ -529,10 +529,10 @@ struct MuxcoverWorker Cell *cell = module->addCell(NEW_ID, ID($_MUX4_)); cell->setPort(ID::A, mux.inputs[0]); cell->setPort(ID::B, mux.inputs[1]); - cell->setPort(ID::C, mux.inputs[2]); - cell->setPort(ID::D, mux.inputs[3]); - cell->setPort(ID::S, mux.selects[0]); - cell->setPort(ID::T, mux.selects[1]); + cell->setPort(ID(C), mux.inputs[2]); + cell->setPort(ID(D), mux.inputs[3]); + cell->setPort(ID(S), mux.selects[0]); + cell->setPort(ID(T), mux.selects[1]); cell->setPort(ID::Y, bit); return; } @@ -542,15 +542,15 @@ struct MuxcoverWorker Cell *cell = module->addCell(NEW_ID, ID($_MUX8_)); cell->setPort(ID::A, mux.inputs[0]); cell->setPort(ID::B, mux.inputs[1]); - cell->setPort(ID::C, mux.inputs[2]); - cell->setPort(ID::D, mux.inputs[3]); - cell->setPort(ID::E, mux.inputs[4]); - cell->setPort(ID::F, mux.inputs[5]); - cell->setPort(ID::G, mux.inputs[6]); - cell->setPort(ID::H, mux.inputs[7]); - cell->setPort(ID::S, mux.selects[0]); - cell->setPort(ID::T, mux.selects[1]); - cell->setPort(ID::U, mux.selects[2]); + cell->setPort(ID(C), mux.inputs[2]); + cell->setPort(ID(D), mux.inputs[3]); + cell->setPort(ID(E), mux.inputs[4]); + cell->setPort(ID(F), mux.inputs[5]); + cell->setPort(ID(G), mux.inputs[6]); + cell->setPort(ID(H), mux.inputs[7]); + cell->setPort(ID(S), mux.selects[0]); + cell->setPort(ID(T), mux.selects[1]); + cell->setPort(ID(U), mux.selects[2]); cell->setPort(ID::Y, bit); return; } @@ -560,24 +560,24 @@ struct MuxcoverWorker Cell *cell = module->addCell(NEW_ID, ID($_MUX16_)); cell->setPort(ID::A, mux.inputs[0]); cell->setPort(ID::B, mux.inputs[1]); - cell->setPort(ID::C, mux.inputs[2]); - cell->setPort(ID::D, mux.inputs[3]); - cell->setPort(ID::E, mux.inputs[4]); - cell->setPort(ID::F, mux.inputs[5]); - cell->setPort(ID::G, mux.inputs[6]); - cell->setPort(ID::H, mux.inputs[7]); - cell->setPort(ID::I, mux.inputs[8]); - cell->setPort(ID::J, mux.inputs[9]); - cell->setPort(ID::K, mux.inputs[10]); - cell->setPort(ID::L, mux.inputs[11]); - cell->setPort(ID::M, mux.inputs[12]); - cell->setPort(ID::N, mux.inputs[13]); - cell->setPort(ID::O, mux.inputs[14]); - cell->setPort(ID::P, mux.inputs[15]); - cell->setPort(ID::S, mux.selects[0]); - cell->setPort(ID::T, mux.selects[1]); - cell->setPort(ID::U, mux.selects[2]); - cell->setPort(ID::V, mux.selects[3]); + cell->setPort(ID(C), mux.inputs[2]); + cell->setPort(ID(D), mux.inputs[3]); + cell->setPort(ID(E), mux.inputs[4]); + cell->setPort(ID(F), mux.inputs[5]); + cell->setPort(ID(G), mux.inputs[6]); + cell->setPort(ID(H), mux.inputs[7]); + cell->setPort(ID(I), mux.inputs[8]); + cell->setPort(ID(J), mux.inputs[9]); + cell->setPort(ID(K), mux.inputs[10]); + cell->setPort(ID(L), mux.inputs[11]); + cell->setPort(ID(M), mux.inputs[12]); + cell->setPort(ID(N), mux.inputs[13]); + cell->setPort(ID(O), mux.inputs[14]); + cell->setPort(ID(P), mux.inputs[15]); + cell->setPort(ID(S), mux.selects[0]); + cell->setPort(ID(T), mux.selects[1]); + cell->setPort(ID(U), mux.selects[2]); + cell->setPort(ID(V), mux.selects[3]); cell->setPort(ID::Y, bit); return; } @@ -623,7 +623,7 @@ struct MuxcoverWorker struct MuxcoverPass : public Pass { MuxcoverPass() : Pass("muxcover", "cover trees of MUX cells with wider MUXes") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -656,7 +656,7 @@ struct MuxcoverPass : public Pass { log(" than different signals.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing MUXCOVER pass (mapping to wider MUXes).\n"); diff --git a/passes/techmap/nlutmap.cc b/passes/techmap/nlutmap.cc index e1ebfcad8a9..798d8224844 100644 --- a/passes/techmap/nlutmap.cc +++ b/passes/techmap/nlutmap.cc @@ -129,7 +129,7 @@ struct NlutmapWorker struct NlutmapPass : public Pass { NlutmapPass() : Pass("nlutmap", "map to LUTs of different sizes") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -149,7 +149,7 @@ struct NlutmapPass : public Pass { log("to generic logic gates ($_AND_, etc.).\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { NlutmapConfig config; diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc index b937d3fb01c..31ab13cec1f 100644 --- a/passes/techmap/pmuxtree.cc +++ b/passes/techmap/pmuxtree.cc @@ -67,7 +67,7 @@ static SigSpec recursive_mux_generator(Module *module, const SigSpec &sig_data, struct PmuxtreePass : public Pass { PmuxtreePass() : Pass("pmuxtree", "transform $pmux cells to trees of $mux cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -76,7 +76,7 @@ struct PmuxtreePass : public Pass { log("This pass transforms $pmux cells to trees of $mux cells.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing PMUXTREE pass.\n"); @@ -93,7 +93,7 @@ struct PmuxtreePass : public Pass { continue; SigSpec sig_data = cell->getPort(ID::B); - SigSpec sig_sel = cell->getPort(ID::S); + SigSpec sig_sel = cell->getPort(ID(S)); if (!cell->getPort(ID::A).is_fully_undef()) { sig_data.append(cell->getPort(ID::A)); diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 237c261aeca..be00e50305b 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -71,12 +71,12 @@ struct ShregmapTechGreenpak4 : ShregmapTech bool fixup(Cell *cell, dict &taps) { - auto D = cell->getPort(ID::D); - auto C = cell->getPort(ID::C); + auto D = cell->getPort(ID(D)); + auto C = cell->getPort(ID(C)); auto newcell = cell->module->addCell(NEW_ID, ID(GP_SHREG)); newcell->setPort(ID(nRST), State::S1); - newcell->setPort(ID::CLK, C); + newcell->setPort(ID(CLK), C); newcell->setPort(ID(IN), D); int i = 0; @@ -117,9 +117,9 @@ struct ShregmapWorker sigbit_with_non_chain_users.insert(bit); } - if (wire->attributes.count(ID::init)) { + if (wire->attributes.count(ID(init))) { SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) if (initval[i] == State::S0 && !opts.zinit) sigbit_init[initsig[i]] = false; @@ -319,7 +319,7 @@ struct ShregmapWorker initval.push_back(State::S0); remove_init.insert(bit); } - first_cell->setParam(ID::INIT, initval); + first_cell->setParam(ID(INIT), initval); } if (opts.zinit) @@ -348,7 +348,7 @@ struct ShregmapWorker first_cell->type = shreg_cell_type_str; first_cell->setPort(q_port, last_cell->getPort(q_port)); - first_cell->setParam(ID::DEPTH, depth); + first_cell->setParam(ID(DEPTH), depth); if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) remove_cells.insert(first_cell); @@ -366,18 +366,18 @@ struct ShregmapWorker for (auto wire : module->wires()) { - if (wire->attributes.count(ID::init) == 0) + if (wire->attributes.count(ID(init)) == 0) continue; SigSpec initsig = sigmap(wire); - Const &initval = wire->attributes.at(ID::init); + Const &initval = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) if (remove_init.count(initsig[i])) initval[i] = State::Sx; if (SigSpec(initval).is_fully_undef()) - wire->attributes.erase(ID::init); + wire->attributes.erase(ID(init)); } remove_cells.clear(); @@ -403,7 +403,7 @@ struct ShregmapWorker struct ShregmapPass : public Pass { ShregmapPass() : Pass("shregmap", "map shift registers") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -461,7 +461,7 @@ struct ShregmapPass : public Pass { log(" map to greenpak4 shift registers.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { ShregmapOptions opts; string clkpol, enpol; @@ -548,19 +548,19 @@ struct ShregmapPass : public Pass { bool en_neg = enpol == "neg" || enpol == "any" || enpol == "any_or_none"; if (clk_pos && en_none) - opts.ffcells[ID($_DFF_P_)] = make_pair(IdString(ID::D), IdString(ID::Q)); + opts.ffcells[ID($_DFF_P_)] = make_pair(IdString(ID(D)), IdString(ID(Q))); if (clk_neg && en_none) - opts.ffcells[ID($_DFF_N_)] = make_pair(IdString(ID::D), IdString(ID::Q)); + opts.ffcells[ID($_DFF_N_)] = make_pair(IdString(ID(D)), IdString(ID(Q))); if (clk_pos && en_pos) - opts.ffcells[ID($_DFFE_PP_)] = make_pair(IdString(ID::D), IdString(ID::Q)); + opts.ffcells[ID($_DFFE_PP_)] = make_pair(IdString(ID(D)), IdString(ID(Q))); if (clk_pos && en_neg) - opts.ffcells[ID($_DFFE_PN_)] = make_pair(IdString(ID::D), IdString(ID::Q)); + opts.ffcells[ID($_DFFE_PN_)] = make_pair(IdString(ID(D)), IdString(ID(Q))); if (clk_neg && en_pos) - opts.ffcells[ID($_DFFE_NP_)] = make_pair(IdString(ID::D), IdString(ID::Q)); + opts.ffcells[ID($_DFFE_NP_)] = make_pair(IdString(ID(D)), IdString(ID(Q))); if (clk_neg && en_neg) - opts.ffcells[ID($_DFFE_NN_)] = make_pair(IdString(ID::D), IdString(ID::Q)); + opts.ffcells[ID($_DFFE_NN_)] = make_pair(IdString(ID(D)), IdString(ID(Q))); if (en_pos || en_neg) opts.ffe = true; diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index b9d337da455..91574f3c6ae 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -31,11 +31,11 @@ void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_a = cell->getPort(ID::A); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); - sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool()); + sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool()); for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_)); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::Y, sig_y[i]); } @@ -46,7 +46,7 @@ void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_a = cell->getPort(ID::A); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); - sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool()); + sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool()); module->connect(RTLIL::SigSig(sig_y, sig_a)); } @@ -57,8 +57,8 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_b = cell->getPort(ID::B); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); - sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool()); - sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID::B_SIGNED).as_bool()); + sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool()); + sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID(B_SIGNED)).as_bool()); if (cell->type == ID($xnor)) { @@ -66,7 +66,7 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_)); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig_t[i]); gate->setPort(ID::Y, sig_y[i]); } @@ -83,7 +83,7 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::B, sig_b[i]); gate->setPort(ID::Y, sig_y[i]); @@ -134,7 +134,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) } RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::B, sig_a[i+1]); gate->setPort(ID::Y, sig_t[i/2]); @@ -147,7 +147,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) if (cell->type == ID($reduce_xnor)) { RTLIL::SigSpec sig_t = module->addWire(NEW_ID); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_)); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig_a); gate->setPort(ID::Y, sig_t); last_output_cell = gate; @@ -175,7 +175,7 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell } RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_OR_)); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig[i]); gate->setPort(ID::B, sig[i+1]); gate->setPort(ID::Y, sig_t[i/2]); @@ -204,7 +204,7 @@ void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell) } RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_)); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig_a); gate->setPort(ID::Y, sig_y); } @@ -233,7 +233,7 @@ void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell) log_assert(!gate_type.empty()); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig_a); gate->setPort(ID::B, sig_b); gate->setPort(ID::Y, sig_y); @@ -244,24 +244,24 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_a = cell->getPort(ID::A); RTLIL::SigSpec sig_b = cell->getPort(ID::B); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); - bool is_signed = cell->parameters.at(ID::A_SIGNED).as_bool(); + bool is_signed = cell->parameters.at(ID(A_SIGNED)).as_bool(); bool is_ne = cell->type.in(ID($ne), ID($nex)); RTLIL::SigSpec xor_out = module->addWire(NEW_ID, max(GetSize(sig_a), GetSize(sig_b))); RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed); - xor_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + xor_cell->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); simplemap_bitop(module, xor_cell); module->remove(xor_cell); RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID); RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out); - reduce_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + reduce_cell->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); simplemap_reduce(module, reduce_cell); module->remove(reduce_cell); if (!is_ne) { RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y); - not_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + not_cell->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); simplemap_lognot(module, not_cell); module->remove(not_cell); } @@ -275,10 +275,10 @@ void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_)); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::B, sig_b[i]); - gate->setPort(ID::S, cell->getPort(ID::S)); + gate->setPort(ID(S), cell->getPort(ID(S))); gate->setPort(ID::Y, sig_y[i]); } } @@ -286,14 +286,14 @@ void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort(ID::A); - RTLIL::SigSpec sig_e = cell->getPort(ID::EN); + RTLIL::SigSpec sig_e = cell->getPort(ID(EN)); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_TBUF_)); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, sig_a[i]); - gate->setPort(ID::E, sig_e); + gate->setPort(ID(E), sig_e); gate->setPort(ID::Y, sig_y[i]); } } @@ -301,18 +301,18 @@ void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell) { SigSpec lut_ctrl = cell->getPort(ID::A); - SigSpec lut_data = cell->getParam(ID::LUT); - lut_data.extend_u0(1 << cell->getParam(ID::WIDTH).as_int()); + SigSpec lut_data = cell->getParam(ID(LUT)); + lut_data.extend_u0(1 << cell->getParam(ID(WIDTH)).as_int()); for (int idx = 0; GetSize(lut_data) > 1; idx++) { SigSpec sig_s = lut_ctrl[idx]; SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2); for (int i = 0; i < GetSize(lut_data); i += 2) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_)); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); gate->setPort(ID::A, lut_data[i]); gate->setPort(ID::B, lut_data[i+1]); - gate->setPort(ID::S, lut_ctrl[idx]); + gate->setPort(ID(S), lut_ctrl[idx]); gate->setPort(ID::Y, new_lut_data[i/2]); } lut_data = new_lut_data; @@ -324,10 +324,10 @@ void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell) { SigSpec ctrl = cell->getPort(ID::A); - SigSpec table = cell->getParam(ID::TABLE); + SigSpec table = cell->getParam(ID(TABLE)); - int width = cell->getParam(ID::WIDTH).as_int(); - int depth = cell->getParam(ID::DEPTH).as_int(); + int width = cell->getParam(ID(WIDTH)).as_int(); + int depth = cell->getParam(ID(DEPTH)).as_int(); table.extend_u0(2 * width * depth); SigSpec products; @@ -353,7 +353,7 @@ void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell) { - int offset = cell->parameters.at(ID::OFFSET).as_int(); + int offset = cell->parameters.at(ID(OFFSET)).as_int(); RTLIL::SigSpec sig_a = cell->getPort(ID::A); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); module->connect(RTLIL::SigSig(sig_y, sig_a.extract(offset, sig_y.size()))); @@ -369,278 +369,160 @@ void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell) { - int width = cell->parameters.at(ID::WIDTH).as_int(); - char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N'; - char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N'; + int width = cell->parameters.at(ID(WIDTH)).as_int(); + char set_pol = cell->parameters.at(ID(SET_POLARITY)).as_bool() ? 'P' : 'N'; + char clr_pol = cell->parameters.at(ID(CLR_POLARITY)).as_bool() ? 'P' : 'N'; - RTLIL::SigSpec sig_s = cell->getPort(ID::SET); - RTLIL::SigSpec sig_r = cell->getPort(ID::CLR); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); + RTLIL::SigSpec sig_s = cell->getPort(ID(SET)); + RTLIL::SigSpec sig_r = cell->getPort(ID(CLR)); + RTLIL::SigSpec sig_q = cell->getPort(ID(Q)); std::string gate_type = stringf("$_SR_%c%c_", set_pol, clr_pol); for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::S, sig_s[i]); - gate->setPort(ID::R, sig_r[i]); - gate->setPort(ID::Q, sig_q[i]); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); + gate->setPort(ID(S), sig_s[i]); + gate->setPort(ID(R), sig_r[i]); + gate->setPort(ID(Q), sig_q[i]); } } void simplemap_ff(RTLIL::Module *module, RTLIL::Cell *cell) { - int width = cell->parameters.at(ID::WIDTH).as_int(); + int width = cell->parameters.at(ID(WIDTH)).as_int(); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); + RTLIL::SigSpec sig_d = cell->getPort(ID(D)); + RTLIL::SigSpec sig_q = cell->getPort(ID(Q)); IdString gate_type = ID($_FF_); for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); + gate->setPort(ID(D), sig_d[i]); + gate->setPort(ID(Q), sig_q[i]); } } void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell) { - int width = cell->parameters.at(ID::WIDTH).as_int(); - char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N'; + int width = cell->parameters.at(ID(WIDTH)).as_int(); + char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N'; - RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); + RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK)); + RTLIL::SigSpec sig_d = cell->getPort(ID(D)); + RTLIL::SigSpec sig_q = cell->getPort(ID(Q)); IdString gate_type = stringf("$_DFF_%c_", clk_pol); for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::C, sig_clk); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); + gate->setPort(ID(C), sig_clk); + gate->setPort(ID(D), sig_d[i]); + gate->setPort(ID(Q), sig_q[i]); } } void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell) { - int width = cell->parameters.at(ID::WIDTH).as_int(); - char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N'; - char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N'; + int width = cell->parameters.at(ID(WIDTH)).as_int(); + char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N'; + char en_pol = cell->parameters.at(ID(EN_POLARITY)).as_bool() ? 'P' : 'N'; - RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK); - RTLIL::SigSpec sig_en = cell->getPort(ID::EN); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); + RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK)); + RTLIL::SigSpec sig_en = cell->getPort(ID(EN)); + RTLIL::SigSpec sig_d = cell->getPort(ID(D)); + RTLIL::SigSpec sig_q = cell->getPort(ID(Q)); IdString gate_type = stringf("$_DFFE_%c%c_", clk_pol, en_pol); for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::C, sig_clk); - gate->setPort(ID::E, sig_en); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); + gate->setPort(ID(C), sig_clk); + gate->setPort(ID(E), sig_en); + gate->setPort(ID(D), sig_d[i]); + gate->setPort(ID(Q), sig_q[i]); } } void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell) { - int width = cell->parameters.at(ID::WIDTH).as_int(); - char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N'; - char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N'; - char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N'; + int width = cell->parameters.at(ID(WIDTH)).as_int(); + char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N'; + char set_pol = cell->parameters.at(ID(SET_POLARITY)).as_bool() ? 'P' : 'N'; + char clr_pol = cell->parameters.at(ID(CLR_POLARITY)).as_bool() ? 'P' : 'N'; - RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK); - RTLIL::SigSpec sig_s = cell->getPort(ID::SET); - RTLIL::SigSpec sig_r = cell->getPort(ID::CLR); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); + RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK)); + RTLIL::SigSpec sig_s = cell->getPort(ID(SET)); + RTLIL::SigSpec sig_r = cell->getPort(ID(CLR)); + RTLIL::SigSpec sig_d = cell->getPort(ID(D)); + RTLIL::SigSpec sig_q = cell->getPort(ID(Q)); IdString gate_type = stringf("$_DFFSR_%c%c%c_", clk_pol, set_pol, clr_pol); for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::C, sig_clk); - gate->setPort(ID::S, sig_s[i]); - gate->setPort(ID::R, sig_r[i]); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); + gate->setPort(ID(C), sig_clk); + gate->setPort(ID(S), sig_s[i]); + gate->setPort(ID(R), sig_r[i]); + gate->setPort(ID(D), sig_d[i]); + gate->setPort(ID(Q), sig_q[i]); } } -void simplemap_dffsre(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell) { - int width = cell->parameters.at(ID::WIDTH).as_int(); - char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N'; - char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N'; - char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N'; - char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N'; + int width = cell->parameters.at(ID(WIDTH)).as_int(); + char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N'; + char rst_pol = cell->parameters.at(ID(ARST_POLARITY)).as_bool() ? 'P' : 'N'; - RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK); - RTLIL::SigSpec sig_s = cell->getPort(ID::SET); - RTLIL::SigSpec sig_r = cell->getPort(ID::CLR); - RTLIL::SigSpec sig_e = cell->getPort(ID::EN); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); - - IdString gate_type = stringf("$_DFFSRE_%c%c%c%c_", clk_pol, set_pol, clr_pol, en_pol); - - for (int i = 0; i < width; i++) { - RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::C, sig_clk); - gate->setPort(ID::S, sig_s[i]); - gate->setPort(ID::R, sig_r[i]); - gate->setPort(ID::E, sig_e); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); - } -} - -void simplemap_adff_sdff(RTLIL::Module *module, RTLIL::Cell *cell) -{ - int width = cell->parameters.at(ID::WIDTH).as_int(); - bool is_async = cell->type == ID($adff); - char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N'; - char rst_pol = cell->parameters.at(is_async ? ID::ARST_POLARITY : ID::SRST_POLARITY).as_bool() ? 'P' : 'N'; - const char *type = is_async ? "DFF" : "SDFF"; - - std::vector rst_val = cell->parameters.at(is_async ? ID::ARST_VALUE : ID::SRST_VALUE).bits; + std::vector rst_val = cell->parameters.at(ID(ARST_VALUE)).bits; while (int(rst_val.size()) < width) rst_val.push_back(RTLIL::State::S0); - RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK); - RTLIL::SigSpec sig_rst = cell->getPort(is_async ? ID::ARST : ID::SRST); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); + RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK)); + RTLIL::SigSpec sig_rst = cell->getPort(ID(ARST)); + RTLIL::SigSpec sig_d = cell->getPort(ID(D)); + RTLIL::SigSpec sig_q = cell->getPort(ID(Q)); - IdString gate_type_0 = stringf("$_%s_%c%c0_", type, clk_pol, rst_pol); - IdString gate_type_1 = stringf("$_%s_%c%c1_", type, clk_pol, rst_pol); + IdString gate_type_0 = stringf("$_DFF_%c%c0_", clk_pol, rst_pol); + IdString gate_type_1 = stringf("$_DFF_%c%c1_", clk_pol, rst_pol); for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::C, sig_clk); - gate->setPort(ID::R, sig_rst); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); - } -} - -void simplemap_adffe_sdffe_sdffce(RTLIL::Module *module, RTLIL::Cell *cell) -{ - int width = cell->parameters.at(ID::WIDTH).as_int(); - bool is_async = cell->type == ID($adffe); - char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N'; - char rst_pol = cell->parameters.at(is_async ? ID::ARST_POLARITY : ID::SRST_POLARITY).as_bool() ? 'P' : 'N'; - char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N'; - const char *type = is_async ? "DFFE" : cell->type == ID($sdffe) ? "SDFFE" : "SDFFCE"; - - std::vector rst_val = cell->parameters.at(is_async ? ID::ARST_VALUE : ID::SRST_VALUE).bits; - while (int(rst_val.size()) < width) - rst_val.push_back(RTLIL::State::S0); - - RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK); - RTLIL::SigSpec sig_rst = cell->getPort(is_async ? ID::ARST : ID::SRST); - RTLIL::SigSpec sig_e = cell->getPort(ID::EN); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); - - IdString gate_type_0 = stringf("$_%s_%c%c0%c_", type, clk_pol, rst_pol, en_pol); - IdString gate_type_1 = stringf("$_%s_%c%c1%c_", type, clk_pol, rst_pol, en_pol); - - for (int i = 0; i < width; i++) { - RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::C, sig_clk); - gate->setPort(ID::R, sig_rst); - gate->setPort(ID::E, sig_e); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); + gate->setPort(ID(C), sig_clk); + gate->setPort(ID(R), sig_rst); + gate->setPort(ID(D), sig_d[i]); + gate->setPort(ID(Q), sig_q[i]); } } void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell) { - int width = cell->parameters.at(ID::WIDTH).as_int(); - char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N'; + int width = cell->parameters.at(ID(WIDTH)).as_int(); + char en_pol = cell->parameters.at(ID(EN_POLARITY)).as_bool() ? 'P' : 'N'; - RTLIL::SigSpec sig_en = cell->getPort(ID::EN); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); + RTLIL::SigSpec sig_en = cell->getPort(ID(EN)); + RTLIL::SigSpec sig_d = cell->getPort(ID(D)); + RTLIL::SigSpec sig_q = cell->getPort(ID(Q)); IdString gate_type = stringf("$_DLATCH_%c_", en_pol); for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::E, sig_en); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); - } -} - -void simplemap_adlatch(RTLIL::Module *module, RTLIL::Cell *cell) -{ - int width = cell->parameters.at(ID::WIDTH).as_int(); - char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N'; - char rst_pol = cell->parameters.at(ID::ARST_POLARITY).as_bool() ? 'P' : 'N'; - - std::vector rst_val = cell->parameters.at(ID::ARST_VALUE).bits; - while (int(rst_val.size()) < width) - rst_val.push_back(RTLIL::State::S0); - - RTLIL::SigSpec sig_en = cell->getPort(ID::EN); - RTLIL::SigSpec sig_rst = cell->getPort(ID::ARST); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); - - IdString gate_type_0 = stringf("$_DLATCH_%c%c0_", en_pol, rst_pol); - IdString gate_type_1 = stringf("$_DLATCH_%c%c1_", en_pol, rst_pol); - - for (int i = 0; i < width; i++) { - RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::E, sig_en); - gate->setPort(ID::R, sig_rst); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); - } -} - -void simplemap_dlatchsr(RTLIL::Module *module, RTLIL::Cell *cell) -{ - int width = cell->parameters.at(ID::WIDTH).as_int(); - char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N'; - char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N'; - char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N'; - - RTLIL::SigSpec sig_en = cell->getPort(ID::EN); - RTLIL::SigSpec sig_s = cell->getPort(ID::SET); - RTLIL::SigSpec sig_r = cell->getPort(ID::CLR); - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); - - IdString gate_type = stringf("$_DLATCHSR_%c%c%c_", en_pol, set_pol, clr_pol); - - for (int i = 0; i < width; i++) { - RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); - gate->setPort(ID::E, sig_en); - gate->setPort(ID::S, sig_s[i]); - gate->setPort(ID::R, sig_r[i]); - gate->setPort(ID::D, sig_d[i]); - gate->setPort(ID::Q, sig_q[i]); + gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src))); + gate->setPort(ID(E), sig_en); + gate->setPort(ID(D), sig_d[i]); + gate->setPort(ID(Q), sig_q[i]); } } -void simplemap_get_mappers(dict &mappers) +void simplemap_get_mappers(std::map &mappers) { mappers[ID($not)] = simplemap_not; mappers[ID($pos)] = simplemap_pos; @@ -671,20 +553,13 @@ void simplemap_get_mappers(dict mappers[ID($dff)] = simplemap_dff; mappers[ID($dffe)] = simplemap_dffe; mappers[ID($dffsr)] = simplemap_dffsr; - mappers[ID($dffsre)] = simplemap_dffsre; - mappers[ID($adff)] = simplemap_adff_sdff; - mappers[ID($sdff)] = simplemap_adff_sdff; - mappers[ID($adffe)] = simplemap_adffe_sdffe_sdffce; - mappers[ID($sdffe)] = simplemap_adffe_sdffe_sdffce; - mappers[ID($sdffce)] = simplemap_adffe_sdffe_sdffce; + mappers[ID($adff)] = simplemap_adff; mappers[ID($dlatch)] = simplemap_dlatch; - mappers[ID($adlatch)] = simplemap_adlatch; - mappers[ID($dlatchsr)] = simplemap_dlatchsr; } void simplemap(RTLIL::Module *module, RTLIL::Cell *cell) { - static dict mappers; + static std::map mappers; static bool initialized_mappers = false; if (!initialized_mappers) { @@ -700,7 +575,7 @@ PRIVATE_NAMESPACE_BEGIN struct SimplemapPass : public Pass { SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -712,15 +587,15 @@ struct SimplemapPass : public Pass { log(" $not, $pos, $and, $or, $xor, $xnor\n"); log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n"); log(" $logic_not, $logic_and, $logic_or, $mux, $tribuf\n"); - log(" $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $sdff, $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\n"); + log(" $sr, $ff, $dff, $dffsr, $adff, $dlatch\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing SIMPLEMAP pass (map simple cells to gate primitives).\n"); extra_args(args, 1, design); - dict mappers; + std::map mappers; simplemap_get_mappers(mappers); for (auto mod : design->modules()) { diff --git a/passes/techmap/simplemap.h b/passes/techmap/simplemap.h index 5091050a11d..c2d73ea7911 100644 --- a/passes/techmap/simplemap.h +++ b/passes/techmap/simplemap.h @@ -42,7 +42,7 @@ extern void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell); extern void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell); extern void simplemap(RTLIL::Module *module, RTLIL::Cell *cell); -extern void simplemap_get_mappers(dict &mappers); +extern void simplemap_get_mappers(std::map &mappers); YOSYS_NAMESPACE_END diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index f98d1564ac1..0c57733d41f 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -27,6 +27,7 @@ #include #include "simplemap.h" +#include "passes/techmap/techmap.inc" YOSYS_NAMESPACE_BEGIN @@ -50,23 +51,27 @@ void apply_prefix(IdString prefix, RTLIL::SigSpec &sig, RTLIL::Module *module) { vector chunks = sig; for (auto &chunk : chunks) - if (chunk.wire != nullptr) { + if (chunk.wire != NULL) { IdString wire_name = chunk.wire->name; apply_prefix(prefix, wire_name); - log_assert(module->wire(wire_name) != nullptr); - chunk.wire = module->wire(wire_name); + log_assert(module->wires_.count(wire_name) > 0); + chunk.wire = module->wires_[wire_name]; } sig = chunks; } struct TechmapWorker { - dict simplemap_mappers; - dict>, RTLIL::Module*> techmap_cache; - dict techmap_do_cache; - pool module_queue; + std::map simplemap_mappers; + std::map>, RTLIL::Module*> techmap_cache; + std::map techmap_do_cache; + std::set> module_queue; dict sigmaps; + pool flatten_do_list; + pool flatten_done_list; + pool flatten_keep_list; + pool log_msg_cache; struct TechmapWireData { @@ -74,20 +79,31 @@ struct TechmapWorker RTLIL::SigSpec value; }; - typedef dict> TechmapWires; + typedef std::map> TechmapWires; - bool extern_mode = false; - bool assert_mode = false; - bool recursive_mode = false; - bool autoproc_mode = false; - bool ignore_wb = false; + bool extern_mode; + bool assert_mode; + bool flatten_mode; + bool recursive_mode; + bool autoproc_mode; + bool ignore_wb; + + TechmapWorker() + { + extern_mode = false; + assert_mode = false; + flatten_mode = false; + recursive_mode = false; + autoproc_mode = false; + ignore_wb = false; + } std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose) { std::string constmap_info; - dict> connbits_map; + std::map> connbits_map; - for (auto &conn : cell->connections()) + for (auto conn : cell->connections()) for (int i = 0; i < GetSize(conn.second); i++) { RTLIL::SigBit bit = sigmap(conn.second[i]); if (bit.wire == nullptr) { @@ -101,7 +117,7 @@ struct TechmapWorker constmap_info += stringf("|%s %d %s %d", log_id(conn.first), i, log_id(connbits_map.at(bit).first), connbits_map.at(bit).second); } else { - connbits_map.emplace(bit, std::make_pair(conn.first, i)); + connbits_map[bit] = std::pair(conn.first, i); constmap_info += stringf("|%s %d", log_id(conn.first), i); } } @@ -113,25 +129,24 @@ struct TechmapWorker { TechmapWires result; - if (module == nullptr) + if (module == NULL) return result; - for (auto w : module->wires()) { - const char *p = w->name.c_str(); + for (auto &it : module->wires_) { + const char *p = it.first.c_str(); if (*p == '$') continue; const char *q = strrchr(p+1, '.'); - if (q) - p = q; + p = q ? q+1 : p+1; - if (!strncmp(p, "\\_TECHMAP_", 10)) { + if (!strncmp(p, "_TECHMAP_", 9)) { TechmapWireData record; - record.wire = w; - record.value = w; + record.wire = it.second; + record.value = it.second; result[p].push_back(record); - w->set_bool_attribute(ID::keep); - w->set_bool_attribute(ID::_techmap_special_); + it.second->attributes[ID::keep] = RTLIL::Const(1); + it.second->attributes[ID(_techmap_special_)] = RTLIL::Const(1); } } @@ -150,7 +165,7 @@ struct TechmapWorker if (tpl->processes.size() != 0) { log("Technology map yielded processes:"); for (auto &it : tpl->processes) - log(" %s",log_id(it.first)); + log(" %s",RTLIL::id2cstr(it.first)); log("\n"); if (autoproc_mode) { Pass::call_on_module(tpl->design, tpl, "proc"); @@ -160,74 +175,92 @@ struct TechmapWorker } std::string orig_cell_name; - pool extra_src_attrs = cell->get_strpool_attribute(ID::src); + pool extra_src_attrs = cell->get_strpool_attribute(ID(src)); - orig_cell_name = cell->name.str(); - for (auto tpl_cell : tpl->cells()) - if (tpl_cell->name == ID::_TECHMAP_REPLACE_) { - module->rename(cell, stringf("$techmap%d", autoidx++) + cell->name.str()); - break; - } + if (!flatten_mode) { + for (auto &it : tpl->cells_) + if (it.first == ID(_TECHMAP_REPLACE_)) { + orig_cell_name = cell->name.str(); + module->rename(cell, stringf("$techmap%d", autoidx++) + cell->name.str()); + break; + } + } dict memory_renames; for (auto &it : tpl->memories) { IdString m_name = it.first; apply_prefix(cell->name, m_name); - RTLIL::Memory *m = module->addMemory(m_name, it.second); - if (m->attributes.count(ID::src)) - m->add_strpool_attribute(ID::src, extra_src_attrs); + RTLIL::Memory *m = new RTLIL::Memory; + m->name = m_name; + m->width = it.second->width; + m->start_offset = it.second->start_offset; + m->size = it.second->size; + m->attributes = it.second->attributes; + if (m->attributes.count(ID(src))) + m->add_strpool_attribute(ID(src), extra_src_attrs); + module->memories[m->name] = m; memory_renames[it.first] = m->name; design->select(module, m); } - dict positional_ports; + std::map positional_ports; dict temp_renamed_wires; pool autopurge_tpl_bits; - for (auto tpl_w : tpl->wires()) + for (auto &it : tpl->wires_) { - if (tpl_w->port_id > 0) + if (it.second->port_id > 0) { - IdString posportname = stringf("$%d", tpl_w->port_id); - positional_ports.emplace(posportname, tpl_w->name); + IdString posportname = stringf("$%d", it.second->port_id); + positional_ports[posportname] = it.first; - if (tpl_w->get_bool_attribute(ID::techmap_autopurge) && - (!cell->hasPort(tpl_w->name) || !GetSize(cell->getPort(tpl_w->name))) && + if (!flatten_mode && it.second->get_bool_attribute(ID(techmap_autopurge)) && + (!cell->hasPort(it.second->name) || !GetSize(cell->getPort(it.second->name))) && (!cell->hasPort(posportname) || !GetSize(cell->getPort(posportname)))) { if (sigmaps.count(tpl) == 0) sigmaps[tpl].set(tpl); - for (auto bit : sigmaps.at(tpl)(tpl_w)) + for (auto bit : sigmaps.at(tpl)(it.second)) if (bit.wire != nullptr) autopurge_tpl_bits.insert(bit); } } - IdString w_name = tpl_w->name; + IdString w_name = it.second->name; apply_prefix(cell->name, w_name); RTLIL::Wire *w = module->wire(w_name); if (w != nullptr) { - temp_renamed_wires[w] = w->name; - module->rename(w, NEW_ID); - w = nullptr; + if (!flatten_mode || !w->get_bool_attribute(ID(hierconn))) { + temp_renamed_wires[w] = w->name; + module->rename(w, NEW_ID); + w = nullptr; + } else { + w->attributes.erase(ID(hierconn)); + if (GetSize(w) < GetSize(it.second)) { + log_warning("Widening signal %s.%s to match size of %s.%s (via %s.%s).\n", log_id(module), log_id(w), + log_id(tpl), log_id(it.second), log_id(module), log_id(cell)); + w->width = GetSize(it.second); + } + } } if (w == nullptr) { - w = module->addWire(w_name, tpl_w); + w = module->addWire(w_name, it.second); w->port_input = false; w->port_output = false; w->port_id = 0; - w->attributes.erase(ID::techmap_autopurge); - if (tpl_w->get_bool_attribute(ID::_techmap_special_)) + if (!flatten_mode) + w->attributes.erase(ID(techmap_autopurge)); + if (it.second->get_bool_attribute(ID(_techmap_special_))) w->attributes.clear(); - if (w->attributes.count(ID::src)) - w->add_strpool_attribute(ID::src, extra_src_attrs); + if (w->attributes.count(ID(src))) + w->add_strpool_attribute(ID(src), extra_src_attrs); } design->select(module, w); - if (tpl_w->name.begins_with("\\_TECHMAP_REPLACE_.")) { - IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), tpl_w->name.c_str() + strlen("\\_TECHMAP_REPLACE_")); - Wire *replace_w = module->addWire(replace_name, tpl_w); + if (it.second->name.begins_with("\\_TECHMAP_REPLACE_.")) { + IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), it.second->name.c_str() + strlen("\\_TECHMAP_REPLACE_")); + Wire *replace_w = module->addWire(replace_name, it.second); module->connect(replace_w, w); } } @@ -235,23 +268,24 @@ struct TechmapWorker SigMap tpl_sigmap(tpl); pool tpl_written_bits; - for (auto tpl_cell : tpl->cells()) - for (auto &conn : tpl_cell->connections()) - if (tpl_cell->output(conn.first)) - for (auto bit : tpl_sigmap(conn.second)) + for (auto &it1 : tpl->cells_) + for (auto &it2 : it1.second->connections_) + if (it1.second->output(it2.first)) + for (auto bit : tpl_sigmap(it2.second)) tpl_written_bits.insert(bit); - for (auto &conn : tpl->connections()) - for (auto bit : tpl_sigmap(conn.first)) + for (auto &it1 : tpl->connections_) + for (auto bit : tpl_sigmap(it1.first)) tpl_written_bits.insert(bit); SigMap port_signal_map; + SigSig port_signal_assign; for (auto &it : cell->connections()) { - IdString portname = it.first; + RTLIL::IdString portname = it.first; if (positional_ports.count(portname) > 0) portname = positional_ports.at(portname); - if (tpl->wire(portname) == nullptr || tpl->wire(portname)->port_id == 0) { + if (tpl->wires_.count(portname) == 0 || tpl->wires_.at(portname)->port_id == 0) { if (portname.begins_with("$")) log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", portname.c_str(), cell->name.c_str(), tpl->name.c_str()); continue; @@ -260,7 +294,7 @@ struct TechmapWorker if (GetSize(it.second) == 0) continue; - RTLIL::Wire *w = tpl->wire(portname); + RTLIL::Wire *w = tpl->wires_.at(portname); RTLIL::SigSig c, extra_connect; if (w->port_output && !w->port_input) { @@ -299,58 +333,76 @@ struct TechmapWorker log_assert(c.first.size() == c.second.size()); - // replace internal wires that are connected to external wires + if (flatten_mode) + { + // more conservative approach: + // connect internal and external wires + + if (sigmaps.count(module) == 0) + sigmaps[module].set(module); + + if (sigmaps.at(module)(c.first).has_const()) + log_error("Mismatch in directionality for cell port %s.%s.%s: %s <= %s\n", + log_id(module), log_id(cell), log_id(it.first), log_signal(c.first), log_signal(c.second)); - if (w->port_output && !w->port_input) { - port_signal_map.add(c.second, c.first); - } else - if (!w->port_output && w->port_input) { - port_signal_map.add(c.first, c.second); - } else { module->connect(c); - extra_connect = SigSig(); } + else + { + // approach that yields nicer outputs: + // replace internal wires that are connected to external wires + + if (w->port_output && !w->port_input) { + port_signal_map.add(c.second, c.first); + } else + if (!w->port_output && w->port_input) { + port_signal_map.add(c.first, c.second); + } else { + module->connect(c); + extra_connect = SigSig(); + } - for (auto &attr : w->attributes) { - if (attr.first == ID::src) - continue; - auto lhs = GetSize(extra_connect.first); - auto rhs = GetSize(extra_connect.second); - if (lhs > rhs) - extra_connect.first.remove(rhs, lhs-rhs); - else if (rhs > lhs) - extra_connect.second.remove(lhs, rhs-lhs); - module->connect(extra_connect); - break; + for (auto &attr : w->attributes) { + if (attr.first == ID(src)) + continue; + auto lhs = GetSize(extra_connect.first); + auto rhs = GetSize(extra_connect.second); + if (lhs > rhs) + extra_connect.first.remove(rhs, lhs-rhs); + else if (rhs > lhs) + extra_connect.second.remove(lhs, rhs-lhs); + module->connect(extra_connect); + break; + } } } - for (auto tpl_cell : tpl->cells()) + for (auto &it : tpl->cells_) { - IdString c_name = tpl_cell->name; - bool techmap_replace_cell = (c_name == ID::_TECHMAP_REPLACE_); + IdString c_name = it.second->name.str(); + bool techmap_replace_cell = (!flatten_mode) && (c_name == ID(_TECHMAP_REPLACE_)); if (techmap_replace_cell) c_name = orig_cell_name; - else if (tpl_cell->name.begins_with("\\_TECHMAP_REPLACE_.")) + else if (it.second->name.begins_with("\\_TECHMAP_REPLACE_.")) c_name = stringf("%s%s", orig_cell_name.c_str(), c_name.c_str() + strlen("\\_TECHMAP_REPLACE_")); else apply_prefix(cell->name, c_name); - RTLIL::Cell *c = module->addCell(c_name, tpl_cell); + RTLIL::Cell *c = module->addCell(c_name, it.second); design->select(module, c); - if (c->type.begins_with("\\$")) + if (!flatten_mode && c->type.begins_with("\\$")) c->type = c->type.substr(1); vector autopurge_ports; - for (auto &conn : c->connections()) + for (auto &it2 : c->connections_) { bool autopurge = false; if (!autopurge_tpl_bits.empty()) { - autopurge = GetSize(conn.second) != 0; - for (auto &bit : sigmaps.at(tpl)(conn.second)) + autopurge = GetSize(it2.second) != 0; + for (auto &bit : sigmaps.at(tpl)(it2.second)) if (!autopurge_tpl_bits.count(bit)) { autopurge = false; break; @@ -358,12 +410,10 @@ struct TechmapWorker } if (autopurge) { - autopurge_ports.push_back(conn.first); + autopurge_ports.push_back(it2.first); } else { - RTLIL::SigSpec new_conn = conn.second; - apply_prefix(cell->name, new_conn, module); - port_signal_map.apply(new_conn); - c->setPort(conn.first, std::move(new_conn)); + apply_prefix(cell->name, it2.second, module); + port_signal_map.apply(it2.second); } } @@ -371,19 +421,19 @@ struct TechmapWorker c->unsetPort(it2); if (c->type.in(ID($memrd), ID($memwr), ID($meminit))) { - IdString memid = c->getParam(ID::MEMID).decode_string(); + IdString memid = c->getParam(ID(MEMID)).decode_string(); log_assert(memory_renames.count(memid) != 0); - c->setParam(ID::MEMID, Const(memory_renames[memid].str())); + c->setParam(ID(MEMID), Const(memory_renames[memid].str())); } if (c->type == ID($mem)) { - IdString memid = c->getParam(ID::MEMID).decode_string(); + IdString memid = c->getParam(ID(MEMID)).decode_string(); apply_prefix(cell->name, memid); - c->setParam(ID::MEMID, Const(memid.c_str())); + c->setParam(ID(MEMID), Const(memid.c_str())); } - if (c->attributes.count(ID::src)) - c->add_strpool_attribute(ID::src, extra_src_attrs); + if (c->attributes.count(ID(src))) + c->add_strpool_attribute(ID(src), extra_src_attrs); if (techmap_replace_cell) for (auto attr : cell->attributes) @@ -413,8 +463,8 @@ struct TechmapWorker } } - bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, pool &handled_cells, - const dict> &celltypeMap, bool in_recursion) + bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, std::set &handled_cells, + const std::map> &celltypeMap, bool in_recursion) { std::string mapmsg_prefix = in_recursion ? "Recursively mapping" : "Mapping"; @@ -431,21 +481,21 @@ struct TechmapWorker pool remove_init_bits; for (auto wire : module->wires()) { - if (wire->attributes.count(ID::init)) { - Const value = wire->attributes.at(ID::init); + if (wire->attributes.count("\\init")) { + Const value = wire->attributes.at("\\init"); for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) if (value[i] != State::Sx) init_bits[sigmap(SigBit(wire, i))] = value[i]; } } - TopoSort> cells; - dict> cell_to_inbit; - dict> outbit_to_cell; + TopoSort> cells; + std::map> cell_to_inbit; + std::map> outbit_to_cell; - for (auto cell : module->selected_cells()) + for (auto cell : module->cells()) { - if (handled_cells.count(cell) > 0) + if (!design->selected(module, cell) || handled_cells.count(cell) > 0) continue; std::string cell_type = cell->type.str(); @@ -458,6 +508,22 @@ struct TechmapWorker continue; } + if (flatten_mode) { + bool keepit = cell->get_bool_attribute(ID(keep_hierarchy)); + for (auto &tpl_name : celltypeMap.at(cell_type)) + if (map->modules_[tpl_name]->get_bool_attribute(ID(keep_hierarchy))) + keepit = true; + if (keepit) { + if (!flatten_keep_list[cell]) { + log("Keeping %s.%s (found keep_hierarchy property).\n", log_id(module), log_id(cell)); + flatten_keep_list.insert(cell); + } + if (!flatten_done_list[cell->type]) + flatten_do_list.insert(cell->type); + continue; + } + } + for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = sigmap(conn.second); @@ -467,7 +533,7 @@ struct TechmapWorker continue; for (auto &tpl_name : celltypeMap.at(cell_type)) { - RTLIL::Module *tpl = map->module(tpl_name); + RTLIL::Module *tpl = map->modules_[tpl_name]; RTLIL::Wire *port = tpl->wire(conn.first); if (port && port->port_input) cell_to_inbit[cell].insert(sig.begin(), sig.end()); @@ -500,188 +566,189 @@ struct TechmapWorker for (auto &tpl_name : celltypeMap.at(cell_type)) { - IdString derived_name = tpl_name; - RTLIL::Module *tpl = map->module(tpl_name); - dict parameters(cell->parameters); + RTLIL::IdString derived_name = tpl_name; + RTLIL::Module *tpl = map->modules_[tpl_name]; + std::map parameters(cell->parameters.begin(), cell->parameters.end()); if (tpl->get_blackbox_attribute(ignore_wb)) continue; - std::string extmapper_name; - - if (tpl->get_bool_attribute(ID::techmap_simplemap)) - extmapper_name = "simplemap"; + if (!flatten_mode) + { + std::string extmapper_name; - if (tpl->get_bool_attribute(ID::techmap_maccmap)) - extmapper_name = "maccmap"; + if (tpl->get_bool_attribute(ID(techmap_simplemap))) + extmapper_name = "simplemap"; - if (tpl->attributes.count(ID::techmap_wrap)) - extmapper_name = "wrap"; + if (tpl->get_bool_attribute(ID(techmap_maccmap))) + extmapper_name = "maccmap"; - if (!extmapper_name.empty()) - { - cell->type = cell_type; + if (tpl->attributes.count(ID(techmap_wrap))) + extmapper_name = "wrap"; - if ((extern_mode && !in_recursion) || extmapper_name == "wrap") + if (!extmapper_name.empty()) { - std::string m_name = stringf("$extern:%s:%s", extmapper_name.c_str(), log_id(cell->type)); + cell->type = cell_type; - for (auto &c : cell->parameters) - m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second)); + if ((extern_mode && !in_recursion) || extmapper_name == "wrap") + { + std::string m_name = stringf("$extern:%s:%s", extmapper_name.c_str(), log_id(cell->type)); - if (extmapper_name == "wrap") - m_name += ":" + sha1(tpl->attributes.at(ID::techmap_wrap).decode_string()); + for (auto &c : cell->parameters) + m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second)); - RTLIL::Design *extmapper_design = extern_mode && !in_recursion ? design : tpl->design; - RTLIL::Module *extmapper_module = extmapper_design->module(m_name); + if (extmapper_name == "wrap") + m_name += ":" + sha1(tpl->attributes.at(ID(techmap_wrap)).decode_string()); - if (extmapper_module == nullptr) - { - extmapper_module = extmapper_design->addModule(m_name); - RTLIL::Cell *extmapper_cell = extmapper_module->addCell(cell->type, cell); - - extmapper_cell->set_src_attribute(cell->get_src_attribute()); - - int port_counter = 1; - for (auto &c : extmapper_cell->connections_) { - RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second)); - if (w->name.in(ID::Y, ID::Q)) - w->port_output = true; - else - w->port_input = true; - w->port_id = port_counter++; - c.second = w; - } + RTLIL::Design *extmapper_design = extern_mode && !in_recursion ? design : tpl->design; + RTLIL::Module *extmapper_module = extmapper_design->module(m_name); - extmapper_module->fixup_ports(); - extmapper_module->check(); + if (extmapper_module == nullptr) + { + extmapper_module = extmapper_design->addModule(m_name); + RTLIL::Cell *extmapper_cell = extmapper_module->addCell(cell->type, cell); + + extmapper_cell->set_src_attribute(cell->get_src_attribute()); + + int port_counter = 1; + for (auto &c : extmapper_cell->connections_) { + RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second)); + if (w->name.in(ID::Y, ID(Q))) + w->port_output = true; + else + w->port_input = true; + w->port_id = port_counter++; + c.second = w; + } - if (extmapper_name == "simplemap") { - log("Creating %s with simplemap.\n", log_id(extmapper_module)); - if (simplemap_mappers.count(extmapper_cell->type) == 0) - log_error("No simplemap mapper for cell type %s found!\n", log_id(extmapper_cell->type)); - simplemap_mappers.at(extmapper_cell->type)(extmapper_module, extmapper_cell); - extmapper_module->remove(extmapper_cell); - } + extmapper_module->fixup_ports(); + extmapper_module->check(); - if (extmapper_name == "maccmap") { - log("Creating %s with maccmap.\n", log_id(extmapper_module)); - if (extmapper_cell->type != ID($macc)) - log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(extmapper_cell->type)); - maccmap(extmapper_module, extmapper_cell); - extmapper_module->remove(extmapper_cell); - } + if (extmapper_name == "simplemap") { + log("Creating %s with simplemap.\n", log_id(extmapper_module)); + if (simplemap_mappers.count(extmapper_cell->type) == 0) + log_error("No simplemap mapper for cell type %s found!\n", log_id(extmapper_cell->type)); + simplemap_mappers.at(extmapper_cell->type)(extmapper_module, extmapper_cell); + extmapper_module->remove(extmapper_cell); + } - if (extmapper_name == "wrap") { - std::string cmd_string = tpl->attributes.at(ID::techmap_wrap).decode_string(); - log("Running \"%s\" on wrapper %s.\n", cmd_string.c_str(), log_id(extmapper_module)); - mkdebug.on(); - Pass::call_on_module(extmapper_design, extmapper_module, cmd_string); - log_continue = true; + if (extmapper_name == "maccmap") { + log("Creating %s with maccmap.\n", log_id(extmapper_module)); + if (extmapper_cell->type != ID($macc)) + log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(extmapper_cell->type)); + maccmap(extmapper_module, extmapper_cell); + extmapper_module->remove(extmapper_cell); + } + + if (extmapper_name == "wrap") { + std::string cmd_string = tpl->attributes.at(ID(techmap_wrap)).decode_string(); + log("Running \"%s\" on wrapper %s.\n", cmd_string.c_str(), log_id(extmapper_module)); + mkdebug.on(); + Pass::call_on_module(extmapper_design, extmapper_module, cmd_string); + log_continue = true; + } } - } - cell->type = extmapper_module->name; - cell->parameters.clear(); + cell->type = extmapper_module->name; + cell->parameters.clear(); - if (!extern_mode || in_recursion) { - tpl = extmapper_module; - goto use_wrapper_tpl; - } + if (!extern_mode || in_recursion) { + tpl = extmapper_module; + goto use_wrapper_tpl; + } - auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type)); - if (!log_msg_cache.count(msg)) { - log_msg_cache.insert(msg); - log("%s\n", msg.c_str()); - } - log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module)); - } - else - { - auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name.c_str(), log_id(cell->type)); - if (!log_msg_cache.count(msg)) { - log_msg_cache.insert(msg); - log("%s\n", msg.c_str()); + auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type)); + if (!log_msg_cache.count(msg)) { + log_msg_cache.insert(msg); + log("%s\n", msg.c_str()); + } + log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module)); } - log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str()); + else + { + auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name.c_str(), log_id(cell->type)); + if (!log_msg_cache.count(msg)) { + log_msg_cache.insert(msg); + log("%s\n", msg.c_str()); + } + log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str()); - if (extmapper_name == "simplemap") { - if (simplemap_mappers.count(cell->type) == 0) - log_error("No simplemap mapper for cell type %s found!\n", log_id(cell->type)); - simplemap_mappers.at(cell->type)(module, cell); - } + if (extmapper_name == "simplemap") { + if (simplemap_mappers.count(cell->type) == 0) + log_error("No simplemap mapper for cell type %s found!\n", RTLIL::id2cstr(cell->type)); + simplemap_mappers.at(cell->type)(module, cell); + } + + if (extmapper_name == "maccmap") { + if (cell->type != ID($macc)) + log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(cell->type)); + maccmap(module, cell); + } - if (extmapper_name == "maccmap") { - if (cell->type != ID($macc)) - log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(cell->type)); - maccmap(module, cell); + module->remove(cell); + cell = NULL; } - module->remove(cell); - cell = nullptr; + did_something = true; + mapped_cell = true; + break; } - did_something = true; - mapped_cell = true; - break; - } + for (auto conn : cell->connections()) { + if (conn.first.begins_with("$")) + continue; + if (tpl->wires_.count(conn.first) > 0 && tpl->wires_.at(conn.first)->port_id > 0) + continue; + if (!conn.second.is_fully_const() || parameters.count(conn.first) > 0 || tpl->avail_parameters.count(conn.first) == 0) + goto next_tpl; + parameters[conn.first] = conn.second.as_const(); + } - for (auto &conn : cell->connections()) { - if (conn.first.begins_with("$")) + if (0) { + next_tpl: continue; - if (tpl->wire(conn.first) != nullptr && tpl->wire(conn.first)->port_id > 0) - continue; - if (!conn.second.is_fully_const() || parameters.count(conn.first) > 0 || tpl->avail_parameters.count(conn.first) == 0) - goto next_tpl; - parameters[conn.first] = conn.second.as_const(); - } - - if (0) { - next_tpl: - continue; - } + } - if (tpl->avail_parameters.count(ID::_TECHMAP_CELLTYPE_) != 0) - parameters.emplace(ID::_TECHMAP_CELLTYPE_, RTLIL::unescape_id(cell->type)); + if (tpl->avail_parameters.count(ID(_TECHMAP_CELLTYPE_)) != 0) + parameters[ID(_TECHMAP_CELLTYPE_)] = RTLIL::unescape_id(cell->type); - for (auto &conn : cell->connections()) { - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first))) != 0) { - std::vector v = sigmap(conn.second).to_sigbit_vector(); - for (auto &bit : v) - bit = RTLIL::SigBit(bit.wire == nullptr ? RTLIL::State::S1 : RTLIL::State::S0); - parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const()); - } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first))) != 0) { - std::vector v = sigmap(conn.second).to_sigbit_vector(); - for (auto &bit : v) - if (bit.wire != nullptr) - bit = RTLIL::SigBit(RTLIL::State::Sx); - parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const()); - } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first))) != 0) { - auto sig = sigmap(conn.second); - RTLIL::Const value(State::Sx, sig.size()); - for (int i = 0; i < sig.size(); i++) { - auto it = init_bits.find(sig[i]); - if (it != init_bits.end()) { - value[i] = it->second; + for (auto conn : cell->connections()) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", RTLIL::id2cstr(conn.first))) != 0) { + std::vector v = sigmap(conn.second).to_sigbit_vector(); + for (auto &bit : v) + bit = RTLIL::SigBit(bit.wire == NULL ? RTLIL::State::S1 : RTLIL::State::S0); + parameters[stringf("\\_TECHMAP_CONSTMSK_%s_", RTLIL::id2cstr(conn.first))] = RTLIL::SigSpec(v).as_const(); + } + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", RTLIL::id2cstr(conn.first))) != 0) { + std::vector v = sigmap(conn.second).to_sigbit_vector(); + for (auto &bit : v) + if (bit.wire != NULL) + bit = RTLIL::SigBit(RTLIL::State::Sx); + parameters[stringf("\\_TECHMAP_CONSTVAL_%s_", RTLIL::id2cstr(conn.first))] = RTLIL::SigSpec(v).as_const(); + } + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", RTLIL::id2cstr(conn.first))) != 0) { + auto sig = sigmap(conn.second); + RTLIL::Const value(State::Sx, sig.size()); + for (int i = 0; i < sig.size(); i++) { + auto it = init_bits.find(sig[i]); + if (it != init_bits.end()) { + value[i] = it->second; + } } + parameters[stringf("\\_TECHMAP_WIREINIT_%s_", RTLIL::id2cstr(conn.first))] = value; } - parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), value); } - } - { int unique_bit_id_counter = 0; - dict unique_bit_id; + std::map unique_bit_id; unique_bit_id[RTLIL::State::S0] = unique_bit_id_counter++; unique_bit_id[RTLIL::State::S1] = unique_bit_id_counter++; unique_bit_id[RTLIL::State::Sx] = unique_bit_id_counter++; unique_bit_id[RTLIL::State::Sz] = unique_bit_id_counter++; - for (auto &conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { - for (auto &bit : sigmap(conn.second)) + for (auto conn : cell->connections()) + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))) != 0) { + for (auto &bit : sigmap(conn.second).to_sigbit_vector()) if (unique_bit_id.count(bit) == 0) unique_bit_id[bit] = unique_bit_id_counter++; } @@ -693,20 +760,17 @@ struct TechmapWorker bits = i; // Increment index by one to get number of bits bits++; - if (tpl->avail_parameters.count(ID::_TECHMAP_BITS_CONNMAP_)) - parameters[ID::_TECHMAP_BITS_CONNMAP_] = bits; + if (tpl->avail_parameters.count(ID(_TECHMAP_BITS_CONNMAP_))) + parameters[ID(_TECHMAP_BITS_CONNMAP_)] = bits; - for (auto &conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { + for (auto conn : cell->connections()) + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))) != 0) { RTLIL::Const value; - for (auto &bit : sigmap(conn.second)) { - int val = unique_bit_id.at(bit); - for (int i = 0; i < bits; i++) { - value.bits.push_back((val & 1) != 0 ? State::S1 : State::S0); - val = val >> 1; - } + for (auto &bit : sigmap(conn.second).to_sigbit_vector()) { + RTLIL::Const chunk(unique_bit_id.at(bit), bits); + value.bits.insert(value.bits.end(), chunk.bits.begin(), chunk.bits.end()); } - parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), value); + parameters[stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))] = value; } } @@ -714,31 +778,34 @@ struct TechmapWorker use_wrapper_tpl:; // do not register techmap_wrap modules with techmap_cache } else { - std::pair> key(tpl_name, parameters); - auto it = techmap_cache.find(key); - if (it != techmap_cache.end()) { - tpl = it->second; + std::pair> key(tpl_name, parameters); + if (techmap_cache.count(key) > 0) { + tpl = techmap_cache[key]; } else { if (parameters.size() != 0) { mkdebug.on(); - derived_name = tpl->derive(map, parameters); + derived_name = tpl->derive(map, dict(parameters.begin(), parameters.end())); tpl = map->module(derived_name); log_continue = true; } - techmap_cache.emplace(std::move(key), tpl); + techmap_cache[key] = tpl; } } - RTLIL::Module *constmapped_tpl = map->module(constmap_tpl_name(sigmap, tpl, cell, false)); - if (constmapped_tpl != nullptr) - tpl = constmapped_tpl; + if (flatten_mode) { + techmap_do_cache[tpl] = true; + } else { + RTLIL::Module *constmapped_tpl = map->module(constmap_tpl_name(sigmap, tpl, cell, false)); + if (constmapped_tpl != nullptr) + tpl = constmapped_tpl; + } if (techmap_do_cache.count(tpl) == 0) { bool keep_running = true; techmap_do_cache[tpl] = true; - pool techmap_wire_names; + std::set techmap_wire_names; while (keep_running) { @@ -748,11 +815,11 @@ struct TechmapWorker for (auto &it : twd) techmap_wire_names.insert(it.first); - for (auto &it : twd[ID::_TECHMAP_FAIL_]) { + for (auto &it : twd["_TECHMAP_FAIL_"]) { RTLIL::SigSpec value = it.value; if (value.is_fully_const() && value.as_bool()) { log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n", - derived_name.c_str(), log_id(it.wire->name), log_signal(value)); + derived_name.c_str(), RTLIL::id2cstr(it.wire->name), log_signal(value)); techmap_do_cache[tpl] = false; } } @@ -762,13 +829,13 @@ struct TechmapWorker for (auto &it : twd) { - if (!it.first.begins_with("\\_TECHMAP_DO_") || it.second.empty()) + if (it.first.compare(0, 12, "_TECHMAP_DO_") != 0 || it.second.empty()) continue; auto &data = it.second.front(); if (!data.value.is_fully_const()) - log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(data.wire->name), log_signal(data.value)); + log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(data.wire->name), log_signal(data.value)); techmap_wire_names.erase(it.first); @@ -784,7 +851,7 @@ struct TechmapWorker cmd_string = cmd_string.substr(strlen("CONSTMAP; ")); log("Analyzing pattern of constant bits for this cell:\n"); - IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true); + RTLIL::IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true); log("Creating constmapped module `%s'.\n", log_id(new_tpl_name)); log_assert(map->module(new_tpl_name) == nullptr); @@ -795,16 +862,16 @@ struct TechmapWorker techmap_do_cache[new_tpl] = true; tpl = new_tpl; - dict port_new2old_map; - dict port_connmap; - dict cellbits_to_tplbits; + std::map port_new2old_map; + std::map port_connmap; + std::map cellbits_to_tplbits; for (auto wire : tpl->wires().to_vector()) { if (!wire->port_input || wire->port_output) continue; - IdString port_name = wire->name; + RTLIL::IdString port_name = wire->name; tpl->rename(wire, NEW_ID); RTLIL::Wire *new_wire = tpl->addWire(port_name, wire); @@ -812,12 +879,12 @@ struct TechmapWorker wire->port_id = 0; for (int i = 0; i < wire->width; i++) { - port_new2old_map.emplace(RTLIL::SigBit(new_wire, i), RTLIL::SigBit(wire, i)); - port_connmap.emplace(RTLIL::SigBit(wire, i), RTLIL::SigBit(new_wire, i)); + port_new2old_map[RTLIL::SigBit(new_wire, i)] = RTLIL::SigBit(wire, i); + port_connmap[RTLIL::SigBit(wire, i)] = RTLIL::SigBit(new_wire, i); } } - for (auto &conn : cell->connections()) + for (auto conn : cell->connections()) for (int i = 0; i < GetSize(conn.second); i++) { RTLIL::SigBit bit = sigmap(conn.second[i]); @@ -839,8 +906,8 @@ struct TechmapWorker RTLIL::SigSig port_conn; for (auto &it : port_connmap) { - port_conn.first.append(it.first); - port_conn.second.append(it.second); + port_conn.first.append_bit(it.first); + port_conn.second.append_bit(it.second); } tpl->connect(port_conn); @@ -859,7 +926,7 @@ struct TechmapWorker log_assert(!strncmp(q, "_TECHMAP_DO_", 12)); std::string new_name = data.wire->name.substr(0, q-p) + "_TECHMAP_DONE_" + data.wire->name.substr(q-p+12); - while (tpl->wire(new_name) != nullptr) + while (tpl->wires_.count(new_name)) new_name += "_"; tpl->rename(data.wire->name, new_name); @@ -870,17 +937,17 @@ struct TechmapWorker TechmapWires twd = techmap_find_special_wires(tpl); for (auto &it : twd) { - if (it.first != ID::_TECHMAP_FAIL_ && (!it.first.begins_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !it.first.begins_with("\\_TECHMAP_DO_") && !it.first.begins_with("\\_TECHMAP_DONE_")) - log_error("Techmap yielded unknown config wire %s.\n", log_id(it.first)); + if (it.first != "_TECHMAP_FAIL_" && (it.first.substr(0, 20) != "_TECHMAP_REMOVEINIT_" || it.first[it.first.size()-1] != '_') && it.first.substr(0, 12) != "_TECHMAP_DO_" && it.first.substr(0, 14) != "_TECHMAP_DONE_") + log_error("Techmap yielded unknown config wire %s.\n", it.first.c_str()); if (techmap_do_cache[tpl]) for (auto &it2 : it.second) if (!it2.value.is_fully_const()) - log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(it2.wire->name), log_signal(it2.value)); + log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(it2.wire->name), log_signal(it2.value)); techmap_wire_names.erase(it.first); } for (auto &it : techmap_wire_names) - log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", log_id(it)); + log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", RTLIL::id2cstr(it)); if (recursive_mode) { if (log_continue) { @@ -903,10 +970,10 @@ struct TechmapWorker TechmapWires twd = techmap_find_special_wires(tpl); for (auto &it : twd) { - if (it.first.begins_with("\\_TECHMAP_REMOVEINIT_")) { + if (it.first.substr(0, 20) == "_TECHMAP_REMOVEINIT_") { for (auto &it2 : it.second) { auto val = it2.value.as_const(); - auto wirename = RTLIL::escape_id(it.first.substr(21, it.first.size() - 21 - 1)); + auto wirename = RTLIL::escape_id(it.first.substr(20, it.first.size() - 20 - 1)); auto it = cell->connections().find(wirename); if (it != cell->connections().end()) { auto sig = sigmap(it->second); @@ -948,7 +1015,7 @@ struct TechmapWorker } log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(tpl)); techmap_module_worker(design, module, cell, tpl); - cell = nullptr; + cell = NULL; } did_something = true; mapped_cell = true; @@ -963,8 +1030,8 @@ struct TechmapWorker if (!remove_init_bits.empty()) { for (auto wire : module->wires()) - if (wire->attributes.count(ID::init)) { - Const &value = wire->attributes.at(ID::init); + if (wire->attributes.count("\\init")) { + Const &value = wire->attributes.at("\\init"); bool do_cleanup = true; for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) { SigBit bit = sigmap(SigBit(wire, i)); @@ -975,7 +1042,7 @@ struct TechmapWorker } if (do_cleanup) { log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire)); - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); } } } @@ -992,7 +1059,7 @@ struct TechmapWorker struct TechmapPass : public Pass { TechmapPass() : Pass("techmap", "generic technology mapper") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1152,7 +1219,7 @@ struct TechmapPass : public Pass { log("essentially techmap but using the design itself as map library).\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing TECHMAP pass (map to technology primitives).\n"); log_push(); @@ -1208,39 +1275,45 @@ struct TechmapPass : public Pass { RTLIL::Design *map = new RTLIL::Design; if (map_files.empty()) { - Frontend::frontend_call(map, nullptr, "+/techmap.v", verilog_frontend); + std::istringstream f(stdcells_code); + Frontend::frontend_call(map, &f, "", verilog_frontend); } else { for (auto &fn : map_files) if (fn.compare(0, 1, "%") == 0) { if (!saved_designs.count(fn.substr(1))) { delete map; - log_cmd_error("Can't open saved design `%s'.\n", fn.c_str()+1); + log_cmd_error("Can't saved design `%s'.\n", fn.c_str()+1); } for (auto mod : saved_designs.at(fn.substr(1))->modules()) - if (!map->module(mod->name)) + if (!map->has(mod->name)) map->add(mod->clone()); } else { - Frontend::frontend_call(map, nullptr, fn, (fn.size() > 3 && fn.compare(fn.size()-3, std::string::npos, ".il") == 0 ? "ilang" : verilog_frontend)); + std::ifstream f; + rewrite_filename(fn); + f.open(fn.c_str()); + yosys_input_files.insert(fn); + if (f.fail()) + log_cmd_error("Can't open map file `%s'\n", fn.c_str()); + Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.compare(fn.size()-3, std::string::npos, ".il") == 0 ? "ilang" : verilog_frontend)); } } log_header(design, "Continuing TECHMAP pass.\n"); - dict> celltypeMap; - for (auto module : map->modules()) { - if (module->attributes.count(ID::techmap_celltype) && !module->attributes.at(ID::techmap_celltype).bits.empty()) { - char *p = strdup(module->attributes.at(ID::techmap_celltype).decode_string().c_str()); - for (char *q = strtok(p, " \t\r\n"); q; q = strtok(nullptr, " \t\r\n")) - celltypeMap[RTLIL::escape_id(q)].insert(module->name); + std::map> celltypeMap; + for (auto &it : map->modules_) { + if (it.second->attributes.count(ID(techmap_celltype)) && !it.second->attributes.at(ID(techmap_celltype)).bits.empty()) { + char *p = strdup(it.second->attributes.at(ID(techmap_celltype)).decode_string().c_str()); + for (char *q = strtok(p, " \t\r\n"); q; q = strtok(NULL, " \t\r\n")) + celltypeMap[RTLIL::escape_id(q)].insert(it.first); free(p); } else { - IdString module_name = module->name.begins_with("\\$") ? - module->name.substr(1) : module->name.str(); - celltypeMap[module_name].insert(module->name); + string module_name = it.first.str(); + if (it.first.begins_with("\\$")) + module_name = module_name.substr(1); + celltypeMap[module_name].insert(it.first); } } - for (auto &i : celltypeMap) - i.second.sort(RTLIL::sort_by_id_str()); for (auto module : design->modules()) worker.module_queue.insert(module); @@ -1252,7 +1325,7 @@ struct TechmapPass : public Pass { int module_max_iter = max_iter; bool did_something = true; - pool handled_cells; + std::set handled_cells; while (did_something) { did_something = false; if (worker.techmap_module(design, module, map, handled_cells, celltypeMap, false)) @@ -1271,4 +1344,100 @@ struct TechmapPass : public Pass { } } TechmapPass; +struct FlattenPass : public Pass { + FlattenPass() : Pass("flatten", "flatten design") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" flatten [options] [selection]\n"); + log("\n"); + log("This pass flattens the design by replacing cells by their implementation. This\n"); + log("pass is very similar to the 'techmap' pass. The only difference is that this\n"); + log("pass is using the current design as mapping library.\n"); + log("\n"); + log("Cells and/or modules with the 'keep_hierarchy' attribute set will not be\n"); + log("flattened by this command.\n"); + log("\n"); + log(" -wb\n"); + log(" Ignore the 'whitebox' attribute on cell implementations.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing FLATTEN pass (flatten design).\n"); + log_push(); + + TechmapWorker worker; + worker.flatten_mode = true; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-wb") { + worker.ignore_wb = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + + std::map> celltypeMap; + for (auto module : design->modules()) + celltypeMap[module->name].insert(module->name); + + RTLIL::Module *top_mod = NULL; + if (design->full_selection()) + for (auto mod : design->modules()) + if (mod->get_bool_attribute(ID(top))) + top_mod = mod; + + std::set handled_cells; + if (top_mod != NULL) { + worker.flatten_do_list.insert(top_mod->name); + while (!worker.flatten_do_list.empty()) { + auto mod = design->module(*worker.flatten_do_list.begin()); + while (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) { } + worker.flatten_done_list.insert(mod->name); + worker.flatten_do_list.erase(mod->name); + } + } else { + for (auto mod : vector(design->modules())) { + while (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) { } + } + } + + log_suppressed(); + log("No more expansions possible.\n"); + + if (top_mod != NULL) + { + pool used_modules, new_used_modules; + new_used_modules.insert(top_mod->name); + while (!new_used_modules.empty()) { + pool queue; + queue.swap(new_used_modules); + for (auto modname : queue) + used_modules.insert(modname); + for (auto modname : queue) + for (auto cell : design->module(modname)->cells()) + if (design->module(cell->type) && !used_modules[cell->type]) + new_used_modules.insert(cell->type); + } + + dict new_modules; + for (auto mod : vector(design->modules())) + if (used_modules[mod->name] || mod->get_blackbox_attribute(worker.ignore_wb)) { + new_modules[mod->name] = mod; + } else { + log("Deleting now unused module %s.\n", log_id(mod)); + delete mod; + } + design->modules_.swap(new_modules); + } + + log_pop(); + } +} FlattenPass; + PRIVATE_NAMESPACE_END diff --git a/passes/techmap/tribuf.cc b/passes/techmap/tribuf.cc index 79ddb4bd7de..41fdc8f3d6b 100644 --- a/passes/techmap/tribuf.cc +++ b/passes/techmap/tribuf.cc @@ -71,7 +71,7 @@ struct TribufWorker { if (cell->type.in(ID($mux), ID($_MUX_))) { - IdString en_port = cell->type == ID($mux) ? ID::EN : ID::E; + IdString en_port = cell->type == ID($mux) ? ID(EN) : ID(E); IdString tri_type = cell->type == ID($mux) ? ID($tribuf) : ID($_TBUF_); if (is_all_z(cell->getPort(ID::A)) && is_all_z(cell->getPort(ID::B))) { @@ -81,22 +81,20 @@ struct TribufWorker { if (is_all_z(cell->getPort(ID::A))) { cell->setPort(ID::A, cell->getPort(ID::B)); - cell->setPort(en_port, cell->getPort(ID::S)); + cell->setPort(en_port, cell->getPort(ID(S))); cell->unsetPort(ID::B); - cell->unsetPort(ID::S); + cell->unsetPort(ID(S)); cell->type = tri_type; tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell); - module->design->scratchpad_set_bool("tribuf.added_something", true); continue; } if (is_all_z(cell->getPort(ID::B))) { - cell->setPort(en_port, module->Not(NEW_ID, cell->getPort(ID::S))); + cell->setPort(en_port, module->Not(NEW_ID, cell->getPort(ID(S)))); cell->unsetPort(ID::B); - cell->unsetPort(ID::S); + cell->unsetPort(ID(S)); cell->type = tri_type; tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell); - module->design->scratchpad_set_bool("tribuf.added_something", true); continue; } } @@ -121,9 +119,9 @@ struct TribufWorker { SigSpec pmux_b, pmux_s; for (auto cell : it.second) { if (cell->type == ID($tribuf)) - pmux_s.append(cell->getPort(ID::EN)); + pmux_s.append(cell->getPort(ID(EN))); else - pmux_s.append(cell->getPort(ID::E)); + pmux_s.append(cell->getPort(ID(E))); pmux_b.append(cell->getPort(ID::A)); module->remove(cell); } @@ -132,10 +130,8 @@ struct TribufWorker { if (no_tribuf) module->connect(it.first, muxout); - else { + else module->addTribuf(NEW_ID, muxout, module->ReduceOr(NEW_ID, pmux_s), it.first); - module->design->scratchpad_set_bool("tribuf.added_something", true); - } } } } @@ -143,7 +139,7 @@ struct TribufWorker { struct TribufPass : public Pass { TribufPass() : Pass("tribuf", "infer tri-state buffers") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -160,7 +156,7 @@ struct TribufPass : public Pass { log(" to non-tristate logic. this option implies -merge.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { TribufConfig config; diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc index cc0b26bcc52..ac3d4ed4ad5 100644 --- a/passes/techmap/zinit.cc +++ b/passes/techmap/zinit.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct ZinitPass : public Pass { ZinitPass() : Pass("zinit", "add inverters so all FF are zero-initialized") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -37,7 +37,7 @@ struct ZinitPass : public Pass { log(" also add zero initialization to uninitialized FFs\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool all_mode = false; @@ -57,15 +57,17 @@ struct ZinitPass : public Pass { for (auto module : design->selected_modules()) { SigMap sigmap(module); - dict> initbits; + dict initbits; + pool donebits; for (auto wire : module->selected_wires()) { - if (wire->attributes.count(ID::init) == 0) + if (wire->attributes.count(ID(init)) == 0) continue; SigSpec wirebits = sigmap(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at(ID(init)); + wire->attributes.erase(ID(init)); for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) { @@ -76,44 +78,24 @@ struct ZinitPass : public Pass { continue; if (initbits.count(bit)) { - if (initbits.at(bit).first != val) + if (initbits.at(bit) != val) log_error("Conflicting init values for signal %s (%s = %s != %s).\n", log_signal(bit), log_signal(SigBit(wire, i)), - log_signal(val), log_signal(initbits.at(bit).first)); + log_signal(val), log_signal(initbits.at(bit))); continue; } - initbits[bit] = std::make_pair(val,SigBit(wire,i)); + initbits[bit] = val; } } pool dff_types = { - // FIXME: It would appear that supporting - // $dffsr/$_DFFSR_* would require a new - // cell type where S has priority over R - ID($ff), ID($dff), ID($dffe), /*ID($dffsr),*/ ID($adff), ID($adffe), - ID($sdff), ID($sdffe), ID($sdffce), + ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($adff), ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), - /*ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), - ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),*/ + ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), + ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), - // Async set/reset - ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_), - ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_), - ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_), - ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_), - // Sync set/reset - ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_), - ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_), - ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_), - ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_), - ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_), - ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_), - ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_), - ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_), - ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_), - ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_) + ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_) }; for (auto cell : module->selected_cells()) @@ -121,8 +103,8 @@ struct ZinitPass : public Pass { if (!dff_types.count(cell->type)) continue; - SigSpec sig_d = sigmap(cell->getPort(ID::D)); - SigSpec sig_q = sigmap(cell->getPort(ID::Q)); + SigSpec sig_d = sigmap(cell->getPort(ID(D))); + SigSpec sig_q = sigmap(cell->getPort(ID(Q))); if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1) continue; @@ -131,23 +113,21 @@ struct ZinitPass : public Pass { for (int i = 0; i < GetSize(sig_q); i++) { if (initbits.count(sig_q[i])) { - const auto &d = initbits.at(sig_q[i]); - initval.bits.push_back(d.first); - const auto &b = d.second; - b.wire->attributes.at(ID::init)[b.offset] = State::Sx; + initval.bits.push_back(initbits.at(sig_q[i])); + donebits.insert(sig_q[i]); } else initval.bits.push_back(all_mode ? State::S0 : State::Sx); } Wire *initwire = module->addWire(NEW_ID, GetSize(initval)); - initwire->attributes[ID::init] = initval; + initwire->attributes[ID(init)] = initval; for (int i = 0; i < GetSize(initwire); i++) - if (initval[i] == State::S1) + if (initval.bits.at(i) == State::S1) { sig_d[i] = module->NotGate(NEW_ID, sig_d[i]); module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]); - initwire->attributes[ID::init][i] = State::S0; + initwire->attributes[ID(init)].bits.at(i) = State::S0; } else { @@ -157,59 +137,13 @@ struct ZinitPass : public Pass { log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type), log_signal(sig_q), log_signal(initval)); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, initwire); - - if (cell->type.in(ID($adff), ID($adffe))) { - auto val = cell->getParam(ID::ARST_VALUE); - for (int i = 0; i < GetSize(initwire); i++) - if (initval[i] == State::S1) - val[i] = (val[i] == State::S1 ? State::S0 : State::S1); - cell->setParam(ID::ARST_VALUE, std::move(val)); - } - else if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) { - auto val = cell->getParam(ID::SRST_VALUE); - for (int i = 0; i < GetSize(initwire); i++) - if (initval[i] == State::S1) - val[i] = (val[i] == State::S1 ? State::S0 : State::S1); - cell->setParam(ID::SRST_VALUE, std::move(val)); - } - else if (initval == State::S1) { - std::string t = cell->type.str(); - if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_))) - { - t[8] = (t[8] == '0' ? '1' : '0'); - } - else if (cell->type.in(ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_), - ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_))) - { - t[9] = (t[9] == '0' ? '1' : '0'); - } - else if (cell->type.in(ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_), - ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_), - ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_), - ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_))) - { - t[9] = (t[9] == '0' ? '1' : '0'); - } - else if (cell->type.in(ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_), - ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_), - ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_), - ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_))) - { - t[10] = (t[10] == '0' ? '1' : '0'); - } - else if (cell->type.in(ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_), - ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_), - ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_), - ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_))) - { - t[11] = (t[11] == '0' ? '1' : '0'); - } - cell->type = t; - } + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), initwire); } + + for (auto &it : initbits) + if (donebits.count(it.first) == 0) + log_error("Failed to handle init bit %s = %s.\n", log_signal(it.first), log_signal(it.second)); } } } ZinitPass; diff --git a/passes/tests/test_abcloop.cc b/passes/tests/test_abcloop.cc index 2d80e66e454..5d5466afe8a 100644 --- a/passes/tests/test_abcloop.cc +++ b/passes/tests/test_abcloop.cc @@ -55,7 +55,7 @@ static void test_abcloop() while (1) { - module = design->addModule(ID(UUT)); + module = design->addModule("\\uut"); create_cycles++; in_sig = {}; @@ -132,7 +132,7 @@ static void test_abcloop() SatGen satgen(ez.get(), &sigmap); for (auto c : module->cells()) { - bool ok = satgen.importCell(c); + bool ok YS_ATTRIBUTE(unused) = satgen.importCell(c); log_assert(ok); } @@ -182,7 +182,7 @@ static void test_abcloop() SatGen satgen(ez.get(), &sigmap); for (auto c : module->cells()) { - bool ok = satgen.importCell(c); + bool ok YS_ATTRIBUTE(unused) = satgen.importCell(c); log_assert(ok); } @@ -244,7 +244,7 @@ static void test_abcloop() struct TestAbcloopPass : public Pass { TestAbcloopPass() : Pass("test_abcloop", "automatically test handling of loops in abc command") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -259,7 +259,7 @@ struct TestAbcloopPass : public Pass { log(" use this value as rng seed value (default = unix time).\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design*) override + void execute(std::vector args, RTLIL::Design*) YS_OVERRIDE { int num_iter = 100; xorshift32_state = 0; diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc index 4ab46014d90..2b6a86c2508 100644 --- a/passes/tests/test_autotb.cc +++ b/passes/tests/test_autotb.cc @@ -81,12 +81,11 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s f << stringf("integer i;\n"); f << stringf("integer file;\n\n"); - f << stringf("reg [1023:0] filename;\n\n"); f << stringf("reg [31:0] xorshift128_x = 123456789;\n"); f << stringf("reg [31:0] xorshift128_y = 362436069;\n"); f << stringf("reg [31:0] xorshift128_z = 521288629;\n"); - f << stringf("reg [31:0] xorshift128_w = %u; // <-- seed value\n", seed ? seed : int(time(nullptr))); + f << stringf("reg [31:0] xorshift128_w = %u; // <-- seed value\n", seed ? seed : int(time(NULL))); f << stringf("reg [31:0] xorshift128_t;\n\n"); f << stringf("task xorshift128;\n"); f << stringf("begin\n"); @@ -98,26 +97,29 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s f << stringf("end\n"); f << stringf("endtask\n\n"); - for (auto mod : design->modules()) + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { std::map signal_in; std::map signal_const; std::map signal_clk; std::map signal_out; - if (mod->get_bool_attribute(ID::gentb_skip)) + RTLIL::Module *mod = it->second; + + if (mod->get_bool_attribute("\\gentb_skip")) continue; int count_ports = 0; - log("Generating test bench for module `%s'.\n", mod->name.c_str()); - for (auto wire : mod->wires()) { + log("Generating test bench for module `%s'.\n", it->first.c_str()); + for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) { + RTLIL::Wire *wire = it2->second; if (wire->port_output) { count_ports++; signal_out[idy("sig", mod->name.str(), wire->name.str())] = wire->width; f << stringf("wire [%d:0] %s;\n", wire->width-1, idy("sig", mod->name.str(), wire->name.str()).c_str()); } else if (wire->port_input) { count_ports++; - bool is_clksignal = wire->get_bool_attribute(ID::gentb_clock); + bool is_clksignal = wire->get_bool_attribute("\\gentb_clock"); for (auto it3 = mod->processes.begin(); it3 != mod->processes.end(); ++it3) for (auto it4 = it3->second->syncs.begin(); it4 != it3->second->syncs.end(); ++it4) { if ((*it4)->type == RTLIL::ST0 || (*it4)->type == RTLIL::ST1) @@ -127,18 +129,19 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s if (c.wire == wire) is_clksignal = true; } - if (is_clksignal && wire->attributes.count(ID::gentb_constant) == 0) { + if (is_clksignal && wire->attributes.count("\\gentb_constant") == 0) { signal_clk[idy("sig", mod->name.str(), wire->name.str())] = wire->width; } else { signal_in[idy("sig", mod->name.str(), wire->name.str())] = wire->width; - if (wire->attributes.count(ID::gentb_constant) != 0) - signal_const[idy("sig", mod->name.str(), wire->name.str())] = wire->attributes[ID::gentb_constant].as_string(); + if (wire->attributes.count("\\gentb_constant") != 0) + signal_const[idy("sig", mod->name.str(), wire->name.str())] = wire->attributes["\\gentb_constant"].as_string(); } f << stringf("reg [%d:0] %s;\n", wire->width-1, idy("sig", mod->name.str(), wire->name.str()).c_str()); } } f << stringf("%s %s(\n", id(mod->name.str()).c_str(), idy("uut", mod->name.str()).c_str()); - for (auto wire : mod->wires()) { + for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) { + RTLIL::Wire *wire = it2->second; if (wire->port_output || wire->port_input) f << stringf("\t.%s(%s)%s\n", id(wire->name.str()).c_str(), idy("sig", mod->name.str(), wire->name.str()).c_str(), --count_ports ? "," : ""); @@ -306,18 +309,12 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s } f << stringf("initial begin\n"); - f << stringf("\tif ($value$plusargs(\"VCD=%%s\", filename)) begin\n"); - f << stringf("\t\t$dumpfile(filename);\n"); - f << stringf("\t\t$dumpvars(0, testbench);\n"); - f << stringf("\tend\n"); - f << stringf("\tif ($value$plusargs(\"OUT=%%s\", filename)) begin\n"); - f << stringf("\t\tfile = $fopen(filename);\n"); - f << stringf("\tend else begin\n"); - f << stringf("\t\tfile = $fopen(`outfile);\n"); - f << stringf("\tend\n"); - for (auto module : design->modules()) - if (!module->get_bool_attribute(ID::gentb_skip)) - f << stringf("\t%s;\n", idy(module->name.str(), "test").c_str()); + f << stringf("\t// $dumpfile(\"testbench.vcd\");\n"); + f << stringf("\t// $dumpvars(0, testbench);\n"); + f << stringf("\tfile = $fopen(`outfile);\n"); + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) + if (!it->second->get_bool_attribute("\\gentb_skip")) + f << stringf("\t%s;\n", idy(it->first.str(), "test").c_str()); f << stringf("\t$fclose(file);\n"); f << stringf("\t$finish;\n"); f << stringf("end\n\n"); @@ -327,7 +324,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s struct TestAutotbBackend : public Backend { TestAutotbBackend() : Backend("=test_autotb", "generate simple test benches") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -360,7 +357,7 @@ struct TestAutotbBackend : public Backend { log(" the current system time.\n"); log("\n"); } - void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { int num_iter = 1000; int seed = 0; diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 125efbaa360..88116eeece5 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -39,98 +39,98 @@ static uint32_t xorshift32(uint32_t limit) { static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, std::string cell_type_flags, bool constmode, bool muxdiv) { - RTLIL::Module *module = design->addModule(ID(gold)); - RTLIL::Cell *cell = module->addCell(ID(UUT), cell_type); + RTLIL::Module *module = design->addModule("\\gold"); + RTLIL::Cell *cell = module->addCell("\\UUT", cell_type); RTLIL::Wire *wire; - if (cell_type.in(ID($mux), ID($pmux))) + if (cell_type.in("$mux", "$pmux")) { int width = 1 + xorshift32(8); - int swidth = cell_type == ID($mux) ? 1 : 1 + xorshift32(8); + int swidth = cell_type == "$mux" ? 1 : 1 + xorshift32(8); - wire = module->addWire(ID::A); + wire = module->addWire("\\A"); wire->width = width; wire->port_input = true; - cell->setPort(ID::A, wire); + cell->setPort("\\A", wire); - wire = module->addWire(ID::B); + wire = module->addWire("\\B"); wire->width = width * swidth; wire->port_input = true; - cell->setPort(ID::B, wire); + cell->setPort("\\B", wire); - wire = module->addWire(ID::S); + wire = module->addWire("\\S"); wire->width = swidth; wire->port_input = true; - cell->setPort(ID::S, wire); + cell->setPort("\\S", wire); - wire = module->addWire(ID::Y); + wire = module->addWire("\\Y"); wire->width = width; wire->port_output = true; - cell->setPort(ID::Y, wire); + cell->setPort("\\Y", wire); } - if (cell_type == ID($fa)) + if (cell_type == "$fa") { int width = 1 + xorshift32(8); - wire = module->addWire(ID::A); + wire = module->addWire("\\A"); wire->width = width; wire->port_input = true; - cell->setPort(ID::A, wire); + cell->setPort("\\A", wire); - wire = module->addWire(ID::B); + wire = module->addWire("\\B"); wire->width = width; wire->port_input = true; - cell->setPort(ID::B, wire); + cell->setPort("\\B", wire); - wire = module->addWire(ID::C); + wire = module->addWire("\\C"); wire->width = width; wire->port_input = true; - cell->setPort(ID::C, wire); + cell->setPort("\\C", wire); - wire = module->addWire(ID::X); + wire = module->addWire("\\X"); wire->width = width; wire->port_output = true; - cell->setPort(ID::X, wire); + cell->setPort("\\X", wire); - wire = module->addWire(ID::Y); + wire = module->addWire("\\Y"); wire->width = width; wire->port_output = true; - cell->setPort(ID::Y, wire); + cell->setPort("\\Y", wire); } - if (cell_type == ID($lcu)) + if (cell_type == "$lcu") { int width = 1 + xorshift32(8); - wire = module->addWire(ID::P); + wire = module->addWire("\\P"); wire->width = width; wire->port_input = true; - cell->setPort(ID::P, wire); + cell->setPort("\\P", wire); - wire = module->addWire(ID::G); + wire = module->addWire("\\G"); wire->width = width; wire->port_input = true; - cell->setPort(ID::G, wire); + cell->setPort("\\G", wire); - wire = module->addWire(ID::CI); + wire = module->addWire("\\CI"); wire->port_input = true; - cell->setPort(ID::CI, wire); + cell->setPort("\\CI", wire); - wire = module->addWire(ID::CO); + wire = module->addWire("\\CO"); wire->width = width; wire->port_output = true; - cell->setPort(ID::CO, wire); + cell->setPort("\\CO", wire); } - if (cell_type == ID($macc)) + if (cell_type == "$macc") { Macc macc; int width = 1 + xorshift32(8); int depth = 1 + xorshift32(6); int mulbits_a = 0, mulbits_b = 0; - RTLIL::Wire *wire_a = module->addWire(ID::A); + RTLIL::Wire *wire_a = module->addWire("\\A"); wire_a->width = 0; wire_a->port_input = true; @@ -158,52 +158,52 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, macc.ports.push_back(this_port); } - wire = module->addWire(ID::B); + wire = module->addWire("\\B"); wire->width = xorshift32(mulbits_a ? xorshift32(4)+1 : xorshift32(16)+1); wire->port_input = true; macc.bit_ports = wire; - wire = module->addWire(ID::Y); + wire = module->addWire("\\Y"); wire->width = width; wire->port_output = true; - cell->setPort(ID::Y, wire); + cell->setPort("\\Y", wire); macc.to_cell(cell); } - if (cell_type == ID($lut)) + if (cell_type == "$lut") { int width = 1 + xorshift32(6); - wire = module->addWire(ID::A); + wire = module->addWire("\\A"); wire->width = width; wire->port_input = true; - cell->setPort(ID::A, wire); + cell->setPort("\\A", wire); - wire = module->addWire(ID::Y); + wire = module->addWire("\\Y"); wire->port_output = true; - cell->setPort(ID::Y, wire); + cell->setPort("\\Y", wire); RTLIL::SigSpec config; for (int i = 0; i < (1 << width); i++) config.append(xorshift32(2) ? State::S1 : State::S0); - cell->setParam(ID::LUT, config.as_const()); + cell->setParam("\\LUT", config.as_const()); } - if (cell_type == ID($sop)) + if (cell_type == "$sop") { int width = 1 + xorshift32(8); int depth = 1 + xorshift32(8); - wire = module->addWire(ID::A); + wire = module->addWire("\\A"); wire->width = width; wire->port_input = true; - cell->setPort(ID::A, wire); + cell->setPort("\\A", wire); - wire = module->addWire(ID::Y); + wire = module->addWire("\\Y"); wire->port_output = true; - cell->setPort(ID::Y, wire); + cell->setPort("\\Y", wire); RTLIL::SigSpec config; for (int i = 0; i < width*depth; i++) @@ -222,78 +222,74 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, break; } - cell->setParam(ID::DEPTH, depth); - cell->setParam(ID::TABLE, config.as_const()); + cell->setParam("\\DEPTH", depth); + cell->setParam("\\TABLE", config.as_const()); } if (cell_type_flags.find('A') != std::string::npos) { - wire = module->addWire(ID::A); + wire = module->addWire("\\A"); wire->width = 1 + xorshift32(8); wire->port_input = true; - cell->setPort(ID::A, wire); + cell->setPort("\\A", wire); } if (cell_type_flags.find('B') != std::string::npos) { - wire = module->addWire(ID::B); + wire = module->addWire("\\B"); if (cell_type_flags.find('h') != std::string::npos) wire->width = 1 + xorshift32(6); else wire->width = 1 + xorshift32(8); wire->port_input = true; - cell->setPort(ID::B, wire); + cell->setPort("\\B", wire); } if (cell_type_flags.find('S') != std::string::npos && xorshift32(2)) { if (cell_type_flags.find('A') != std::string::npos) - cell->parameters[ID::A_SIGNED] = true; + cell->parameters["\\A_SIGNED"] = true; if (cell_type_flags.find('B') != std::string::npos) - cell->parameters[ID::B_SIGNED] = true; + cell->parameters["\\B_SIGNED"] = true; } if (cell_type_flags.find('s') != std::string::npos) { if (cell_type_flags.find('A') != std::string::npos && xorshift32(2)) - cell->parameters[ID::A_SIGNED] = true; + cell->parameters["\\A_SIGNED"] = true; if (cell_type_flags.find('B') != std::string::npos && xorshift32(2)) - cell->parameters[ID::B_SIGNED] = true; + cell->parameters["\\B_SIGNED"] = true; } if (cell_type_flags.find('Y') != std::string::npos) { - wire = module->addWire(ID::Y); + wire = module->addWire("\\Y"); wire->width = 1 + xorshift32(8); wire->port_output = true; - cell->setPort(ID::Y, wire); + cell->setPort("\\Y", wire); } - if (cell_type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) { - cell->parameters[ID::B_SIGNED] = false; + if (muxdiv && cell_type.in("$div", "$mod")) { + auto b_not_zero = module->ReduceBool(NEW_ID, cell->getPort("\\B")); + auto div_out = module->addWire(NEW_ID, GetSize(cell->getPort("\\Y"))); + module->addMux(NEW_ID, RTLIL::SigSpec(0, GetSize(div_out)), div_out, b_not_zero, cell->getPort("\\Y")); + cell->setPort("\\Y", div_out); } - if (muxdiv && cell_type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) { - auto b_not_zero = module->ReduceBool(NEW_ID, cell->getPort(ID::B)); - auto div_out = module->addWire(NEW_ID, GetSize(cell->getPort(ID::Y))); - module->addMux(NEW_ID, RTLIL::SigSpec(0, GetSize(div_out)), div_out, b_not_zero, cell->getPort(ID::Y)); - cell->setPort(ID::Y, div_out); - } - - if (cell_type == ID($alu)) + if (cell_type == "$alu") { - wire = module->addWire(ID::CI); + wire = module->addWire("\\CI"); wire->port_input = true; - cell->setPort(ID::CI, wire); + cell->setPort("\\CI", wire); - wire = module->addWire(ID::BI); + wire = module->addWire("\\BI"); wire->port_input = true; - cell->setPort(ID::BI, wire); + cell->setPort("\\BI", wire); - wire = module->addWire(ID::X); - wire->width = GetSize(cell->getPort(ID::Y)); + wire = module->addWire("\\X"); + wire->width = GetSize(cell->getPort("\\Y")); wire->port_output = true; - cell->setPort(ID::X, wire); + cell->setPort("\\X", wire); - wire = module->addWire(ID::CO); - wire->width = GetSize(cell->getPort(ID::Y)); + wire = module->addWire("\\CO"); + wire->width = GetSize(cell->getPort("\\Y")); wire->port_output = true; - cell->setPort(ID::CO, wire); + cell->setPort("\\CO", wire); } if (constmode) @@ -425,8 +421,8 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: { log("Eval testing:%c", verbose ? '\n' : ' '); - RTLIL::Module *gold_mod = design->module(ID(gold)); - RTLIL::Module *gate_mod = design->module(ID(gate)); + RTLIL::Module *gold_mod = design->module("\\gold"); + RTLIL::Module *gate_mod = design->module("\\gate"); ConstEval gold_ce(gold_mod), gate_ce(gate_mod); ezSatPtr ez1, ez2; @@ -656,7 +652,7 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: struct TestCellPass : public Pass { TestCellPass() : Pass("test_cell", "automatically test the implementation of a cell type") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -716,7 +712,7 @@ struct TestCellPass : public Pass { log(" create a Verilog test bench to test simlib and write_verilog\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design*) override + void execute(std::vector args, RTLIL::Design*) YS_OVERRIDE { int num_iter = 100; std::string techmap_cmd = "techmap -assert"; @@ -804,67 +800,65 @@ struct TestCellPass : public Pass { log("Rng seed value: %d\n", int(xorshift32_state)); } - std::map cell_types; - std::vector selected_cell_types; - - cell_types[ID($not)] = "ASY"; - cell_types[ID($pos)] = "ASY"; - cell_types[ID($neg)] = "ASY"; - - cell_types[ID($and)] = "ABSY"; - cell_types[ID($or)] = "ABSY"; - cell_types[ID($xor)] = "ABSY"; - cell_types[ID($xnor)] = "ABSY"; - - cell_types[ID($reduce_and)] = "ASY"; - cell_types[ID($reduce_or)] = "ASY"; - cell_types[ID($reduce_xor)] = "ASY"; - cell_types[ID($reduce_xnor)] = "ASY"; - cell_types[ID($reduce_bool)] = "ASY"; - - cell_types[ID($shl)] = "ABshY"; - cell_types[ID($shr)] = "ABshY"; - cell_types[ID($sshl)] = "ABshY"; - cell_types[ID($sshr)] = "ABshY"; - cell_types[ID($shift)] = "ABshY"; - cell_types[ID($shiftx)] = "ABshY"; - - cell_types[ID($lt)] = "ABSY"; - cell_types[ID($le)] = "ABSY"; - cell_types[ID($eq)] = "ABSY"; - cell_types[ID($ne)] = "ABSY"; - // cell_types[ID($eqx)] = "ABSY"; - // cell_types[ID($nex)] = "ABSY"; - cell_types[ID($ge)] = "ABSY"; - cell_types[ID($gt)] = "ABSY"; - - cell_types[ID($add)] = "ABSY"; - cell_types[ID($sub)] = "ABSY"; - cell_types[ID($mul)] = "ABSY"; - cell_types[ID($div)] = "ABSY"; - cell_types[ID($mod)] = "ABSY"; - cell_types[ID($divfloor)] = "ABSY"; - cell_types[ID($modfloor)] = "ABSY"; - // cell_types[ID($pow)] = "ABsY"; - - cell_types[ID($logic_not)] = "ASY"; - cell_types[ID($logic_and)] = "ABSY"; - cell_types[ID($logic_or)] = "ABSY"; + std::map cell_types; + std::vector selected_cell_types; + + cell_types["$not"] = "ASY"; + cell_types["$pos"] = "ASY"; + cell_types["$neg"] = "ASY"; + + cell_types["$and"] = "ABSY"; + cell_types["$or"] = "ABSY"; + cell_types["$xor"] = "ABSY"; + cell_types["$xnor"] = "ABSY"; + + cell_types["$reduce_and"] = "ASY"; + cell_types["$reduce_or"] = "ASY"; + cell_types["$reduce_xor"] = "ASY"; + cell_types["$reduce_xnor"] = "ASY"; + cell_types["$reduce_bool"] = "ASY"; + + cell_types["$shl"] = "ABshY"; + cell_types["$shr"] = "ABshY"; + cell_types["$sshl"] = "ABshY"; + cell_types["$sshr"] = "ABshY"; + cell_types["$shift"] = "ABshY"; + cell_types["$shiftx"] = "ABshY"; + + cell_types["$lt"] = "ABSY"; + cell_types["$le"] = "ABSY"; + cell_types["$eq"] = "ABSY"; + cell_types["$ne"] = "ABSY"; + // cell_types["$eqx"] = "ABSY"; + // cell_types["$nex"] = "ABSY"; + cell_types["$ge"] = "ABSY"; + cell_types["$gt"] = "ABSY"; + + cell_types["$add"] = "ABSY"; + cell_types["$sub"] = "ABSY"; + cell_types["$mul"] = "ABSY"; + cell_types["$div"] = "ABSY"; + cell_types["$mod"] = "ABSY"; + // cell_types["$pow"] = "ABsY"; + + cell_types["$logic_not"] = "ASY"; + cell_types["$logic_and"] = "ABSY"; + cell_types["$logic_or"] = "ABSY"; if (edges) { - cell_types[ID($mux)] = "*"; - cell_types[ID($pmux)] = "*"; + cell_types["$mux"] = "*"; + cell_types["$pmux"] = "*"; } - // cell_types[ID($slice)] = "A"; - // cell_types[ID($concat)] = "A"; + // cell_types["$slice"] = "A"; + // cell_types["$concat"] = "A"; - cell_types[ID($lut)] = "*"; - cell_types[ID($sop)] = "*"; - cell_types[ID($alu)] = "ABSY"; - cell_types[ID($lcu)] = "*"; - cell_types[ID($macc)] = "*"; - cell_types[ID($fa)] = "*"; + cell_types["$lut"] = "*"; + cell_types["$sop"] = "*"; + cell_types["$alu"] = "ABSY"; + cell_types["$lcu"] = "*"; + cell_types["$macc"] = "*"; + cell_types["$fa"] = "*"; for (; argidx < GetSize(args); argidx++) { @@ -879,7 +873,7 @@ struct TestCellPass : public Pass { } if (args[argidx].compare(0, 1, "/") == 0) { - std::vector new_selected_cell_types; + std::vector new_selected_cell_types; for (auto it : selected_cell_types) if (it != args[argidx].substr(1)) new_selected_cell_types.push_back(it); @@ -892,10 +886,10 @@ struct TestCellPass : public Pass { int charcount = 100; for (auto &it : cell_types) { if (charcount > 60) { - cell_type_list += stringf("\n%s", + log_id(it.first)); + cell_type_list += "\n" + it.first; charcount = 0; } else - cell_type_list += stringf(" %s", log_id(it.first)); + cell_type_list += " " + it.first; charcount += GetSize(it.first); } log_cmd_error("The cell type `%s' is currently not supported. Try one of these:%s\n", diff --git a/techlibs/achronix/Makefile.inc b/techlibs/achronix/Makefile.inc old mode 100644 new mode 100755 diff --git a/techlibs/achronix/speedster22i/cells_arith.v b/techlibs/achronix/speedster22i/cells_arith.v old mode 100644 new mode 100755 index 8529706a7dd..e2194cbd7ba --- a/techlibs/achronix/speedster22i/cells_arith.v +++ b/techlibs/achronix/speedster22i/cells_arith.v @@ -26,11 +26,8 @@ module _80_altera_max10_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; @@ -39,14 +36,11 @@ module _80_altera_max10_alu (A, B, CI, BI, X, Y, CO); wire _TECHMAP_FAIL_ = Y_WIDTH <= 4; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; //wire [Y_WIDTH:0] C = {CO, CI}; wire [Y_WIDTH+1:0] COx; diff --git a/techlibs/achronix/speedster22i/cells_map.v b/techlibs/achronix/speedster22i/cells_map.v old mode 100644 new mode 100755 index a19e53f4997..9f647cbef09 --- a/techlibs/achronix/speedster22i/cells_map.v +++ b/techlibs/achronix/speedster22i/cells_map.v @@ -38,7 +38,6 @@ endmodule module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; generate diff --git a/techlibs/achronix/speedster22i/cells_sim.v b/techlibs/achronix/speedster22i/cells_sim.v old mode 100644 new mode 100755 diff --git a/techlibs/achronix/synth_achronix.cc b/techlibs/achronix/synth_achronix.cc old mode 100644 new mode 100755 index ddd9822b9ab..626860d9c17 --- a/techlibs/achronix/synth_achronix.cc +++ b/techlibs/achronix/synth_achronix.cc @@ -28,7 +28,7 @@ PRIVATE_NAMESPACE_BEGIN struct SynthAchronixPass : public ScriptPass { SynthAchronixPass() : ScriptPass("synth_achronix", "synthesis for Acrhonix Speedster22i FPGAs.") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -52,7 +52,7 @@ struct SynthAchronixPass : public ScriptPass { log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -63,7 +63,7 @@ struct SynthAchronixPass : public ScriptPass { string top_opt, family_opt, vout_file; bool retime, flatten; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; vout_file = ""; @@ -71,7 +71,7 @@ struct SynthAchronixPass : public ScriptPass { flatten = true; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -118,7 +118,7 @@ struct SynthAchronixPass : public ScriptPass { log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { @@ -144,6 +144,7 @@ struct SynthAchronixPass : public ScriptPass { run("opt -fast -mux_undef -undriven -fine -full"); run("memory_map"); run("opt -undriven -fine"); + run("dffsr2dff"); run("dff2dffe -direct-match $_DFF_*"); run("opt -fine"); run("techmap -map +/techmap.v"); @@ -151,12 +152,12 @@ struct SynthAchronixPass : public ScriptPass { run("clean -purge"); run("setundef -undriven -zero"); if (retime || help_mode) - run("abc -markgroups -dff -D 1", "(only if -retime)"); + run("abc -markgroups -dff", "(only if -retime)"); } if (check_label("map_luts")) { - run("abc -lut 4" + string(retime ? " -dff -D 1" : "")); + run("abc -lut 4" + string(retime ? " -dff" : "")); run("clean"); } diff --git a/techlibs/anlogic/Makefile.inc b/techlibs/anlogic/Makefile.inc index 2d8d65e2e41..9426b5ca545 100644 --- a/techlibs/anlogic/Makefile.inc +++ b/techlibs/anlogic/Makefile.inc @@ -7,6 +7,6 @@ $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_sim.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/eagle_bb.v)) -$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams.txt)) -$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams_map.v)) -$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutram_init_16x4.vh)) +$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/drams.txt)) +$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/drams_map.v)) +$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/dram_init_16x4.vh)) diff --git a/techlibs/anlogic/anlogic_eqn.cc b/techlibs/anlogic/anlogic_eqn.cc index e5fbc186f39..070d39a20c3 100644 --- a/techlibs/anlogic/anlogic_eqn.cc +++ b/techlibs/anlogic/anlogic_eqn.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct AnlogicEqnPass : public Pass { AnlogicEqnPass() : Pass("anlogic_eqn", "Anlogic: Calculate equations for luts") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" anlogic_eqn [selection]\n"); @@ -63,7 +63,7 @@ struct AnlogicEqnPass : public Pass { return Const(eqn); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ANLOGIC_EQN pass (calculate equations for luts).\n"); @@ -74,34 +74,34 @@ struct AnlogicEqnPass : public Pass { { for (auto cell : module->selected_cells()) { - if (cell->type == ID(AL_MAP_LUT1)) + if (cell->type == "\\AL_MAP_LUT1") { - cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT),1)); + cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),1)); cnt++; } - if (cell->type == ID(AL_MAP_LUT2)) + if (cell->type == "\\AL_MAP_LUT2") { - cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT),2)); + cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),2)); cnt++; } - if (cell->type == ID(AL_MAP_LUT3)) + if (cell->type == "\\AL_MAP_LUT3") { - cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT),3)); + cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),3)); cnt++; } - if (cell->type == ID(AL_MAP_LUT4)) + if (cell->type == "\\AL_MAP_LUT4") { - cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT),4)); + cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),4)); cnt++; } - if (cell->type == ID(AL_MAP_LUT5)) + if (cell->type == "\\AL_MAP_LUT5") { - cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT),5)); + cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),5)); cnt++; } - if (cell->type == ID(AL_MAP_LUT6)) + if (cell->type == "\\AL_MAP_LUT6") { - cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT),6)); + cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),6)); cnt++; } } diff --git a/techlibs/anlogic/anlogic_fixcarry.cc b/techlibs/anlogic/anlogic_fixcarry.cc index c7dfe3c0540..87164d375f2 100644 --- a/techlibs/anlogic/anlogic_fixcarry.cc +++ b/techlibs/anlogic/anlogic_fixcarry.cc @@ -39,13 +39,13 @@ static void fix_carry_chain(Module *module) for (auto cell : module->cells()) { - if (cell->type == ID(AL_MAP_ADDER)) { - if (cell->getParam(ID(ALUTYPE)) != Const("ADD")) continue; - SigBit bit_i0 = get_bit_or_zero(cell->getPort(ID(a))); - SigBit bit_i1 = get_bit_or_zero(cell->getPort(ID(b))); + if (cell->type == "\\AL_MAP_ADDER") { + if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue; + SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a")); + SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b")); if (bit_i0 == State::S0 && bit_i1== State::S0) { - SigBit bit_ci = get_bit_or_zero(cell->getPort(ID(c))); - SigSpec o = cell->getPort(ID(o)); + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c")); + SigSpec o = cell->getPort("\\o"); if (GetSize(o) == 2) { SigBit bit_o = o[0]; ci_bits.insert(bit_ci); @@ -57,11 +57,11 @@ static void fix_carry_chain(Module *module) vector adders_to_fix_cells; for (auto cell : module->cells()) { - if (cell->type == ID(AL_MAP_ADDER)) { - if (cell->getParam(ID(ALUTYPE)) != Const("ADD")) continue; - SigBit bit_ci = get_bit_or_zero(cell->getPort(ID(c))); - SigBit bit_i0 = get_bit_or_zero(cell->getPort(ID(a))); - SigBit bit_i1 = get_bit_or_zero(cell->getPort(ID(b))); + if (cell->type == "\\AL_MAP_ADDER") { + if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue; + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c")); + SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a")); + SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b")); SigBit canonical_bit = sigmap(bit_ci); if (!ci_bits.count(canonical_bit)) continue; @@ -75,30 +75,30 @@ static void fix_carry_chain(Module *module) for (auto cell : adders_to_fix_cells) { - SigBit bit_ci = get_bit_or_zero(cell->getPort(ID(c))); + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c")); SigBit canonical_bit = sigmap(bit_ci); auto bit = mapping_bits.at(canonical_bit); log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell)); - Cell *c = module->addCell(NEW_ID, ID(AL_MAP_ADDER)); + Cell *c = module->addCell(NEW_ID, "\\AL_MAP_ADDER"); SigBit new_bit = module->addWire(NEW_ID); SigBit dummy_bit = module->addWire(NEW_ID); SigSpec bits; bits.append(dummy_bit); bits.append(new_bit); - c->setParam(ID(ALUTYPE), Const("ADD_CARRY")); - c->setPort(ID(a), bit); - c->setPort(ID(b), State::S0); - c->setPort(ID(c), State::S0); - c->setPort(ID(o), bits); + c->setParam("\\ALUTYPE", Const("ADD_CARRY")); + c->setPort("\\a", bit); + c->setPort("\\b", State::S0); + c->setPort("\\c", State::S0); + c->setPort("\\o", bits); - cell->setPort(ID(c), new_bit); + cell->setPort("\\c", new_bit); } } struct AnlogicCarryFixPass : public Pass { AnlogicCarryFixPass() : Pass("anlogic_fixcarry", "Anlogic: fix carry chain") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -107,7 +107,7 @@ struct AnlogicCarryFixPass : public Pass { log("Add Anlogic adders to fix carry chain if needed.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing anlogic_fixcarry pass (fix invalid carry chain).\n"); diff --git a/techlibs/anlogic/arith_map.v b/techlibs/anlogic/arith_map.v index 23e190bcb87..1186543daed 100644 --- a/techlibs/anlogic/arith_map.v +++ b/techlibs/anlogic/arith_map.v @@ -26,33 +26,24 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; - (* force_downto *) output [Y_WIDTH-1:0] CO; wire CIx; - (* force_downto *) wire [Y_WIDTH-1:0] COx; wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; - (* force_downto *) wire [Y_WIDTH-1:0] C = { COx, CIx }; wire dummy; diff --git a/techlibs/anlogic/cells_map.v b/techlibs/anlogic/cells_map.v index 0bcea985657..cfc743a4bd1 100644 --- a/techlibs/anlogic/cells_map.v +++ b/techlibs/anlogic/cells_map.v @@ -6,14 +6,14 @@ module \$_DFFE_NP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REG module \$_DFFE_PN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule module \$_DFFE_PP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule -module \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), . SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), . SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule module \$_DLATCH_N_ (E, D, Q); wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; @@ -32,7 +32,6 @@ module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; diff --git a/techlibs/anlogic/lutram_init_16x4.vh b/techlibs/anlogic/dram_init_16x4.vh similarity index 100% rename from techlibs/anlogic/lutram_init_16x4.vh rename to techlibs/anlogic/dram_init_16x4.vh diff --git a/techlibs/anlogic/lutrams.txt b/techlibs/anlogic/drams.txt similarity index 100% rename from techlibs/anlogic/lutrams.txt rename to techlibs/anlogic/drams.txt diff --git a/techlibs/anlogic/lutrams_map.v b/techlibs/anlogic/drams_map.v similarity index 91% rename from techlibs/anlogic/lutrams_map.v rename to techlibs/anlogic/drams_map.v index 5a464cafc3e..084e2a25fee 100644 --- a/techlibs/anlogic/lutrams_map.v +++ b/techlibs/anlogic/drams_map.v @@ -10,7 +10,7 @@ module \$__ANLOGIC_DRAM16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); input B1EN; EG_LOGIC_DRAM16X4 #( - `include "lutram_init_16x4.vh" + `include "dram_init_16x4.vh" ) _TECHMAP_REPLACE_ ( .di(B1DATA), .waddr(B1ADDR), diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc index d7475df86a0..b87fc8566e2 100644 --- a/techlibs/anlogic/synth_anlogic.cc +++ b/techlibs/anlogic/synth_anlogic.cc @@ -30,7 +30,7 @@ struct SynthAnlogicPass : public ScriptPass { SynthAnlogicPass() : ScriptPass("synth_anlogic", "synthesis for Anlogic FPGAs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -58,10 +58,7 @@ struct SynthAnlogicPass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); - log("\n"); - log(" -nolutram\n"); - log(" do not use EG_LOGIC_DRAM16X4 cells in output netlist\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -70,19 +67,18 @@ struct SynthAnlogicPass : public ScriptPass } string top_opt, edif_file, json_file; - bool flatten, retime, nolutram; + bool flatten, retime; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; edif_file = ""; json_file = ""; flatten = true; retime = false; - nolutram = false; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -114,10 +110,6 @@ struct SynthAnlogicPass : public ScriptPass flatten = false; continue; } - if (args[argidx] == "-nolutram") { - nolutram = true; - continue; - } if (args[argidx] == "-retime") { retime = true; continue; @@ -137,7 +129,7 @@ struct SynthAnlogicPass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { @@ -158,30 +150,26 @@ struct SynthAnlogicPass : public ScriptPass run("synth -run coarse"); } - if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) + if (check_label("dram")) { - run("memory_bram -rules +/anlogic/lutrams.txt"); - run("techmap -map +/anlogic/lutrams_map.v"); + run("memory_bram -rules +/anlogic/drams.txt"); + run("techmap -map +/anlogic/drams_map.v"); run("setundef -zero -params t:EG_LOGIC_DRAM16X4"); } - if (check_label("map_ffram")) + if (check_label("fine")) { run("opt -fast -mux_undef -undriven -fine"); run("memory_map"); run("opt -undriven -fine"); - } - - if (check_label("map_gates")) - { run("techmap -map +/techmap.v -map +/anlogic/arith_map.v"); - run("opt -fast"); if (retime || help_mode) - run("abc -dff -D 1", "(only if -retime)"); + run("abc -dff", "(only if -retime)"); } if (check_label("map_ffs")) { + run("dffsr2dff"); run("techmap -D NO_LUT -map +/anlogic/cells_map.v"); run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit"); run("opt_expr -mux_undef"); @@ -199,7 +187,7 @@ struct SynthAnlogicPass : public ScriptPass run("techmap -map +/anlogic/cells_map.v"); run("clean"); } - + if (check_label("map_anlogic")) { run("anlogic_fixcarry"); diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 607e772a228..a42f6312804 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -29,7 +29,4 @@ $(eval $(call add_share_file,share,techlibs/common/gate2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cells.lib)) $(eval $(call add_share_file,share,techlibs/common/mul2dsp.v)) -$(eval $(call add_share_file,share,techlibs/common/abc9_model.v)) -$(eval $(call add_share_file,share,techlibs/common/abc9_map.v)) -$(eval $(call add_share_file,share,techlibs/common/abc9_unmap.v)) -$(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v)) +$(eval $(call add_share_file,share,techlibs/common/dummy.box)) diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v deleted file mode 100644 index 6ed90b5f571..00000000000 --- a/techlibs/common/abc9_map.v +++ /dev/null @@ -1,27 +0,0 @@ -`ifdef DFF -(* techmap_celltype = "$_DFF_N_ $_DFF_P_" *) -module $_DFF_x_(input C, D, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - parameter _TECHMAP_CELLTYPE_ = ""; - wire D_; - generate if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin - if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin - $__DFF_N__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); - $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); - end - else - (* abc9_keep *) $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - end - else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin - if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin - $__DFF_P__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); - $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); - end - else - (* abc9_keep *) $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - end - else if (_TECHMAP_CELLTYPE_ != "") - $error("Unrecognised _TECHMAP_CELLTYPE_"); - endgenerate -endmodule -`endif diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v deleted file mode 100644 index 4fee60f752a..00000000000 --- a/techlibs/common/abc9_model.v +++ /dev/null @@ -1,25 +0,0 @@ -(* abc9_box *) -module $__ABC9_DELAY (input I, output O); - parameter DELAY = 0; - specify - (I => O) = DELAY; - endspecify -endmodule - -(* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_N__$abc9_flop (input C, D, Q, output n1); - assign n1 = D; - specify - $setup(D, posedge C, 0); - (posedge C => (n1:D)) = 0; - endspecify -endmodule - -(* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_P__$abc9_flop (input C, D, Q, output n1); - assign n1 = D; - specify - $setup(D, posedge C, 0); - (posedge C => (n1:D)) = 0; - endspecify -endmodule diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v deleted file mode 100644 index c39648c623a..00000000000 --- a/techlibs/common/abc9_unmap.v +++ /dev/null @@ -1,11 +0,0 @@ -(* techmap_celltype = "$__DFF_N__$abc9_flop $__DFF_P__$abc9_flop" *) -module $__DFF_x__$abc9_flop (input C, D, (* init = 1'b0 *) input Q, output n1); - parameter _TECHMAP_CELLTYPE_ = ""; - generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N__$abc9_flop") - $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - else if (_TECHMAP_CELLTYPE_ == "$__DFF_P__$abc9_flop") - $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - else if (_TECHMAP_CELLTYPE_ != "") - $error("Unrecognised _TECHMAP_CELLTYPE_"); - endgenerate -endmodule diff --git a/techlibs/common/adff2dff.v b/techlibs/common/adff2dff.v index eca0110eb1f..86744d41534 100644 --- a/techlibs/common/adff2dff.v +++ b/techlibs/common/adff2dff.v @@ -6,11 +6,8 @@ module adff2dff (CLK, ARST, D, Q); parameter ARST_VALUE = 0; input CLK, ARST; - (* force_downto *) input [WIDTH-1:0] D; - (* force_downto *) output reg [WIDTH-1:0] Q; - (* force_downto *) wire reg [WIDTH-1:0] NEXT_Q; wire [1023:0] _TECHMAP_DO_ = "proc;;"; diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v deleted file mode 100644 index a221727e774..00000000000 --- a/techlibs/common/cmp2lcu.v +++ /dev/null @@ -1,132 +0,0 @@ -// This pass performs an optimisation that decomposes wide arithmetic -// comparisons into LUT-size chunks (as guided by the `LUT_WIDTH -// macro) connected to a single lookahead-carry-unit $lcu cell, -// which is typically mapped to dedicated (and fast) FPGA -// carry-chains. -(* techmap_celltype = "$lt $le $gt $ge" *) -module _80_lcu_cmp_ (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 0; -parameter B_WIDTH = 0; -parameter Y_WIDTH = 0; - -(* force_downto *) -input [A_WIDTH-1:0] A; -(* force_downto *) -input [B_WIDTH-1:0] B; -(* force_downto *) -output [Y_WIDTH-1:0] Y; - -parameter _TECHMAP_CELLTYPE_ = ""; - -generate - if (_TECHMAP_CELLTYPE_ == "" || `LUT_WIDTH < 2) - wire _TECHMAP_FAIL_ = 1; - else if (_TECHMAP_CELLTYPE_ == "$lt") begin - // Transform $lt into $gt by swapping A and B - $gt #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); - end - else if (_TECHMAP_CELLTYPE_ == "$le") begin - // Transform $le into $ge by swapping A and B - $ge #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); - end - else begin - // Perform sign extension on A and B - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - (* force_downto *) - wire [WIDTH-1:0] AA = {{(WIDTH-A_WIDTH){A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; - (* force_downto *) - wire [WIDTH-1:0] BB = {{(WIDTH-B_WIDTH){B_SIGNED ? B[B_WIDTH-1] : 1'b0}}, B}; - // For $ge operation, start with the assumption that A and B are - // equal (propagating this equality if A and B turn out to be so) - if (_TECHMAP_CELLTYPE_ == "$ge") - localparam CI = 1'b1; - else - localparam CI = 1'b0; - $__CMP2LCU #(.AB_WIDTH(WIDTH), .AB_SIGNED(A_SIGNED && B_SIGNED), .LCU_WIDTH(1), .BUDGET(`LUT_WIDTH), .CI(CI)) - _TECHMAP_REPLACE_ (.A(AA), .B(BB), .P(1'b1), .G(1'b0), .Y(Y)); - end -endgenerate -endmodule - -module $__CMP2LCU (A, B, P, G, Y); - -parameter AB_WIDTH = 0; -parameter AB_SIGNED = 0; -parameter LCU_WIDTH = 1; -parameter BUDGET = 0; -parameter CI = 0; - -(* force_downto *) -input [AB_WIDTH-1:0] A; // A from original $gt/$ge -(* force_downto *) -input [AB_WIDTH-1:0] B; // B from original $gt/$ge -(* force_downto *) -input [LCU_WIDTH-1:0] P; // P of $lcu -(* force_downto *) -input [LCU_WIDTH-1:0] G; // G of $lcu -output Y; - -parameter [AB_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; -parameter [AB_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; -parameter [LCU_WIDTH-1:0] _TECHMAP_CONSTMSK_P_ = 0; - -generate - if (AB_WIDTH == 0) begin - (* force_downto *) - wire [LCU_WIDTH-1:0] CO; - $lcu #(.WIDTH(LCU_WIDTH)) _TECHMAP_REPLACE_ (.P(P), .G(G), .CI(CI), .CO(CO)); - assign Y = CO[LCU_WIDTH-1]; - end - else begin - if (_TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] && _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0]) - localparam COST = 0; - else if (_TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] || _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0]) - localparam COST = 1; - else - localparam COST = 2; - - if (BUDGET < COST) - $__CMP2LCU #(.AB_WIDTH(AB_WIDTH), .AB_SIGNED(AB_SIGNED), .LCU_WIDTH(LCU_WIDTH+1), .BUDGET(`LUT_WIDTH), .CI(CI)) - _TECHMAP_REPLACE_ (.A(A), .B(B), .P({P, 1'b1}), .G({G, 1'b0}), .Y(Y)); - else begin - wire PP, GG; - // Bit-wise equality (xnor) of A and B - assign PP = A[AB_WIDTH-1] ^~ B[AB_WIDTH-1]; - if (AB_SIGNED) - assign GG = ~A[AB_WIDTH-1] & B[AB_WIDTH-1]; - else if (_TECHMAP_CONSTMSK_P_[LCU_WIDTH-1]) // First compare for LUT if P (and G) is constant - assign GG = A[AB_WIDTH-1] & ~B[AB_WIDTH-1]; - else - // Priority "encoder" that checks A[i] == 1'b1 && B[i] == 1'b0 - // from MSB down, deferring to less significant bits if the - // MSBs are equal - assign GG = P[0] & (A[AB_WIDTH-1] & ~B[AB_WIDTH-1]); - if (LCU_WIDTH == 1) begin - // Propagate only if all pairs are equal - // (inconclusive evidence to say A >= B) - wire P_ = P[0] & PP; - // Generate if any comparisons call for it - wire G_ = G[0] | GG; - end - else begin - // Propagate only if all pairs are equal - // (inconclusive evidence to say A >= B) - (* force_downto *) - wire [LCU_WIDTH-1:0] P_ = {P[LCU_WIDTH-1:1], P[0] & PP}; - // Generate if any comparisons call for it - (* force_downto *) - wire [LCU_WIDTH-1:0] G_ = {G[LCU_WIDTH-1:1], G[0] | GG}; - end - if (AB_WIDTH == 1) - $__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-COST), .CI(CI)) - _TECHMAP_REPLACE_ (.A(), .B(), .P(P_), .G(G_), .Y(Y)); - else - $__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-COST), .CI(CI)) - _TECHMAP_REPLACE_ (.A(A[AB_WIDTH-2:0]), .B(B[AB_WIDTH-2:0]), .P(P_), .G(G_), .Y(Y)); - end - end -endgenerate -endmodule diff --git a/techlibs/common/cmp2lut.v b/techlibs/common/cmp2lut.v index ec8f98e8d75..1c8192b85f7 100644 --- a/techlibs/common/cmp2lut.v +++ b/techlibs/common/cmp2lut.v @@ -16,11 +16,8 @@ parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; -(* force_downto *) input [A_WIDTH-1:0] A; -(* force_downto *) input [B_WIDTH-1:0] B; -(* force_downto *) output [Y_WIDTH-1:0] Y; parameter _TECHMAP_CELLTYPE_ = ""; @@ -60,6 +57,10 @@ function automatic [(1 << `LUT_WIDTH)-1:0] gen_lut; o_bit = (lhs > rhs); if (operation == 3) o_bit = (lhs >= rhs); + if (operation == 4) + o_bit = (lhs == rhs); + if (operation == 5) + o_bit = (lhs != rhs); gen_lut = gen_lut | (o_bit << n); end end @@ -74,6 +75,10 @@ generate localparam operation = 2; if (_TECHMAP_CELLTYPE_ == "$ge") localparam operation = 3; + if (_TECHMAP_CELLTYPE_ == "$eq") + localparam operation = 4; + if (_TECHMAP_CELLTYPE_ == "$ne") + localparam operation = 5; if (A_WIDTH > `LUT_WIDTH || B_WIDTH > `LUT_WIDTH || Y_WIDTH != 1) wire _TECHMAP_FAIL_ = 1; diff --git a/techlibs/common/dff2ff.v b/techlibs/common/dff2ff.v index 33a79ffffab..2dc4d20d37d 100644 --- a/techlibs/common/dff2ff.v +++ b/techlibs/common/dff2ff.v @@ -4,9 +4,7 @@ module dff2ff (CLK, D, Q); parameter CLK_POLARITY = 1; input CLK; - (* force_downto *) input [WIDTH-1:0] D; - (* force_downto *) output reg [WIDTH-1:0] Q; wire [1023:0] _TECHMAP_DO_ = "proc;;"; diff --git a/techlibs/common/dummy.box b/techlibs/common/dummy.box new file mode 100644 index 00000000000..0c18070a02c --- /dev/null +++ b/techlibs/common/dummy.box @@ -0,0 +1 @@ +(dummy) 1 0 0 0 diff --git a/techlibs/common/gate2lut.v b/techlibs/common/gate2lut.v index 15cea3d8d5b..99c123f4a3a 100644 --- a/techlibs/common/gate2lut.v +++ b/techlibs/common/gate2lut.v @@ -79,7 +79,7 @@ module _90_lut_mux (A, B, S, Y); // A 1010 1010 // B 1100 1100 // S 1111 0000 - .LUT(8'b 1100_1010) + .LUT(8'b_1100_1010) ) lut ( .A(AA), .Y(Y) diff --git a/techlibs/common/gen_fine_ffs.py b/techlibs/common/gen_fine_ffs.py deleted file mode 100644 index e92d58f40ef..00000000000 --- a/techlibs/common/gen_fine_ffs.py +++ /dev/null @@ -1,391 +0,0 @@ -TEMPLATES = [ -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SR_{S:N|P}{R:N|P}_ (S, R, Q) -//- -//- A set-reset latch with {S:negative|positive} polarity SET and {R:negative|positive} polarity RESET. -//- -//- Truth table: S R | Q -//- -----+--- -//- - {R:0|1} | 0 -//- {S:0|1} - | 1 -//- - - | q -//- -module \$_SR_{S:N|P}{R:N|P}_ (S, R, Q); -input S, R; -output reg Q; -always @* begin - if (R == {R:0|1}) - Q <= 0; - else if (S == {S:0|1}) - Q <= 1; -end -endmodule -""", -""" -`ifdef SIMCELLS_FF -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_FF_ (D, Q) -//- -//- A D-type flip-flop that is clocked from the implicit global clock. (This cell -//- type is usually only used in netlists for formal verification.) -//- -module \$_FF_ (D, Q); -input D; -output reg Q; -always @($global_clock) begin - Q <= D; -end -endmodule -`endif -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFF_{C:N|P}_ (D, C, Q) -//- -//- A {C:negative|positive} edge D-type flip-flop. -//- -//- Truth table: D C | Q -//- -----+--- -//- d {C:\\|/} | d -//- - - | q -//- -module \$_DFF_{C:N|P}_ (D, C, Q); -input D, C; -output reg Q; -always @({C:neg|pos}edge C) begin - Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFE_{C:N|P}{E:N|P}_ (D, C, E, Q) -//- -//- A {C:negative|positive} edge D-type flip-flop with {E:negative|positive} polarity enable. -//- -//- Truth table: D C E | Q -//- -------+--- -//- d {C:\\|/} {E:0|1} | d -//- - - - | q -//- -module \$_DFFE_{C:N|P}{E:N|P}_ (D, C, E, Q); -input D, C, E; -output reg Q; -always @({C:neg|pos}edge C) begin - if ({E:!E|E}) Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q) -//- -//- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity {V:reset|set}. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - - {R:0|1} | {V:0|1} -//- d {C:\\|/} - | d -//- - - - | q -//- -module \$_DFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @({C:neg|pos}edge C or {R:neg|pos}edge R) begin - if (R == {R:0|1}) - Q <= {V:0|1}; - else - Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q) -//- -//- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity {V:reset|set} and {E:negative|positive} -//- polarity clock enable. -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - - {R:0|1} - | {V:0|1} -//- d {C:\\|/} - {E:0|1} | d -//- - - - - | q -//- -module \$_DFFE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @({C:neg|pos}edge C or {R:neg|pos}edge R) begin - if (R == {R:0|1}) - Q <= {V:0|1}; - else if (E == {E:0|1}) - Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q) -//- -//- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set and {R:negative|positive} -//- polarity reset. -//- -//- Truth table: C S R D | Q -//- ---------+--- -//- - - {R:0|1} - | 0 -//- - {S:0|1} - - | 1 -//- {C:\\|/} - - d | d -//- - - - - | q -//- -module \$_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q); -input C, S, R, D; -output reg Q; -always @({C:neg|pos}edge C, {S:neg|pos}edge S, {R:neg|pos}edge R) begin - if (R == {R:0|1}) - Q <= 0; - else if (S == {S:0|1}) - Q <= 1; - else - Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_{C:N|P}{S:N|P}{R:N|P}{E:N|P}_ (C, S, R, E, D, Q) -//- -//- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set, {R:negative|positive} -//- polarity reset and {E:negative|positive} polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - {R:0|1} - - | 0 -//- - {S:0|1} - - - | 1 -//- {C:\\|/} - - {E:0|1} d | d -//- - - - - - | q -//- -module \$_DFFSRE_{C:N|P}{S:N|P}{R:N|P}{E:N|P}_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @({C:neg|pos}edge C, {S:neg|pos}edge S, {R:neg|pos}edge R) begin - if (R == {R:0|1}) - Q <= 0; - else if (S == {S:0|1}) - Q <= 1; - else if (E == {E:0|1}) - Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q) -//- -//- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity synchronous {V:reset|set}. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - {C:\\|/} {R:0|1} | {V:0|1} -//- d {C:\\|/} - | d -//- - - - | q -//- -module \$_SDFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @({C:neg|pos}edge C) begin - if (R == {R:0|1}) - Q <= {V:0|1}; - else - Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q) -//- -//- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity synchronous {V:reset|set} and {E:negative|positive} -//- polarity clock enable (with {V:reset|set} having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - {C:\\|/} {R:0|1} - | {V:0|1} -//- d {C:\\|/} - {E:0|1} | d -//- - - - - | q -//- -module \$_SDFFE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @({C:neg|pos}edge C) begin - if (R == {R:0|1}) - Q <= {V:0|1}; - else if (E == {E:0|1}) - Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q) -//- -//- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity synchronous {V:reset|set} and {E:negative|positive} -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - {C:\\|/} {R:0|1} {E:0|1} | {V:0|1} -//- d {C:\\|/} - {E:0|1} | d -//- - - - - | q -//- -module \$_SDFFCE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @({C:neg|pos}edge C) begin - if (E == {E:0|1}) begin - if (R == {R:0|1}) - Q <= {V:0|1}; - else - Q <= D; - end -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_{E:N|P}_ (E, D, Q) -//- -//- A {E:negative|positive} enable D-type latch. -//- -//- Truth table: E D | Q -//- -----+--- -//- {E:0|1} d | d -//- - - | q -//- -module \$_DLATCH_{E:N|P}_ (E, D, Q); -input E, D; -output reg Q; -always @* begin - if (E == {E:0|1}) - Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_{E:N|P}{R:N|P}{V:0|1}_ (E, R, D, Q) -//- -//- A {E:negative|positive} enable D-type latch with {R:negative|positive} polarity {V:reset|set}. -//- -//- Truth table: E R D | Q -//- -------+--- -//- - {R:0|1} - | {V:0|1} -//- {E:0|1} - d | d -//- - - - | q -//- -module \$_DLATCH_{E:N|P}{R:N|P}{V:0|1}_ (E, R, D, Q); -input E, R, D; -output reg Q; -always @* begin - if (R == {E:0|1}) - Q <= {V:0|1}; - else if (E == {E:0|1}) - Q <= D; -end -endmodule -""", -""" -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCHSR_{E:N|P}{S:N|P}{R:N|P}_ (E, S, R, D, Q) -//- -//- A {E:negative|positive} enable D-type latch with {S:negative|positive} polarity set and {R:negative|positive} -//- polarity reset. -//- -//- Truth table: E S R D | Q -//- ---------+--- -//- - - {R:0|1} - | 0 -//- - {S:0|1} - - | 1 -//- {E:0|1} - - d | d -//- - - - - | q -//- -module \$_DLATCHSR_{E:N|P}{S:N|P}{R:N|P}_ (E, S, R, D, Q); -input E, S, R, D; -output reg Q; -always @* begin - if (R == {R:0|1}) - Q <= 0; - else if (S == {S:0|1}) - Q <= 1; - else if (E == {E:0|1}) - Q <= D; -end -endmodule -""", -] - -lines = [] -with open('simcells.v') as f: - for l in f: - lines.append(l) - if 'START AUTOGENERATED CELL TYPES' in l: - break - -with open('simcells.v', 'w') as f: - for l in lines: - f.write(l) - for template in TEMPLATES: - chunks = [] - vars = {} - pos = 0 - while pos < len(template): - if template[pos] != '{': - np = template.find('{', pos) - if np == -1: - np = len(template) - chunks.append(template[pos:np]) - pos = np - else: - np = template.index('}', pos) - sub = template[pos + 1:np] - pos = np + 1 - var, _, vals = sub.partition(':') - if not vals: - raise ValueError(sub) - vals = vals.split('|') - if var not in vars: - vars[var] = len(vals) - else: - if vars[var] != len(vals): - raise ValueError(vars[var], vals) - chunks.append((var, vals)) - combs = [{}] - for var in vars: - combs = [ - { - var: i, - **comb, - } - for comb in combs - for i in range(vars[var]) - ] - for comb in combs: - f.write( - ''.join( - c if isinstance(c, str) else c[1][comb[c[0]]] - for c in chunks - ) - ) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index bec47d01f9c..4cabb4453e9 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -57,11 +57,8 @@ module _80_mul (A, B, Y); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; parameter _TECHMAP_CELLTYPE_ = ""; @@ -122,19 +119,13 @@ module _80_mul (A, B, Y); localparam last_A_WIDTH = A_WIDTH-n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom); localparam last_Y_WIDTH = B_WIDTH+last_A_WIDTH; if (A_SIGNED && B_SIGNED) begin - (* force_downto *) wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; - (* force_downto *) wire signed [last_Y_WIDTH-1:0] last_partial; - (* force_downto *) wire signed [Y_WIDTH-1:0] partial_sum [n:0]; end else begin - (* force_downto *) wire [partial_Y_WIDTH-1:0] partial [n-1:0]; - (* force_downto *) wire [last_Y_WIDTH-1:0] last_partial; - (* force_downto *) wire [Y_WIDTH-1:0] partial_sum [n:0]; end @@ -179,19 +170,13 @@ module _80_mul (A, B, Y); localparam last_B_WIDTH = B_WIDTH-n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom); localparam last_Y_WIDTH = A_WIDTH+last_B_WIDTH; if (A_SIGNED && B_SIGNED) begin - (* force_downto *) wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; - (* force_downto *) wire signed [last_Y_WIDTH-1:0] last_partial; - (* force_downto *) wire signed [Y_WIDTH-1:0] partial_sum [n:0]; end else begin - (* force_downto *) wire [partial_Y_WIDTH-1:0] partial [n-1:0]; - (* force_downto *) wire [last_Y_WIDTH-1:0] last_partial; - (* force_downto *) wire [Y_WIDTH-1:0] partial_sum [n:0]; end @@ -264,11 +249,8 @@ module _90_soft_mul (A, B, Y); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; // Indirection necessary since mapping diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc index 93b0910d674..cdd21c3b328 100644 --- a/techlibs/common/prep.cc +++ b/techlibs/common/prep.cc @@ -29,7 +29,7 @@ struct PrepPass : public ScriptPass { PrepPass() : ScriptPass("prep", "generic synthesis script") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -81,7 +81,7 @@ struct PrepPass : public ScriptPass string top_module, fsm_opts; bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, nordff; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_module.clear(); @@ -94,7 +94,7 @@ struct PrepPass : public ScriptPass nordff = true; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; @@ -163,7 +163,7 @@ struct PrepPass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) @@ -192,7 +192,7 @@ struct PrepPass : public ScriptPass run(nokeepdc ? "opt_expr" : "opt_expr -keepdc"); run("opt_clean"); run("check"); - run(nokeepdc ? "opt -noff" : "opt -noff -keepdc"); + run(nokeepdc ? "opt" : "opt -keepdc"); if (!ifxmode) { if (help_mode) run("wreduce -keepdc [-memx]"); @@ -208,7 +208,7 @@ struct PrepPass : public ScriptPass run("opt_clean"); run("memory_collect"); } - run(nokeepdc ? "opt -noff -fast" : "opt -noff -keepdc -fast"); + run(nokeepdc ? "opt -fast" : "opt -keepdc -fast"); } if (check_label("check")) diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index 01b5bdfa69c..64720e59859 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -456,27 +456,23 @@ output Y; assign Y = E ? A : 1'bz; endmodule -// NOTE: the following cell types are autogenerated. DO NOT EDIT them manually, -// instead edit the templates in gen_ff_types.py and rerun it. - -// START AUTOGENERATED CELL TYPES - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- //- $_SR_NN_ (S, R, Q) //- -//- A set-reset latch with negative polarity SET and negative polarity RESET. +//- A set-reset latch with negative polarity SET and RESET. //- //- Truth table: S R | Q //- -----+--- -//- - 0 | 0 -//- 0 - | 1 -//- - - | q +//- 0 0 | x +//- 0 1 | 1 +//- 1 0 | 0 +//- 1 1 | y //- module \$_SR_NN_ (S, R, Q); input S, R; output reg Q; -always @* begin +always @(negedge S, negedge R) begin if (R == 0) Q <= 0; else if (S == 0) @@ -492,14 +488,15 @@ endmodule //- //- Truth table: S R | Q //- -----+--- -//- - 1 | 0 -//- 0 - | 1 -//- - - | q +//- 0 1 | x +//- 0 0 | 1 +//- 1 1 | 0 +//- 1 0 | y //- module \$_SR_NP_ (S, R, Q); input S, R; output reg Q; -always @* begin +always @(negedge S, posedge R) begin if (R == 1) Q <= 0; else if (S == 0) @@ -515,14 +512,15 @@ endmodule //- //- Truth table: S R | Q //- -----+--- -//- - 0 | 0 -//- 1 - | 1 -//- - - | q +//- 1 0 | x +//- 1 1 | 1 +//- 0 0 | 0 +//- 0 1 | y //- module \$_SR_PN_ (S, R, Q); input S, R; output reg Q; -always @* begin +always @(posedge S, negedge R) begin if (R == 0) Q <= 0; else if (S == 1) @@ -534,18 +532,19 @@ endmodule //- //- $_SR_PP_ (S, R, Q) //- -//- A set-reset latch with positive polarity SET and positive polarity RESET. +//- A set-reset latch with positive polarity SET and RESET. //- //- Truth table: S R | Q //- -----+--- -//- - 1 | 0 -//- 1 - | 1 -//- - - | q +//- 1 1 | x +//- 1 0 | 1 +//- 0 1 | 0 +//- 0 0 | y //- module \$_SR_PP_ (S, R, Q); input S, R; output reg Q; -always @* begin +always @(posedge S, posedge R) begin if (R == 1) Q <= 0; else if (S == 1) @@ -870,262 +869,276 @@ endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_NN0N_ (D, C, R, E, Q) +//- $_DFFSR_NNN_ (C, S, R, D, Q) //- -//- A negative edge D-type flip-flop with negative polarity reset and negative -//- polarity clock enable. +//- A negative edge D-type flip-flop with negative polarity set and reset. //- -//- Truth table: D C R E | Q +//- Truth table: C S R D | Q //- ---------+--- //- - - 0 - | 0 -//- d \ - 0 | d +//- - 0 - - | 1 +//- \ - - d | d //- - - - - | q //- -module \$_DFFE_NN0N_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DFFSR_NNN_ (C, S, R, D, Q); +input C, S, R, D; output reg Q; -always @(negedge C or negedge R) begin +always @(negedge C, negedge S, negedge R) begin if (R == 0) Q <= 0; - else if (E == 0) + else if (S == 0) + Q <= 1; + else Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_NN0P_ (D, C, R, E, Q) +//- $_DFFSR_NNP_ (C, S, R, D, Q) //- -//- A negative edge D-type flip-flop with negative polarity reset and positive -//- polarity clock enable. +//- A negative edge D-type flip-flop with negative polarity set and positive +//- polarity reset. //- -//- Truth table: D C R E | Q +//- Truth table: C S R D | Q //- ---------+--- -//- - - 0 - | 0 -//- d \ - 1 | d +//- - - 1 - | 0 +//- - 0 - - | 1 +//- \ - - d | d //- - - - - | q //- -module \$_DFFE_NN0P_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DFFSR_NNP_ (C, S, R, D, Q); +input C, S, R, D; output reg Q; -always @(negedge C or negedge R) begin - if (R == 0) +always @(negedge C, negedge S, posedge R) begin + if (R == 1) Q <= 0; - else if (E == 1) + else if (S == 0) + Q <= 1; + else Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_NN1N_ (D, C, R, E, Q) +//- $_DFFSR_NPN_ (C, S, R, D, Q) //- -//- A negative edge D-type flip-flop with negative polarity set and negative -//- polarity clock enable. +//- A negative edge D-type flip-flop with positive polarity set and negative +//- polarity reset. //- -//- Truth table: D C R E | Q +//- Truth table: C S R D | Q //- ---------+--- -//- - - 0 - | 1 -//- d \ - 0 | d +//- - - 0 - | 0 +//- - 1 - - | 1 +//- \ - - d | d //- - - - - | q //- -module \$_DFFE_NN1N_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DFFSR_NPN_ (C, S, R, D, Q); +input C, S, R, D; output reg Q; -always @(negedge C or negedge R) begin +always @(negedge C, posedge S, negedge R) begin if (R == 0) + Q <= 0; + else if (S == 1) Q <= 1; - else if (E == 0) + else Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_NN1P_ (D, C, R, E, Q) +//- $_DFFSR_NPP_ (C, S, R, D, Q) //- -//- A negative edge D-type flip-flop with negative polarity set and positive -//- polarity clock enable. +//- A negative edge D-type flip-flop with positive polarity set and reset. //- -//- Truth table: D C R E | Q +//- Truth table: C S R D | Q //- ---------+--- -//- - - 0 - | 1 -//- d \ - 1 | d +//- - - 1 - | 0 +//- - 1 - - | 1 +//- \ - - d | d //- - - - - | q //- -module \$_DFFE_NN1P_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DFFSR_NPP_ (C, S, R, D, Q); +input C, S, R, D; output reg Q; -always @(negedge C or negedge R) begin - if (R == 0) +always @(negedge C, posedge S, posedge R) begin + if (R == 1) + Q <= 0; + else if (S == 1) Q <= 1; - else if (E == 1) + else Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_NP0N_ (D, C, R, E, Q) +//- $_DFFSR_PNN_ (C, S, R, D, Q) //- -//- A negative edge D-type flip-flop with positive polarity reset and negative -//- polarity clock enable. +//- A positive edge D-type flip-flop with negative polarity set and reset. //- -//- Truth table: D C R E | Q +//- Truth table: C S R D | Q //- ---------+--- -//- - - 1 - | 0 -//- d \ - 0 | d +//- - - 0 - | 0 +//- - 0 - - | 1 +//- / - - d | d //- - - - - | q //- -module \$_DFFE_NP0N_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DFFSR_PNN_ (C, S, R, D, Q); +input C, S, R, D; output reg Q; -always @(negedge C or posedge R) begin - if (R == 1) +always @(posedge C, negedge S, negedge R) begin + if (R == 0) Q <= 0; - else if (E == 0) + else if (S == 0) + Q <= 1; + else Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_NP0P_ (D, C, R, E, Q) +//- $_DFFSR_PNP_ (C, S, R, D, Q) //- -//- A negative edge D-type flip-flop with positive polarity reset and positive -//- polarity clock enable. +//- A positive edge D-type flip-flop with negative polarity set and positive +//- polarity reset. //- -//- Truth table: D C R E | Q +//- Truth table: C S R D | Q //- ---------+--- //- - - 1 - | 0 -//- d \ - 1 | d +//- - 0 - - | 1 +//- / - - d | d //- - - - - | q //- -module \$_DFFE_NP0P_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DFFSR_PNP_ (C, S, R, D, Q); +input C, S, R, D; output reg Q; -always @(negedge C or posedge R) begin +always @(posedge C, negedge S, posedge R) begin if (R == 1) Q <= 0; - else if (E == 1) + else if (S == 0) + Q <= 1; + else Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_NP1N_ (D, C, R, E, Q) +//- $_DFFSR_PPN_ (C, S, R, D, Q) //- -//- A negative edge D-type flip-flop with positive polarity set and negative -//- polarity clock enable. +//- A positive edge D-type flip-flop with positive polarity set and negative +//- polarity reset. //- -//- Truth table: D C R E | Q +//- Truth table: C S R D | Q //- ---------+--- -//- - - 1 - | 1 -//- d \ - 0 | d +//- - - 0 - | 0 +//- - 1 - - | 1 +//- / - - d | d //- - - - - | q //- -module \$_DFFE_NP1N_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DFFSR_PPN_ (C, S, R, D, Q); +input C, S, R, D; output reg Q; -always @(negedge C or posedge R) begin - if (R == 1) +always @(posedge C, posedge S, negedge R) begin + if (R == 0) + Q <= 0; + else if (S == 1) Q <= 1; - else if (E == 0) + else Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_NP1P_ (D, C, R, E, Q) +//- $_DFFSR_PPP_ (C, S, R, D, Q) //- -//- A negative edge D-type flip-flop with positive polarity set and positive -//- polarity clock enable. +//- A positive edge D-type flip-flop with positive polarity set and reset. //- -//- Truth table: D C R E | Q +//- Truth table: C S R D | Q //- ---------+--- -//- - - 1 - | 1 -//- d \ - 1 | d +//- - - 1 - | 0 +//- - 1 - - | 1 +//- / - - d | d //- - - - - | q //- -module \$_DFFE_NP1P_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DFFSR_PPP_ (C, S, R, D, Q); +input C, S, R, D; output reg Q; -always @(negedge C or posedge R) begin +always @(posedge C, posedge S, posedge R) begin if (R == 1) + Q <= 0; + else if (S == 1) Q <= 1; - else if (E == 1) + else Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_PN0N_ (D, C, R, E, Q) +//- $_DLATCH_N_ (E, D, Q) //- -//- A positive edge D-type flip-flop with negative polarity reset and negative -//- polarity clock enable. +//- A negative enable D-type latch. //- -//- Truth table: D C R E | Q -//- ---------+--- -//- - - 0 - | 0 -//- d / - 0 | d -//- - - - - | q +//- Truth table: E D | Q +//- -----+--- +//- 0 d | d +//- - - | q //- -module \$_DFFE_PN0N_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DLATCH_N_ (E, D, Q); +input E, D; output reg Q; -always @(posedge C or negedge R) begin - if (R == 0) - Q <= 0; - else if (E == 0) +always @* begin + if (E == 0) Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_PN0P_ (D, C, R, E, Q) +//- $_DLATCH_P_ (E, D, Q) //- -//- A positive edge D-type flip-flop with negative polarity reset and positive -//- polarity clock enable. +//- A positive enable D-type latch. //- -//- Truth table: D C R E | Q -//- ---------+--- -//- - - 0 - | 0 -//- d / - 1 | d -//- - - - - | q +//- Truth table: E D | Q +//- -----+--- +//- 1 d | d +//- - - | q //- -module \$_DFFE_PN0P_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DLATCH_P_ (E, D, Q); +input E, D; output reg Q; -always @(posedge C or negedge R) begin - if (R == 0) - Q <= 0; - else if (E == 1) +always @* begin + if (E == 1) Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_PN1N_ (D, C, R, E, Q) +//- $_DLATCHSR_NNN_ (E, S, R, D, Q) //- -//- A positive edge D-type flip-flop with negative polarity set and negative -//- polarity clock enable. +//- A negative enable D-type latch with negative polarity set and reset. //- -//- Truth table: D C R E | Q +//- Truth table: E S R D | Q //- ---------+--- -//- - - 0 - | 1 -//- d / - 0 | d +//- - - 0 - | 0 +//- - 0 - - | 1 +//- 0 - - d | d //- - - - - | q //- -module \$_DFFE_PN1N_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DLATCHSR_NNN_ (E, S, R, D, Q); +input E, S, R, D; output reg Q; -always @(posedge C or negedge R) begin +always @* begin if (R == 0) + Q <= 0; + else if (S == 0) Q <= 1; else if (E == 0) Q <= D; @@ -1134,47 +1147,53 @@ endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_PN1P_ (D, C, R, E, Q) +//- $_DLATCHSR_NNP_ (E, S, R, D, Q) //- -//- A positive edge D-type flip-flop with negative polarity set and positive -//- polarity clock enable. +//- A negative enable D-type latch with negative polarity set and positive polarity +//- reset. //- -//- Truth table: D C R E | Q +//- Truth table: E S R D | Q //- ---------+--- -//- - - 0 - | 1 -//- d / - 1 | d +//- - - 1 - | 0 +//- - 0 - - | 1 +//- 0 - - d | d //- - - - - | q //- -module \$_DFFE_PN1P_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DLATCHSR_NNP_ (E, S, R, D, Q); +input E, S, R, D; output reg Q; -always @(posedge C or negedge R) begin - if (R == 0) +always @* begin + if (R == 1) + Q <= 0; + else if (S == 0) Q <= 1; - else if (E == 1) + else if (E == 0) Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_PP0N_ (D, C, R, E, Q) +//- $_DLATCHSR_NPN_ (E, S, R, D, Q) //- -//- A positive edge D-type flip-flop with positive polarity reset and negative -//- polarity clock enable. +//- A negative enable D-type latch with positive polarity set and negative polarity +//- reset. //- -//- Truth table: D C R E | Q +//- Truth table: E S R D | Q //- ---------+--- -//- - - 1 - | 0 -//- d / - 0 | d +//- - - 0 - | 0 +//- - 1 - - | 1 +//- 0 - - d | d //- - - - - | q //- -module \$_DFFE_PP0N_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DLATCHSR_NPN_ (E, S, R, D, Q); +input E, S, R, D; output reg Q; -always @(posedge C or posedge R) begin - if (R == 1) +always @* begin + if (R == 0) Q <= 0; + else if (S == 1) + Q <= 1; else if (E == 0) Q <= D; end @@ -1182,70 +1201,77 @@ endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_PP0P_ (D, C, R, E, Q) +//- $_DLATCHSR_NPP_ (E, S, R, D, Q) //- -//- A positive edge D-type flip-flop with positive polarity reset and positive -//- polarity clock enable. +//- A negative enable D-type latch with positive polarity set and reset. //- -//- Truth table: D C R E | Q +//- Truth table: E S R D | Q //- ---------+--- //- - - 1 - | 0 -//- d / - 1 | d +//- - 1 - - | 1 +//- 0 - - d | d //- - - - - | q //- -module \$_DFFE_PP0P_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DLATCHSR_NPP_ (E, S, R, D, Q); +input E, S, R, D; output reg Q; -always @(posedge C or posedge R) begin +always @* begin if (R == 1) Q <= 0; - else if (E == 1) + else if (S == 1) + Q <= 1; + else if (E == 0) Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_PP1N_ (D, C, R, E, Q) +//- $_DLATCHSR_PNN_ (E, S, R, D, Q) //- -//- A positive edge D-type flip-flop with positive polarity set and negative -//- polarity clock enable. +//- A positive enable D-type latch with negative polarity set and reset. //- -//- Truth table: D C R E | Q +//- Truth table: E S R D | Q //- ---------+--- -//- - - 1 - | 1 -//- d / - 0 | d +//- - - 0 - | 0 +//- - 0 - - | 1 +//- 1 - - d | d //- - - - - | q //- -module \$_DFFE_PP1N_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DLATCHSR_PNN_ (E, S, R, D, Q); +input E, S, R, D; output reg Q; -always @(posedge C or posedge R) begin - if (R == 1) +always @* begin + if (R == 0) + Q <= 0; + else if (S == 0) Q <= 1; - else if (E == 0) + else if (E == 1) Q <= D; end endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFE_PP1P_ (D, C, R, E, Q) +//- $_DLATCHSR_PNP_ (E, S, R, D, Q) //- -//- A positive edge D-type flip-flop with positive polarity set and positive -//- polarity clock enable. +//- A positive enable D-type latch with negative polarity set and positive polarity +//- reset. //- -//- Truth table: D C R E | Q +//- Truth table: E S R D | Q //- ---------+--- -//- - - 1 - | 1 -//- d / - 1 | d +//- - - 1 - | 0 +//- - 0 - - | 1 +//- 1 - - d | d //- - - - - | q //- -module \$_DFFE_PP1P_ (D, C, R, E, Q); -input D, C, R, E; +module \$_DLATCHSR_PNP_ (E, S, R, D, Q); +input E, S, R, D; output reg Q; -always @(posedge C or posedge R) begin +always @* begin if (R == 1) + Q <= 0; + else if (S == 0) Q <= 1; else if (E == 1) Q <= D; @@ -1254,2028 +1280,10 @@ endmodule // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- -//- $_DFFSR_NNN_ (C, S, R, D, Q) +//- $_DLATCHSR_PPN_ (E, S, R, D, Q) //- -//- A negative edge D-type flip-flop with negative polarity set and negative -//- polarity reset. -//- -//- Truth table: C S R D | Q -//- ---------+--- -//- - - 0 - | 0 -//- - 0 - - | 1 -//- \ - - d | d -//- - - - - | q -//- -module \$_DFFSR_NNN_ (C, S, R, D, Q); -input C, S, R, D; -output reg Q; -always @(negedge C, negedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 0) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSR_NNP_ (C, S, R, D, Q) -//- -//- A negative edge D-type flip-flop with negative polarity set and positive -//- polarity reset. -//- -//- Truth table: C S R D | Q -//- ---------+--- -//- - - 1 - | 0 -//- - 0 - - | 1 -//- \ - - d | d -//- - - - - | q -//- -module \$_DFFSR_NNP_ (C, S, R, D, Q); -input C, S, R, D; -output reg Q; -always @(negedge C, negedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 0) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSR_NPN_ (C, S, R, D, Q) -//- -//- A negative edge D-type flip-flop with positive polarity set and negative -//- polarity reset. -//- -//- Truth table: C S R D | Q -//- ---------+--- -//- - - 0 - | 0 -//- - 1 - - | 1 -//- \ - - d | d -//- - - - - | q -//- -module \$_DFFSR_NPN_ (C, S, R, D, Q); -input C, S, R, D; -output reg Q; -always @(negedge C, posedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 1) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSR_NPP_ (C, S, R, D, Q) -//- -//- A negative edge D-type flip-flop with positive polarity set and positive -//- polarity reset. -//- -//- Truth table: C S R D | Q -//- ---------+--- -//- - - 1 - | 0 -//- - 1 - - | 1 -//- \ - - d | d -//- - - - - | q -//- -module \$_DFFSR_NPP_ (C, S, R, D, Q); -input C, S, R, D; -output reg Q; -always @(negedge C, posedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 1) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSR_PNN_ (C, S, R, D, Q) -//- -//- A positive edge D-type flip-flop with negative polarity set and negative -//- polarity reset. -//- -//- Truth table: C S R D | Q -//- ---------+--- -//- - - 0 - | 0 -//- - 0 - - | 1 -//- / - - d | d -//- - - - - | q -//- -module \$_DFFSR_PNN_ (C, S, R, D, Q); -input C, S, R, D; -output reg Q; -always @(posedge C, negedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 0) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSR_PNP_ (C, S, R, D, Q) -//- -//- A positive edge D-type flip-flop with negative polarity set and positive -//- polarity reset. -//- -//- Truth table: C S R D | Q -//- ---------+--- -//- - - 1 - | 0 -//- - 0 - - | 1 -//- / - - d | d -//- - - - - | q -//- -module \$_DFFSR_PNP_ (C, S, R, D, Q); -input C, S, R, D; -output reg Q; -always @(posedge C, negedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 0) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSR_PPN_ (C, S, R, D, Q) -//- -//- A positive edge D-type flip-flop with positive polarity set and negative -//- polarity reset. -//- -//- Truth table: C S R D | Q -//- ---------+--- -//- - - 0 - | 0 -//- - 1 - - | 1 -//- / - - d | d -//- - - - - | q -//- -module \$_DFFSR_PPN_ (C, S, R, D, Q); -input C, S, R, D; -output reg Q; -always @(posedge C, posedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 1) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSR_PPP_ (C, S, R, D, Q) -//- -//- A positive edge D-type flip-flop with positive polarity set and positive -//- polarity reset. -//- -//- Truth table: C S R D | Q -//- ---------+--- -//- - - 1 - | 0 -//- - 1 - - | 1 -//- / - - d | d -//- - - - - | q -//- -module \$_DFFSR_PPP_ (C, S, R, D, Q); -input C, S, R, D; -output reg Q; -always @(posedge C, posedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 1) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_NNNN_ (C, S, R, E, D, Q) -//- -//- A negative edge D-type flip-flop with negative polarity set, negative -//- polarity reset and negative polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 0 - - | 0 -//- - 0 - - - | 1 -//- \ - - 0 d | d -//- - - - - - | q -//- -module \$_DFFSRE_NNNN_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(negedge C, negedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_NNNP_ (C, S, R, E, D, Q) -//- -//- A negative edge D-type flip-flop with negative polarity set, negative -//- polarity reset and positive polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 0 - - | 0 -//- - 0 - - - | 1 -//- \ - - 1 d | d -//- - - - - - | q -//- -module \$_DFFSRE_NNNP_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(negedge C, negedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_NNPN_ (C, S, R, E, D, Q) -//- -//- A negative edge D-type flip-flop with negative polarity set, positive -//- polarity reset and negative polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 1 - - | 0 -//- - 0 - - - | 1 -//- \ - - 0 d | d -//- - - - - - | q -//- -module \$_DFFSRE_NNPN_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(negedge C, negedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_NNPP_ (C, S, R, E, D, Q) -//- -//- A negative edge D-type flip-flop with negative polarity set, positive -//- polarity reset and positive polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 1 - - | 0 -//- - 0 - - - | 1 -//- \ - - 1 d | d -//- - - - - - | q -//- -module \$_DFFSRE_NNPP_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(negedge C, negedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_NPNN_ (C, S, R, E, D, Q) -//- -//- A negative edge D-type flip-flop with positive polarity set, negative -//- polarity reset and negative polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 0 - - | 0 -//- - 1 - - - | 1 -//- \ - - 0 d | d -//- - - - - - | q -//- -module \$_DFFSRE_NPNN_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(negedge C, posedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_NPNP_ (C, S, R, E, D, Q) -//- -//- A negative edge D-type flip-flop with positive polarity set, negative -//- polarity reset and positive polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 0 - - | 0 -//- - 1 - - - | 1 -//- \ - - 1 d | d -//- - - - - - | q -//- -module \$_DFFSRE_NPNP_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(negedge C, posedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_NPPN_ (C, S, R, E, D, Q) -//- -//- A negative edge D-type flip-flop with positive polarity set, positive -//- polarity reset and negative polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 1 - - | 0 -//- - 1 - - - | 1 -//- \ - - 0 d | d -//- - - - - - | q -//- -module \$_DFFSRE_NPPN_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(negedge C, posedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_NPPP_ (C, S, R, E, D, Q) -//- -//- A negative edge D-type flip-flop with positive polarity set, positive -//- polarity reset and positive polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 1 - - | 0 -//- - 1 - - - | 1 -//- \ - - 1 d | d -//- - - - - - | q -//- -module \$_DFFSRE_NPPP_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(negedge C, posedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_PNNN_ (C, S, R, E, D, Q) -//- -//- A positive edge D-type flip-flop with negative polarity set, negative -//- polarity reset and negative polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 0 - - | 0 -//- - 0 - - - | 1 -//- / - - 0 d | d -//- - - - - - | q -//- -module \$_DFFSRE_PNNN_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(posedge C, negedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_PNNP_ (C, S, R, E, D, Q) -//- -//- A positive edge D-type flip-flop with negative polarity set, negative -//- polarity reset and positive polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 0 - - | 0 -//- - 0 - - - | 1 -//- / - - 1 d | d -//- - - - - - | q -//- -module \$_DFFSRE_PNNP_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(posedge C, negedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_PNPN_ (C, S, R, E, D, Q) -//- -//- A positive edge D-type flip-flop with negative polarity set, positive -//- polarity reset and negative polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 1 - - | 0 -//- - 0 - - - | 1 -//- / - - 0 d | d -//- - - - - - | q -//- -module \$_DFFSRE_PNPN_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(posedge C, negedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_PNPP_ (C, S, R, E, D, Q) -//- -//- A positive edge D-type flip-flop with negative polarity set, positive -//- polarity reset and positive polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 1 - - | 0 -//- - 0 - - - | 1 -//- / - - 1 d | d -//- - - - - - | q -//- -module \$_DFFSRE_PNPP_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(posedge C, negedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_PPNN_ (C, S, R, E, D, Q) -//- -//- A positive edge D-type flip-flop with positive polarity set, negative -//- polarity reset and negative polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 0 - - | 0 -//- - 1 - - - | 1 -//- / - - 0 d | d -//- - - - - - | q -//- -module \$_DFFSRE_PPNN_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(posedge C, posedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_PPNP_ (C, S, R, E, D, Q) -//- -//- A positive edge D-type flip-flop with positive polarity set, negative -//- polarity reset and positive polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 0 - - | 0 -//- - 1 - - - | 1 -//- / - - 1 d | d -//- - - - - - | q -//- -module \$_DFFSRE_PPNP_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(posedge C, posedge S, negedge R) begin - if (R == 0) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_PPPN_ (C, S, R, E, D, Q) -//- -//- A positive edge D-type flip-flop with positive polarity set, positive -//- polarity reset and negative polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 1 - - | 0 -//- - 1 - - - | 1 -//- / - - 0 d | d -//- - - - - - | q -//- -module \$_DFFSRE_PPPN_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(posedge C, posedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DFFSRE_PPPP_ (C, S, R, E, D, Q) -//- -//- A positive edge D-type flip-flop with positive polarity set, positive -//- polarity reset and positive polarity clock enable. -//- -//- Truth table: C S R E D | Q -//- -----------+--- -//- - - 1 - - | 0 -//- - 1 - - - | 1 -//- / - - 1 d | d -//- - - - - - | q -//- -module \$_DFFSRE_PPPP_ (C, S, R, E, D, Q); -input C, S, R, E, D; -output reg Q; -always @(posedge C, posedge S, posedge R) begin - if (R == 1) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFF_NN0_ (D, C, R, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous reset. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - \ 0 | 0 -//- d \ - | d -//- - - - | q -//- -module \$_SDFF_NN0_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @(negedge C) begin - if (R == 0) - Q <= 0; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFF_NN1_ (D, C, R, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous set. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - \ 0 | 1 -//- d \ - | d -//- - - - | q -//- -module \$_SDFF_NN1_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @(negedge C) begin - if (R == 0) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFF_NP0_ (D, C, R, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous reset. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - \ 1 | 0 -//- d \ - | d -//- - - - | q -//- -module \$_SDFF_NP0_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @(negedge C) begin - if (R == 1) - Q <= 0; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFF_NP1_ (D, C, R, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous set. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - \ 1 | 1 -//- d \ - | d -//- - - - | q -//- -module \$_SDFF_NP1_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @(negedge C) begin - if (R == 1) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFF_PN0_ (D, C, R, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous reset. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - / 0 | 0 -//- d / - | d -//- - - - | q -//- -module \$_SDFF_PN0_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @(posedge C) begin - if (R == 0) - Q <= 0; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFF_PN1_ (D, C, R, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous set. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - / 0 | 1 -//- d / - | d -//- - - - | q -//- -module \$_SDFF_PN1_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @(posedge C) begin - if (R == 0) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFF_PP0_ (D, C, R, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous reset. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - / 1 | 0 -//- d / - | d -//- - - - | q -//- -module \$_SDFF_PP0_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @(posedge C) begin - if (R == 1) - Q <= 0; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFF_PP1_ (D, C, R, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous set. -//- -//- Truth table: D C R | Q -//- -------+--- -//- - / 1 | 1 -//- d / - | d -//- - - - | q -//- -module \$_SDFF_PP1_ (D, C, R, Q); -input D, C, R; -output reg Q; -always @(posedge C) begin - if (R == 1) - Q <= 1; - else - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_NN0N_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous reset and negative -//- polarity clock enable (with reset having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 0 - | 0 -//- d \ - 0 | d -//- - - - - | q -//- -module \$_SDFFE_NN0N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (R == 0) - Q <= 0; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_NN0P_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous reset and positive -//- polarity clock enable (with reset having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 0 - | 0 -//- d \ - 1 | d -//- - - - - | q -//- -module \$_SDFFE_NN0P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (R == 0) - Q <= 0; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_NN1N_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous set and negative -//- polarity clock enable (with set having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 0 - | 1 -//- d \ - 0 | d -//- - - - - | q -//- -module \$_SDFFE_NN1N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (R == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_NN1P_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous set and positive -//- polarity clock enable (with set having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 0 - | 1 -//- d \ - 1 | d -//- - - - - | q -//- -module \$_SDFFE_NN1P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (R == 0) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_NP0N_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous reset and negative -//- polarity clock enable (with reset having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 1 - | 0 -//- d \ - 0 | d -//- - - - - | q -//- -module \$_SDFFE_NP0N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (R == 1) - Q <= 0; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_NP0P_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous reset and positive -//- polarity clock enable (with reset having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 1 - | 0 -//- d \ - 1 | d -//- - - - - | q -//- -module \$_SDFFE_NP0P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (R == 1) - Q <= 0; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_NP1N_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous set and negative -//- polarity clock enable (with set having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 1 - | 1 -//- d \ - 0 | d -//- - - - - | q -//- -module \$_SDFFE_NP1N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (R == 1) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_NP1P_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous set and positive -//- polarity clock enable (with set having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 1 - | 1 -//- d \ - 1 | d -//- - - - - | q -//- -module \$_SDFFE_NP1P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (R == 1) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_PN0N_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous reset and negative -//- polarity clock enable (with reset having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 0 - | 0 -//- d / - 0 | d -//- - - - - | q -//- -module \$_SDFFE_PN0N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (R == 0) - Q <= 0; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_PN0P_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous reset and positive -//- polarity clock enable (with reset having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 0 - | 0 -//- d / - 1 | d -//- - - - - | q -//- -module \$_SDFFE_PN0P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (R == 0) - Q <= 0; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_PN1N_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous set and negative -//- polarity clock enable (with set having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 0 - | 1 -//- d / - 0 | d -//- - - - - | q -//- -module \$_SDFFE_PN1N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (R == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_PN1P_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous set and positive -//- polarity clock enable (with set having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 0 - | 1 -//- d / - 1 | d -//- - - - - | q -//- -module \$_SDFFE_PN1P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (R == 0) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_PP0N_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous reset and negative -//- polarity clock enable (with reset having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 1 - | 0 -//- d / - 0 | d -//- - - - - | q -//- -module \$_SDFFE_PP0N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (R == 1) - Q <= 0; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_PP0P_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous reset and positive -//- polarity clock enable (with reset having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 1 - | 0 -//- d / - 1 | d -//- - - - - | q -//- -module \$_SDFFE_PP0P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (R == 1) - Q <= 0; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_PP1N_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous set and negative -//- polarity clock enable (with set having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 1 - | 1 -//- d / - 0 | d -//- - - - - | q -//- -module \$_SDFFE_PP1N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (R == 1) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFE_PP1P_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous set and positive -//- polarity clock enable (with set having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 1 - | 1 -//- d / - 1 | d -//- - - - - | q -//- -module \$_SDFFE_PP1P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (R == 1) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_NN0N_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous reset and negative -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 0 0 | 0 -//- d \ - 0 | d -//- - - - - | q -//- -module \$_SDFFCE_NN0N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (E == 0) begin - if (R == 0) - Q <= 0; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_NN0P_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous reset and positive -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 0 1 | 0 -//- d \ - 1 | d -//- - - - - | q -//- -module \$_SDFFCE_NN0P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (E == 1) begin - if (R == 0) - Q <= 0; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_NN1N_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous set and negative -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 0 0 | 1 -//- d \ - 0 | d -//- - - - - | q -//- -module \$_SDFFCE_NN1N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (E == 0) begin - if (R == 0) - Q <= 1; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_NN1P_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with negative polarity synchronous set and positive -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 0 1 | 1 -//- d \ - 1 | d -//- - - - - | q -//- -module \$_SDFFCE_NN1P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (E == 1) begin - if (R == 0) - Q <= 1; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_NP0N_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous reset and negative -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 1 0 | 0 -//- d \ - 0 | d -//- - - - - | q -//- -module \$_SDFFCE_NP0N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (E == 0) begin - if (R == 1) - Q <= 0; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_NP0P_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous reset and positive -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 1 1 | 0 -//- d \ - 1 | d -//- - - - - | q -//- -module \$_SDFFCE_NP0P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (E == 1) begin - if (R == 1) - Q <= 0; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_NP1N_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous set and negative -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 1 0 | 1 -//- d \ - 0 | d -//- - - - - | q -//- -module \$_SDFFCE_NP1N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (E == 0) begin - if (R == 1) - Q <= 1; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_NP1P_ (D, C, R, E, Q) -//- -//- A negative edge D-type flip-flop with positive polarity synchronous set and positive -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - \ 1 1 | 1 -//- d \ - 1 | d -//- - - - - | q -//- -module \$_SDFFCE_NP1P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(negedge C) begin - if (E == 1) begin - if (R == 1) - Q <= 1; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_PN0N_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous reset and negative -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 0 0 | 0 -//- d / - 0 | d -//- - - - - | q -//- -module \$_SDFFCE_PN0N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (E == 0) begin - if (R == 0) - Q <= 0; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_PN0P_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous reset and positive -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 0 1 | 0 -//- d / - 1 | d -//- - - - - | q -//- -module \$_SDFFCE_PN0P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (E == 1) begin - if (R == 0) - Q <= 0; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_PN1N_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous set and negative -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 0 0 | 1 -//- d / - 0 | d -//- - - - - | q -//- -module \$_SDFFCE_PN1N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (E == 0) begin - if (R == 0) - Q <= 1; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_PN1P_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with negative polarity synchronous set and positive -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 0 1 | 1 -//- d / - 1 | d -//- - - - - | q -//- -module \$_SDFFCE_PN1P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (E == 1) begin - if (R == 0) - Q <= 1; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_PP0N_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous reset and negative -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 1 0 | 0 -//- d / - 0 | d -//- - - - - | q -//- -module \$_SDFFCE_PP0N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (E == 0) begin - if (R == 1) - Q <= 0; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_PP0P_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous reset and positive -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 1 1 | 0 -//- d / - 1 | d -//- - - - - | q -//- -module \$_SDFFCE_PP0P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (E == 1) begin - if (R == 1) - Q <= 0; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_PP1N_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous set and negative -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 1 0 | 1 -//- d / - 0 | d -//- - - - - | q -//- -module \$_SDFFCE_PP1N_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (E == 0) begin - if (R == 1) - Q <= 1; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_SDFFCE_PP1P_ (D, C, R, E, Q) -//- -//- A positive edge D-type flip-flop with positive polarity synchronous set and positive -//- polarity clock enable (with clock enable having priority). -//- -//- Truth table: D C R E | Q -//- ---------+--- -//- - / 1 1 | 1 -//- d / - 1 | d -//- - - - - | q -//- -module \$_SDFFCE_PP1P_ (D, C, R, E, Q); -input D, C, R, E; -output reg Q; -always @(posedge C) begin - if (E == 1) begin - if (R == 1) - Q <= 1; - else - Q <= D; - end -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_N_ (E, D, Q) -//- -//- A negative enable D-type latch. -//- -//- Truth table: E D | Q -//- -----+--- -//- 0 d | d -//- - - | q -//- -module \$_DLATCH_N_ (E, D, Q); -input E, D; -output reg Q; -always @* begin - if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_P_ (E, D, Q) -//- -//- A positive enable D-type latch. -//- -//- Truth table: E D | Q -//- -----+--- -//- 1 d | d -//- - - | q -//- -module \$_DLATCH_P_ (E, D, Q); -input E, D; -output reg Q; -always @* begin - if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_NN0_ (E, R, D, Q) -//- -//- A negative enable D-type latch with negative polarity reset. -//- -//- Truth table: E R D | Q -//- -------+--- -//- - 0 - | 0 -//- 0 - d | d -//- - - - | q -//- -module \$_DLATCH_NN0_ (E, R, D, Q); -input E, R, D; -output reg Q; -always @* begin - if (R == 0) - Q <= 0; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_NN1_ (E, R, D, Q) -//- -//- A negative enable D-type latch with negative polarity set. -//- -//- Truth table: E R D | Q -//- -------+--- -//- - 0 - | 1 -//- 0 - d | d -//- - - - | q -//- -module \$_DLATCH_NN1_ (E, R, D, Q); -input E, R, D; -output reg Q; -always @* begin - if (R == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_NP0_ (E, R, D, Q) -//- -//- A negative enable D-type latch with positive polarity reset. -//- -//- Truth table: E R D | Q -//- -------+--- -//- - 1 - | 0 -//- 0 - d | d -//- - - - | q -//- -module \$_DLATCH_NP0_ (E, R, D, Q); -input E, R, D; -output reg Q; -always @* begin - if (R == 0) - Q <= 0; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_NP1_ (E, R, D, Q) -//- -//- A negative enable D-type latch with positive polarity set. -//- -//- Truth table: E R D | Q -//- -------+--- -//- - 1 - | 1 -//- 0 - d | d -//- - - - | q -//- -module \$_DLATCH_NP1_ (E, R, D, Q); -input E, R, D; -output reg Q; -always @* begin - if (R == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_PN0_ (E, R, D, Q) -//- -//- A positive enable D-type latch with negative polarity reset. -//- -//- Truth table: E R D | Q -//- -------+--- -//- - 0 - | 0 -//- 1 - d | d -//- - - - | q -//- -module \$_DLATCH_PN0_ (E, R, D, Q); -input E, R, D; -output reg Q; -always @* begin - if (R == 1) - Q <= 0; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_PN1_ (E, R, D, Q) -//- -//- A positive enable D-type latch with negative polarity set. -//- -//- Truth table: E R D | Q -//- -------+--- -//- - 0 - | 1 -//- 1 - d | d -//- - - - | q -//- -module \$_DLATCH_PN1_ (E, R, D, Q); -input E, R, D; -output reg Q; -always @* begin - if (R == 1) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_PP0_ (E, R, D, Q) -//- -//- A positive enable D-type latch with positive polarity reset. -//- -//- Truth table: E R D | Q -//- -------+--- -//- - 1 - | 0 -//- 1 - d | d -//- - - - | q -//- -module \$_DLATCH_PP0_ (E, R, D, Q); -input E, R, D; -output reg Q; -always @* begin - if (R == 1) - Q <= 0; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCH_PP1_ (E, R, D, Q) -//- -//- A positive enable D-type latch with positive polarity set. -//- -//- Truth table: E R D | Q -//- -------+--- -//- - 1 - | 1 -//- 1 - d | d -//- - - - | q -//- -module \$_DLATCH_PP1_ (E, R, D, Q); -input E, R, D; -output reg Q; -always @* begin - if (R == 1) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCHSR_NNN_ (E, S, R, D, Q) -//- -//- A negative enable D-type latch with negative polarity set and negative -//- polarity reset. -//- -//- Truth table: E S R D | Q -//- ---------+--- -//- - - 0 - | 0 -//- - 0 - - | 1 -//- 0 - - d | d -//- - - - - | q -//- -module \$_DLATCHSR_NNN_ (E, S, R, D, Q); -input E, S, R, D; -output reg Q; -always @* begin - if (R == 0) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCHSR_NNP_ (E, S, R, D, Q) -//- -//- A negative enable D-type latch with negative polarity set and positive -//- polarity reset. -//- -//- Truth table: E S R D | Q -//- ---------+--- -//- - - 1 - | 0 -//- - 0 - - | 1 -//- 0 - - d | d -//- - - - - | q -//- -module \$_DLATCHSR_NNP_ (E, S, R, D, Q); -input E, S, R, D; -output reg Q; -always @* begin - if (R == 1) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCHSR_NPN_ (E, S, R, D, Q) -//- -//- A negative enable D-type latch with positive polarity set and negative -//- polarity reset. -//- -//- Truth table: E S R D | Q -//- ---------+--- -//- - - 0 - | 0 -//- - 1 - - | 1 -//- 0 - - d | d -//- - - - - | q -//- -module \$_DLATCHSR_NPN_ (E, S, R, D, Q); -input E, S, R, D; -output reg Q; -always @* begin - if (R == 0) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCHSR_NPP_ (E, S, R, D, Q) -//- -//- A negative enable D-type latch with positive polarity set and positive -//- polarity reset. -//- -//- Truth table: E S R D | Q -//- ---------+--- -//- - - 1 - | 0 -//- - 1 - - | 1 -//- 0 - - d | d -//- - - - - | q -//- -module \$_DLATCHSR_NPP_ (E, S, R, D, Q); -input E, S, R, D; -output reg Q; -always @* begin - if (R == 1) - Q <= 0; - else if (S == 1) - Q <= 1; - else if (E == 0) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCHSR_PNN_ (E, S, R, D, Q) -//- -//- A positive enable D-type latch with negative polarity set and negative -//- polarity reset. -//- -//- Truth table: E S R D | Q -//- ---------+--- -//- - - 0 - | 0 -//- - 0 - - | 1 -//- 1 - - d | d -//- - - - - | q -//- -module \$_DLATCHSR_PNN_ (E, S, R, D, Q); -input E, S, R, D; -output reg Q; -always @* begin - if (R == 0) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCHSR_PNP_ (E, S, R, D, Q) -//- -//- A positive enable D-type latch with negative polarity set and positive -//- polarity reset. -//- -//- Truth table: E S R D | Q -//- ---------+--- -//- - - 1 - | 0 -//- - 0 - - | 1 -//- 1 - - d | d -//- - - - - | q -//- -module \$_DLATCHSR_PNP_ (E, S, R, D, Q); -input E, S, R, D; -output reg Q; -always @* begin - if (R == 1) - Q <= 0; - else if (S == 0) - Q <= 1; - else if (E == 1) - Q <= D; -end -endmodule - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $_DLATCHSR_PPN_ (E, S, R, D, Q) -//- -//- A positive enable D-type latch with positive polarity set and negative -//- polarity reset. +//- A positive enable D-type latch with positive polarity set and negative polarity +//- reset. //- //- Truth table: E S R D | Q //- ---------+--- @@ -3301,8 +1309,7 @@ endmodule //- //- $_DLATCHSR_PPP_ (E, S, R, D, Q) //- -//- A positive enable D-type latch with positive polarity set and positive -//- polarity reset. +//- A positive enable D-type latch with positive polarity set and reset. //- //- Truth table: E S R D | Q //- ---------+--- @@ -3323,3 +1330,4 @@ always @* begin Q <= D; end endmodule + diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 2660e6f152f..7845a3fed14 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -997,12 +997,6 @@ endmodule // -------------------------------------------------------- -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $div (A, B, Y) -//- -//- Division with truncated result (rounded towards 0). -//- module \$div (A, B, Y); parameter A_SIGNED = 0; @@ -1027,14 +1021,6 @@ endmodule // -------------------------------------------------------- -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $mod (A, B, Y) -//- -//- Modulo/remainder of division with truncated result (rounded towards 0). -//- -//- Invariant: $div(A, B) * B + $mod(A, B) == A -//- module \$mod (A, B, Y); parameter A_SIGNED = 0; @@ -1057,83 +1043,6 @@ endgenerate endmodule -// -------------------------------------------------------- - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $divfloor (A, B, Y) -//- -//- Division with floored result (rounded towards negative infinity). -//- -module \$divfloor (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 0; -parameter B_WIDTH = 0; -parameter Y_WIDTH = 0; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -generate - if (A_SIGNED && B_SIGNED) begin:BLOCK1 - localparam WIDTH = - A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : - B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; - wire [WIDTH:0] A_buf, B_buf, N_buf; - assign A_buf = $signed(A); - assign B_buf = $signed(B); - assign N_buf = (A[A_WIDTH-1] == B[B_WIDTH-1]) || A == 0 ? A_buf : $signed(A_buf - (B[B_WIDTH-1] ? B_buf+1 : B_buf-1)); - assign Y = $signed(N_buf) / $signed(B_buf); - end else begin:BLOCK2 - assign Y = A / B; - end -endgenerate - -endmodule - -// -------------------------------------------------------- - -// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -//- -//- $modfloor (A, B, Y) -//- -//- Modulo/remainder of division with floored result (rounded towards negative infinity). -//- -//- Invariant: $divfloor(A, B) * B + $modfloor(A, B) == A -//- -module \$modfloor (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 0; -parameter B_WIDTH = 0; -parameter Y_WIDTH = 0; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -generate - if (A_SIGNED && B_SIGNED) begin:BLOCK1 - localparam WIDTH = B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; - wire [WIDTH-1:0] B_buf, Y_trunc; - assign B_buf = $signed(B); - assign Y_trunc = $signed(A) % $signed(B); - // flooring mod is the same as truncating mod for positive division results (A and B have - // the same sign), as well as when there's no remainder. - // For all other cases, they behave as `floor - trunc = B` - assign Y = (A[A_WIDTH-1] == B[B_WIDTH-1]) || Y_trunc == 0 ? Y_trunc : $signed(B_buf) + $signed(Y_trunc); - end else begin:BLOCK2 - // no difference between truncating and flooring for unsigned - assign Y = A % B; - end -endgenerate - -endmodule - // -------------------------------------------------------- `ifndef SIMLIB_NOPOW @@ -1724,7 +1633,7 @@ wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; genvar i; generate for (i = 0; i < WIDTH; i = i+1) begin:bitslices - always @* + always @(posedge pos_set[i], posedge pos_clr[i]) if (pos_clr[i]) Q[i] <= 0; else if (pos_set[i]) @@ -1822,39 +1731,6 @@ endgenerate endmodule -// -------------------------------------------------------- - -module \$dffsre (CLK, SET, CLR, EN, D, Q); - -parameter WIDTH = 0; -parameter CLK_POLARITY = 1'b1; -parameter SET_POLARITY = 1'b1; -parameter CLR_POLARITY = 1'b1; -parameter EN_POLARITY = 1'b1; - -input CLK, EN; -input [WIDTH-1:0] SET, CLR, D; -output reg [WIDTH-1:0] Q; - -wire pos_clk = CLK == CLK_POLARITY; -wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET; -wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; - -genvar i; -generate - for (i = 0; i < WIDTH; i = i+1) begin:bitslices - always @(posedge pos_set[i], posedge pos_clr[i], posedge pos_clk) - if (pos_clr[i]) - Q[i] <= 0; - else if (pos_set[i]) - Q[i] <= 1; - else if (EN == EN_POLARITY) - Q[i] <= D[i]; - end -endgenerate - -endmodule - `endif // -------------------------------------------------------- @@ -1882,107 +1758,6 @@ endmodule // -------------------------------------------------------- -module \$sdff (CLK, SRST, D, Q); - -parameter WIDTH = 0; -parameter CLK_POLARITY = 1'b1; -parameter SRST_POLARITY = 1'b1; -parameter SRST_VALUE = 0; - -input CLK, SRST; -input [WIDTH-1:0] D; -output reg [WIDTH-1:0] Q; -wire pos_clk = CLK == CLK_POLARITY; -wire pos_srst = SRST == SRST_POLARITY; - -always @(posedge pos_clk) begin - if (pos_srst) - Q <= SRST_VALUE; - else - Q <= D; -end - -endmodule - -// -------------------------------------------------------- - -module \$adffe (CLK, ARST, EN, D, Q); - -parameter WIDTH = 0; -parameter CLK_POLARITY = 1'b1; -parameter EN_POLARITY = 1'b1; -parameter ARST_POLARITY = 1'b1; -parameter ARST_VALUE = 0; - -input CLK, ARST, EN; -input [WIDTH-1:0] D; -output reg [WIDTH-1:0] Q; -wire pos_clk = CLK == CLK_POLARITY; -wire pos_arst = ARST == ARST_POLARITY; - -always @(posedge pos_clk, posedge pos_arst) begin - if (pos_arst) - Q <= ARST_VALUE; - else if (EN == EN_POLARITY) - Q <= D; -end - -endmodule - -// -------------------------------------------------------- - -module \$sdffe (CLK, SRST, EN, D, Q); - -parameter WIDTH = 0; -parameter CLK_POLARITY = 1'b1; -parameter EN_POLARITY = 1'b1; -parameter SRST_POLARITY = 1'b1; -parameter SRST_VALUE = 0; - -input CLK, SRST, EN; -input [WIDTH-1:0] D; -output reg [WIDTH-1:0] Q; -wire pos_clk = CLK == CLK_POLARITY; -wire pos_srst = SRST == SRST_POLARITY; - -always @(posedge pos_clk) begin - if (pos_srst) - Q <= SRST_VALUE; - else if (EN == EN_POLARITY) - Q <= D; -end - -endmodule - -// -------------------------------------------------------- - -module \$sdffce (CLK, SRST, EN, D, Q); - -parameter WIDTH = 0; -parameter CLK_POLARITY = 1'b1; -parameter EN_POLARITY = 1'b1; -parameter SRST_POLARITY = 1'b1; -parameter SRST_VALUE = 0; - -input CLK, SRST, EN; -input [WIDTH-1:0] D; -output reg [WIDTH-1:0] Q; -wire pos_clk = CLK == CLK_POLARITY; -wire pos_srst = SRST == SRST_POLARITY; - -always @(posedge pos_clk) begin - if (EN == EN_POLARITY) begin - if (pos_srst) - Q <= SRST_VALUE; - else - Q <= D; - end -end - -endmodule - -// -------------------------------------------------------- - module \$dlatch (EN, D, Q); parameter WIDTH = 0; @@ -1999,28 +1774,6 @@ end endmodule -// -------------------------------------------------------- - -module \$adlatch (EN, ARST, D, Q); - -parameter WIDTH = 0; -parameter EN_POLARITY = 1'b1; -parameter ARST_POLARITY = 1'b1; -parameter ARST_VALUE = 0; - -input EN, ARST; -input [WIDTH-1:0] D; -output reg [WIDTH-1:0] Q; - -always @* begin - if (ARST == ARST_POLARITY) - Q = ARST_VALUE; - else if (EN == EN_POLARITY) - Q = D; -end - -endmodule - // -------------------------------------------------------- `ifndef SIMLIB_NOSR diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index b4c65e658b2..a176357a722 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -29,7 +29,7 @@ struct SynthPass : public ScriptPass { SynthPass() : ScriptPass("synth", "generic synthesis script") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -78,9 +78,6 @@ struct SynthPass : public ScriptPass log(" -abc9\n"); log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); - log(" -flowmap\n"); - log(" use FlowMap LUT techmapping instead of ABC\n"); - log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -88,10 +85,10 @@ struct SynthPass : public ScriptPass } string top_module, fsm_opts, memory_opts, abc; - bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap; + bool autotop, flatten, noalumacc, nofsm, noabc, noshare; int lut; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_module.clear(); fsm_opts.clear(); @@ -104,11 +101,10 @@ struct SynthPass : public ScriptPass nofsm = false; noabc = false; noshare = false; - flowmap = false; abc = "abc"; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -171,10 +167,6 @@ struct SynthPass : public ScriptPass abc = "abc9"; continue; } - if (args[argidx] == "-flowmap") { - flowmap = true; - continue; - } break; } extra_args(args, argidx, design); @@ -184,8 +176,6 @@ struct SynthPass : public ScriptPass if (abc == "abc9" && !lut) log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)\n"); - if (flowmap && !lut) - log_cmd_error("FlowMap is only supported for FPGA synthesis (using '-lut' option)\n"); log_header(design, "Executing SYNTH pass.\n"); log_push(); @@ -195,7 +185,7 @@ struct SynthPass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { @@ -225,9 +215,9 @@ struct SynthPass : public ScriptPass run("peepopt"); run("opt_clean"); if (help_mode) - run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)"); - else if (lut) - run(stringf("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", lut)); + run("techmap -map +/cmp2lut.v", " (if -lut)"); + else + run(stringf("techmap -map +/cmp2lut.v -D LUT_WIDTH=%d", lut)); if (!noalumacc) run("alumacc", " (unless -noalumacc)"); if (!noshare) @@ -250,20 +240,15 @@ struct SynthPass : public ScriptPass { run("techmap -map +/gate2lut.v", "(if -noabc and -lut)"); run("clean; opt_lut", " (if -noabc and -lut)"); - run("flowmap -maxlut K", " (if -flowmap and -lut)"); } else if (noabc && lut) { run(stringf("techmap -map +/gate2lut.v -D LUT_WIDTH=%d", lut)); run("clean; opt_lut"); } - else if (flowmap) - { - run(stringf("flowmap -maxlut %d", lut)); - } run("opt -fast"); - if (!noabc && !flowmap) { + if (!noabc) { #ifdef YOSYS_ENABLE_ABC if (help_mode) { diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 9607302b70d..d7ec3947eb8 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -64,7 +64,7 @@ module _90_simplemap_various; endmodule (* techmap_simplemap *) -(* techmap_celltype = "$sr $ff $dff $dffe $adff $adffe $sdff $sdffe $sdffce $dffsr $dffsre $dlatch $adlatch $dlatchsr" *) +(* techmap_celltype = "$sr $ff $dff $dffe $adff $dffsr $dlatch" *) module _90_simplemap_registers; endmodule @@ -85,11 +85,8 @@ module _90_shift_ops_shr_shl_sshl_sshr (A, B, Y); localparam shift_left = _TECHMAP_CELLTYPE_ == "$shl" || _TECHMAP_CELLTYPE_ == "$sshl"; localparam sign_extend = A_SIGNED && _TECHMAP_CELLTYPE_ == "$sshr"; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH); @@ -99,7 +96,6 @@ module _90_shift_ops_shr_shl_sshl_sshr (A, B, Y); wire [1023:0] _TECHMAP_DO_01_ = "RECURSION; CONSTMAP; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;"; integer i; - (* force_downto *) reg [WIDTH-1:0] buffer; reg overflow; @@ -129,90 +125,51 @@ module _90_shift_shiftx (A, B, Y); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; - parameter _TECHMAP_CELLTYPE_ = ""; - parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; - parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH); + localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0); + parameter _TECHMAP_CELLTYPE_ = ""; localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx; - generate -`ifndef NO_LSB_FIRST_SHIFT_SHIFTX - // If $shift/$shiftx only shifts in units of Y_WIDTH - // (a common pattern created by pmux2shiftx) - // which is checked by ensuring that all that - // the appropriate LSBs of B are constant zero, - // then we can decompose LSB first instead of - // MSB first - localparam CLOG2_Y_WIDTH = $clog2(Y_WIDTH); - if (B_WIDTH > CLOG2_Y_WIDTH+1 && - _TECHMAP_CONSTMSK_B_[CLOG2_Y_WIDTH-1:0] == {CLOG2_Y_WIDTH{1'b1}} && - _TECHMAP_CONSTVAL_B_[CLOG2_Y_WIDTH-1:0] == {CLOG2_Y_WIDTH{1'b0}}) begin - // Halve the size of $shift/$shiftx by $mux-ing A according to - // the LSB of B, after discarding the zeroed bits - localparam Y_WIDTH2 = 2**CLOG2_Y_WIDTH; - localparam entries = (A_WIDTH+Y_WIDTH-1)/Y_WIDTH2; - localparam len = Y_WIDTH2 * ((entries+1)/2); - wire [len-1:0] AA; - wire [(A_WIDTH+Y_WIDTH2+Y_WIDTH-1)-1:0] Apad = {{(Y_WIDTH2+Y_WIDTH-1){extbit}}, A}; - genvar i; - for (i = 0; i < A_WIDTH; i=i+Y_WIDTH2*2) - assign AA[i/2 +: Y_WIDTH2] = B[CLOG2_Y_WIDTH] ? Apad[i+Y_WIDTH2 +: Y_WIDTH2] : Apad[i +: Y_WIDTH2]; - wire [B_WIDTH-2:0] BB = {B[B_WIDTH-1:CLOG2_Y_WIDTH+1], {CLOG2_Y_WIDTH{1'b0}}}; - if (_TECHMAP_CELLTYPE_ == "$shift") - $shift #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(len), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y)); - else - $shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(len), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y)); - end - else -`endif - begin - localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH); - localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0); - - wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; - wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;"; + wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; + wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;"; - integer i; - (* force_downto *) - reg [WIDTH-1:0] buffer; - reg overflow; + integer i; + reg [WIDTH-1:0] buffer; + reg overflow; - always @* begin - overflow = 0; + always @* begin + overflow = 0; + buffer = {WIDTH{extbit}}; + buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A; + + if (B_WIDTH > BB_WIDTH) begin + if (B_SIGNED) begin + for (i = BB_WIDTH; i < B_WIDTH; i = i+1) + if (B[i] != B[BB_WIDTH-1]) + overflow = 1; + end else + overflow = |B[B_WIDTH-1:BB_WIDTH]; + if (overflow) buffer = {WIDTH{extbit}}; - buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A; - - if (B_WIDTH > BB_WIDTH) begin - if (B_SIGNED) begin - for (i = BB_WIDTH; i < B_WIDTH; i = i+1) - if (B[i] != B[BB_WIDTH-1]) - overflow = 1; - end else - overflow = |B[B_WIDTH-1:BB_WIDTH]; - if (overflow) - buffer = {WIDTH{extbit}}; - end - - for (i = BB_WIDTH-1; i >= 0; i = i-1) - if (B[i]) begin - if (B_SIGNED && i == BB_WIDTH-1) - buffer = {buffer, {2**i{extbit}}}; - else if (2**i < WIDTH) - buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]}; - else - buffer = {WIDTH{extbit}}; - end - end - assign Y = buffer; end - endgenerate + + for (i = BB_WIDTH-1; i >= 0; i = i-1) + if (B[i]) begin + if (B_SIGNED && i == BB_WIDTH-1) + buffer = {buffer, {2**i{extbit}}}; + else if (2**i < WIDTH) + buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]}; + else + buffer = {WIDTH{extbit}}; + end + end + + assign Y = buffer; endmodule @@ -224,12 +181,9 @@ endmodule module _90_fa (A, B, C, X, Y); parameter WIDTH = 1; - (* force_downto *) input [WIDTH-1:0] A, B, C; - (* force_downto *) output [WIDTH-1:0] X, Y; - (* force_downto *) wire [WIDTH-1:0] t1, t2, t3; assign t1 = A ^ B, t2 = A & B, t3 = C & t1; @@ -240,15 +194,12 @@ endmodule module _90_lcu (P, G, CI, CO); parameter WIDTH = 2; - (* force_downto *) input [WIDTH-1:0] P, G; input CI; - (* force_downto *) output [WIDTH-1:0] CO; integer i, j; - (* force_downto *) reg [WIDTH-1:0] p, g; wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; @@ -292,27 +243,20 @@ module _90_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; - (* force_downto *) output [Y_WIDTH-1:0] CO; - (* force_downto *) - wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) - wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; - - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + wire [Y_WIDTH-1:0] AA = A_buf; + wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; + \$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(X), .G(AA & BB), .CI(CI), .CO(CO)); assign X = AA ^ BB; @@ -337,19 +281,15 @@ endmodule module \$__div_mod_u (A, B, Y, R); parameter WIDTH = 1; - (* force_downto *) input [WIDTH-1:0] A, B; - (* force_downto *) output [WIDTH-1:0] Y, R; - (* force_downto *) wire [WIDTH*WIDTH-1:0] chaindata; assign R = chaindata[WIDTH*WIDTH-1:WIDTH*(WIDTH-1)]; genvar i; generate begin for (i = 0; i < WIDTH; i=i+1) begin:stage - (* force_downto *) wire [WIDTH-1:0] stage_in; if (i == 0) begin:cp @@ -364,8 +304,7 @@ module \$__div_mod_u (A, B, Y, R); end endgenerate endmodule -// truncating signed division/modulo -module \$__div_mod_trunc (A, B, Y, R); +module \$__div_mod (A, B, Y, R); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -376,19 +315,14 @@ module \$__div_mod_trunc (A, B, Y, R); A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y, R; - (* force_downto *) wire [WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u; assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf; assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf; @@ -414,14 +348,11 @@ module _90_div (A, B, Y); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; - \$__div_mod_trunc #( + \$__div_mod #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), @@ -442,114 +373,11 @@ module _90_mod (A, B, Y); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) - input [A_WIDTH-1:0] A; - (* force_downto *) - input [B_WIDTH-1:0] B; - (* force_downto *) - output [Y_WIDTH-1:0] Y; - - \$__div_mod_trunc #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) div_mod ( - .A(A), - .B(B), - .R(Y) - ); -endmodule - -// flooring signed division/modulo -module \$__div_mod_floor (A, B, Y, R); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = - A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : - B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y, R; - - wire [WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u, R_s; - assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf; - assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf; - - \$__div_mod_u #( - .WIDTH(WIDTH) - ) div_mod_u ( - .A(A_buf_u), - .B(B_buf_u), - .Y(Y_u), - .R(R_u) - ); - - // For negative results, if there was a remainder, subtract one to turn - // the round towards 0 into a round towards -inf - assign Y = A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? (R_u == 0 ? -Y_u : -Y_u-1) : Y_u; - - // truncating modulo - assign R_s = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u; - // Flooring modulo differs from truncating modulo only if it is nonzero and - // A and B have different signs - then `floor - trunc = B` - assign R = (R_s != 0) && A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? $signed(B_buf) + $signed(R_s) : R_s; -endmodule - -(* techmap_celltype = "$divfloor" *) -module _90_divfloor (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - (* force_downto *) - input [A_WIDTH-1:0] A; - (* force_downto *) - input [B_WIDTH-1:0] B; - (* force_downto *) - output [Y_WIDTH-1:0] Y; - - \$__div_mod_floor #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) div_mod ( - .A(A), - .B(B), - .Y(Y) - ); -endmodule - -(* techmap_celltype = "$modfloor" *) -module _90_modfloor (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; - \$__div_mod_floor #( + \$__div_mod #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), @@ -575,11 +403,8 @@ module _90_pow (A, B, Y); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; wire _TECHMAP_FAIL_ = 1; @@ -595,27 +420,20 @@ module _90_pmux (A, B, S, Y); parameter WIDTH = 1; parameter S_WIDTH = 1; - (* force_downto *) input [WIDTH-1:0] A; - (* force_downto *) input [WIDTH*S_WIDTH-1:0] B; - (* force_downto *) input [S_WIDTH-1:0] S; - (* force_downto *) output [WIDTH-1:0] Y; - (* force_downto *) wire [WIDTH-1:0] Y_B; genvar i, j; generate - (* force_downto *) wire [WIDTH*S_WIDTH-1:0] B_AND_S; for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}}; end:B_AND for (i = 0; i < WIDTH; i = i + 1) begin:B_OR - (* force_downto *) wire [S_WIDTH-1:0] B_AND_BITS; for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i]; diff --git a/techlibs/coolrunner2/Makefile.inc b/techlibs/coolrunner2/Makefile.inc index 7a680c4fd54..d62c9960c70 100644 --- a/techlibs/coolrunner2/Makefile.inc +++ b/techlibs/coolrunner2/Makefile.inc @@ -1,10 +1,8 @@ OBJS += techlibs/coolrunner2/synth_coolrunner2.o OBJS += techlibs/coolrunner2/coolrunner2_sop.o -OBJS += techlibs/coolrunner2/coolrunner2_fixup.o $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_latch.v)) $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_sim.v)) -$(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_counter_map.v)) $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/tff_extract.v)) $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/xc2_dff.lib)) diff --git a/techlibs/coolrunner2/cells_counter_map.v b/techlibs/coolrunner2/cells_counter_map.v deleted file mode 100644 index f9c44c80ff2..00000000000 --- a/techlibs/coolrunner2/cells_counter_map.v +++ /dev/null @@ -1,162 +0,0 @@ -module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP); - - input wire CE; - input wire CLK; - output wire OUT; - (* force_downto *) - output wire[WIDTH-1:0] POUT; - input wire RST; - input wire UP; - - parameter COUNT_TO = 1; - parameter RESET_MODE = "RISING"; - parameter RESET_TO_MAX = 0; - parameter HAS_POUT = 0; - parameter HAS_CE = 0; - parameter WIDTH = 8; - parameter DIRECTION = "DOWN"; - - if (DIRECTION == "UP") begin - if (WIDTH < 2) begin - initial begin - $display("ERROR: \$__COUNT_ must be at least 2 bits wide (bug in extract_counter pass?)."); - $finish; - end - end - - // FIXME: Max width? - - assign OUT = POUT == COUNT_TO; - - if (HAS_CE) begin - genvar i; - for (i = 0; i < WIDTH; i++) begin: countbits - // each bit = (cur & !reset) ^ (all prev & !reset) - wire xor_to_mc_bitn; - FDCP #( - .INIT(0) - ) bitn_ff ( - .C(CLK), - .CLR(0), - .D(xor_to_mc_bitn), - .PRE(0), - .Q(POUT[i]) - ); - wire orterm_to_xor_bitn; - wire pterm0_to_or_bitn; - wire pterm1_to_or_bitn; - MACROCELL_XOR #( - .INVERT_OUT(0) - ) bitn_xor ( - .IN_ORTERM(orterm_to_xor_bitn), - .IN_PTC(pterm1_to_or_bitn), - .OUT(xor_to_mc_bitn) - ); - ORTERM #( - .WIDTH(1) - ) bitn_or ( - .IN(pterm0_to_or_bitn), - .OUT(orterm_to_xor_bitn) - ); - ANDTERM #( - .COMP_INP(1), - .TRUE_INP(1) - ) bitn_pterm0 ( - .IN(POUT[i]), - .IN_B(OUT), - .OUT(pterm0_to_or_bitn) - ); - ANDTERM #( - .COMP_INP(1), - .TRUE_INP(i + 1) - ) bitn_pterm1 ( - .IN({POUT[i-1:0], CE}), - .IN_B(OUT), - .OUT(pterm1_to_or_bitn) - ); - end - end else begin - // Bit0 is special; toggle unless reset - // cur reset out - // 0 0 1 - // 0 1 0 - // 1 0 0 - // 1 1 0 - wire xor_to_mc_bit0; - FDCP #( - .INIT(0) - ) bit0_ff ( - .C(CLK), - .CLR(0), - .D(xor_to_mc_bit0), - .PRE(0), - .Q(POUT[0]) - ); - wire pterm_to_xor_bit0; - MACROCELL_XOR #( - .INVERT_OUT(0) - ) bit0_xor ( - .IN_PTC(pterm_to_xor_bit0), - .OUT(xor_to_mc_bit0) - ); - ANDTERM #( - .COMP_INP(2), - .TRUE_INP(0) - ) bit0_pterm ( - .IN(), - .IN_B({POUT[0], OUT}), - .OUT(pterm_to_xor_bit0) - ); - - genvar i; - for (i = 1; i < WIDTH; i++) begin: countbits - // each bit = (cur & !reset) ^ (all prev & !reset) - wire xor_to_mc_bitn; - FDCP #( - .INIT(0) - ) bitn_ff ( - .C(CLK), - .CLR(0), - .D(xor_to_mc_bitn), - .PRE(0), - .Q(POUT[i]) - ); - wire orterm_to_xor_bitn; - wire pterm0_to_or_bitn; - wire pterm1_to_or_bitn; - MACROCELL_XOR #( - .INVERT_OUT(0) - ) bitn_xor ( - .IN_ORTERM(orterm_to_xor_bitn), - .IN_PTC(pterm1_to_or_bitn), - .OUT(xor_to_mc_bitn) - ); - ORTERM #( - .WIDTH(1) - ) bitn_or ( - .IN(pterm0_to_or_bitn), - .OUT(orterm_to_xor_bitn) - ); - ANDTERM #( - .COMP_INP(1), - .TRUE_INP(1) - ) bitn_pterm0 ( - .IN(POUT[i]), - .IN_B(OUT), - .OUT(pterm0_to_or_bitn) - ); - ANDTERM #( - .COMP_INP(1), - .TRUE_INP(i) - ) bitn_pterm1 ( - .IN(POUT[i-1:0]), - .IN_B(OUT), - .OUT(pterm1_to_or_bitn) - ); - end - end - end - - // FIXME: down counters - -endmodule diff --git a/techlibs/coolrunner2/coolrunner2_fixup.cc b/techlibs/coolrunner2/coolrunner2_fixup.cc deleted file mode 100644 index 50710e2bdfe..00000000000 --- a/techlibs/coolrunner2/coolrunner2_fixup.cc +++ /dev/null @@ -1,520 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 R. Ou - * - * 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 - -RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cellname) -{ - RTLIL::Wire *outwire = nullptr; - - if (inwire == SigBit(true)) - { - // Constant 1 - outwire = module->addWire( - module->uniquify(stringf("$xc2fix$%s_BUF1_XOR_OUT", cellname))); - auto xor_cell = module->addCell( - module->uniquify(stringf("$xc2fix$%s_BUF1_XOR", cellname)), - ID(MACROCELL_XOR)); - xor_cell->setParam(ID(INVERT_OUT), true); - xor_cell->setPort(ID(OUT), outwire); - } - else if (inwire == SigBit(false)) - { - // Constant 0 - outwire = module->addWire( - module->uniquify(stringf("$xc2fix$%s_BUF0_XOR_OUT", cellname))); - auto xor_cell = module->addCell( - module->uniquify(stringf("$xc2fix$%s_BUF0_XOR", cellname)), - ID(MACROCELL_XOR)); - xor_cell->setParam(ID(INVERT_OUT), false); - xor_cell->setPort(ID(OUT), outwire); - } - else if (inwire == SigBit(RTLIL::State::Sx)) - { - // x; treat as 0 - log_warning("While buffering, changing x to 0 into cell %s\n", cellname); - outwire = module->addWire( - module->uniquify(stringf("$xc2fix$%s_BUF0_XOR_OUT", cellname))); - auto xor_cell = module->addCell( - module->uniquify(stringf("$xc2fix$%s_BUF0_XOR", cellname)), - ID(MACROCELL_XOR)); - xor_cell->setParam(ID(INVERT_OUT), false); - xor_cell->setPort(ID(OUT), outwire); - } - else - { - auto inwire_name = inwire.wire->name.c_str(); - - outwire = module->addWire( - module->uniquify(stringf("$xc2fix$%s_BUF_XOR_OUT", inwire_name))); - - auto and_to_xor_wire = module->addWire( - module->uniquify(stringf("$xc2fix$%s_BUF_AND_OUT", inwire_name))); - - auto and_cell = module->addCell( - module->uniquify(stringf("$xc2fix$%s_BUF_AND", inwire_name)), - ID(ANDTERM)); - and_cell->setParam(ID(TRUE_INP), 1); - and_cell->setParam(ID(COMP_INP), 0); - and_cell->setPort(ID(OUT), and_to_xor_wire); - and_cell->setPort(ID(IN), inwire); - and_cell->setPort(ID(IN_B), SigSpec()); - - auto xor_cell = module->addCell( - module->uniquify(stringf("$xc2fix$%s_BUF_XOR", inwire_name)), - ID(MACROCELL_XOR)); - xor_cell->setParam(ID(INVERT_OUT), false); - xor_cell->setPort(ID(IN_PTC), and_to_xor_wire); - xor_cell->setPort(ID(OUT), outwire); - } - - return outwire; -} - -RTLIL::Wire *makeptermbuffer(RTLIL::Module *module, SigBit inwire) -{ - auto inwire_name = inwire.wire->name.c_str(); - - auto outwire = module->addWire( - module->uniquify(stringf("$xc2fix$%s_BUF_AND_OUT", inwire_name))); - - auto and_cell = module->addCell( - module->uniquify(stringf("$xc2fix$%s_BUF_AND", inwire_name)), - ID(ANDTERM)); - and_cell->setParam(ID(TRUE_INP), 1); - and_cell->setParam(ID(COMP_INP), 0); - and_cell->setPort(ID(OUT), outwire); - and_cell->setPort(ID(IN), inwire); - and_cell->setPort(ID(IN_B), SigSpec()); - - return outwire; -} - -struct Coolrunner2FixupPass : public Pass { - Coolrunner2FixupPass() : Pass("coolrunner2_fixup", "insert necessary buffer cells for CoolRunner-II architecture") { } - void help() override - { - log("\n"); - log(" coolrunner2_fixup [options] [selection]\n"); - log("\n"); - log("Insert necessary buffer cells for CoolRunner-II architecture.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - log_header(design, "Executing COOLRUNNER2_FIXUP pass (insert necessary buffer cells for CoolRunner-II architecture).\n"); - extra_args(args, 1, design); - - for (auto module : design->selected_modules()) - { - SigMap sigmap(module); - - // Find all the FF outputs - pool sig_fed_by_ff; - for (auto cell : module->selected_cells()) - { - if (cell->type.in(ID(FDCP), ID(FDCP_N), ID(FDDCP), ID(LDCP), ID(LDCP_N), - ID(FTCP), ID(FTCP_N), ID(FTDCP), ID(FDCPE), ID(FDCPE_N), ID(FDDCPE))) - { - auto output = sigmap(cell->getPort(ID::Q)[0]); - sig_fed_by_ff.insert(output); - } - } - - // Find all the XOR outputs - pool sig_fed_by_xor; - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(MACROCELL_XOR)) - { - auto output = sigmap(cell->getPort(ID(OUT))[0]); - sig_fed_by_xor.insert(output); - } - } - - // Find all the input/inout outputs - pool sig_fed_by_io; - for (auto cell : module->selected_cells()) - { - if (cell->type.in(ID(IBUF), ID(IOBUFE))) - { - if (cell->hasPort(ID::O)) { - auto output = sigmap(cell->getPort(ID::O)[0]); - sig_fed_by_io.insert(output); - } - } - } - - // Find all the pterm outputs - pool sig_fed_by_pterm; - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(ANDTERM)) - { - auto output = sigmap(cell->getPort(ID(OUT))[0]); - sig_fed_by_pterm.insert(output); - } - } - - // Find all the bufg outputs - pool sig_fed_by_bufg; - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(BUFG)) - { - auto output = sigmap(cell->getPort(ID::O)[0]); - sig_fed_by_bufg.insert(output); - } - } - - // Find all the bufgsr outputs - pool sig_fed_by_bufgsr; - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(BUFGSR)) - { - auto output = sigmap(cell->getPort(ID::O)[0]); - sig_fed_by_bufgsr.insert(output); - } - } - - // Find all the bufgts outputs - pool sig_fed_by_bufgts; - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(BUFGTS)) - { - auto output = sigmap(cell->getPort(ID::O)[0]); - sig_fed_by_bufgts.insert(output); - } - } - - // This is used to fix the input -> FF -> output scenario - pool sig_fed_by_ibuf; - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(IBUF)) - { - auto output = sigmap(cell->getPort(ID::O)[0]); - sig_fed_by_ibuf.insert(output); - } - } - - // Find all of the sinks for each output from an IBUF - dict> ibuf_fanouts; - for (auto cell : module->selected_cells()) - { - for (auto &conn : cell->connections()) - { - if (cell->input(conn.first)) - { - for (auto wire_in : sigmap(conn.second)) - { - if (sig_fed_by_ibuf[wire_in]) - { - auto existing_count = ibuf_fanouts[wire_in].first; - ibuf_fanouts[wire_in] = - std::pair(existing_count + 1, cell); - } - } - } - } - } - - dict ibuf_out_to_packed_reg_cell; - pool packed_reg_out; - for (auto x : ibuf_fanouts) - { - auto ibuf_out_wire = x.first; - auto fanout_count = x.second.first; - auto maybe_ff_cell = x.second.second; - - // The register can be packed with the IBUF only if it's - // actually a register and it's the only fanout. Otherwise, - // the pad-to-zia path has to be used up and the register - // can't be packed with the ibuf. - if (fanout_count == 1 && maybe_ff_cell->type.in( - ID(FDCP), ID(FDCP_N), ID(FDDCP), ID(LDCP), ID(LDCP_N), - ID(FTCP), ID(FTCP_N), ID(FTDCP), ID(FDCPE), ID(FDCPE_N), ID(FDDCPE))) - { - SigBit input; - if (maybe_ff_cell->type.in(ID(FTCP), ID(FTCP_N), ID(FTDCP))) - input = sigmap(maybe_ff_cell->getPort(ID::T)[0]); - else - input = sigmap(maybe_ff_cell->getPort(ID::D)[0]); - SigBit output = sigmap(maybe_ff_cell->getPort(ID::Q)[0]); - - if (input == ibuf_out_wire) - { - log("Found IBUF %s that can be packed with FF %s (type %s)\n", - ibuf_out_wire.wire->name.c_str(), - maybe_ff_cell->name.c_str(), - maybe_ff_cell->type.c_str()); - - ibuf_out_to_packed_reg_cell[ibuf_out_wire] = maybe_ff_cell; - packed_reg_out.insert(output); - } - } - } - - for (auto cell : module->selected_cells()) - { - if (cell->type.in(ID(FDCP), ID(FDCP_N), ID(FDDCP), ID(LDCP), ID(LDCP_N), - ID(FTCP), ID(FTCP_N), ID(FTDCP), ID(FDCPE), ID(FDCPE_N), ID(FDDCPE))) - { - // Buffering FF inputs. FF inputs can only come from either - // an IO pin or from an XOR. Otherwise AND/XOR cells need - // to be inserted. - SigBit input; - if (cell->type.in(ID(FTCP), ID(FTCP_N), ID(FTDCP))) - input = sigmap(cell->getPort(ID::T)[0]); - else - input = sigmap(cell->getPort(ID::D)[0]); - - // If the input wasn't an XOR nor an IO, then a buffer - // definitely needs to be added. - // Otherwise, if it is an IO, only leave unbuffered - // if we're being packed with the IO. - if ((!sig_fed_by_xor[input] && !sig_fed_by_io[input]) || - (sig_fed_by_io[input] && ibuf_out_to_packed_reg_cell[input] != cell)) - { - log("Buffering input to \"%s\"\n", cell->name.c_str()); - - auto xor_to_ff_wire = makexorbuffer(module, input, cell->name.c_str()); - - if (cell->type.in(ID(FTCP), ID(FTCP_N), ID(FTDCP))) - cell->setPort(ID::T, xor_to_ff_wire); - else - cell->setPort(ID::D, xor_to_ff_wire); - } - - // Buffering FF clocks. FF clocks can only come from either - // a pterm or a bufg. In some cases this will be handled - // in coolrunner2_sop (e.g. if clock is generated from - // AND-ing two signals) but not in all cases. - SigBit clock; - if (cell->type.in(ID(LDCP), ID(LDCP_N))) - clock = sigmap(cell->getPort(ID::G)[0]); - else - clock = sigmap(cell->getPort(ID::C)[0]); - - if (!sig_fed_by_pterm[clock] && !sig_fed_by_bufg[clock]) - { - log("Buffering clock to \"%s\"\n", cell->name.c_str()); - - auto pterm_to_ff_wire = makeptermbuffer(module, clock); - - if (cell->type.in(ID(LDCP), ID(LDCP_N))) - cell->setPort(ID::G, pterm_to_ff_wire); - else - cell->setPort(ID::C, pterm_to_ff_wire); - } - - // Buffering FF set/reset. This can only come from either - // a pterm or a bufgsr. - SigBit set; - set = sigmap(cell->getPort(ID(PRE))[0]); - if (set != SigBit(false)) - { - if (!sig_fed_by_pterm[set] && !sig_fed_by_bufgsr[set]) - { - log("Buffering set to \"%s\"\n", cell->name.c_str()); - - auto pterm_to_ff_wire = makeptermbuffer(module, set); - - cell->setPort(ID(PRE), pterm_to_ff_wire); - } - } - - SigBit reset; - reset = sigmap(cell->getPort(ID::CLR)[0]); - if (reset != SigBit(false)) - { - if (!sig_fed_by_pterm[reset] && !sig_fed_by_bufgsr[reset]) - { - log("Buffering reset to \"%s\"\n", cell->name.c_str()); - - auto pterm_to_ff_wire = makeptermbuffer(module, reset); - - cell->setPort(ID::CLR, pterm_to_ff_wire); - } - } - - // Buffering FF clock enable - // FIXME: This doesn't fully fix PTC conflicts - // FIXME: Need to ensure constant enables are optimized out - if (cell->type.in(ID(FDCPE), ID(FDCPE_N), ID(FDDCPE))) - { - SigBit ce; - ce = sigmap(cell->getPort(ID(CE))[0]); - if (!sig_fed_by_pterm[ce]) - { - log("Buffering clock enable to \"%s\"\n", cell->name.c_str()); - - auto pterm_to_ff_wire = makeptermbuffer(module, ce); - - cell->setPort(ID(CE), pterm_to_ff_wire); - } - } - } - } - - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(IOBUFE)) - { - // Buffer IOBUFE inputs. This can only be fed from an XOR or FF. - SigBit input = sigmap(cell->getPort(ID::I)[0]); - - if ((!sig_fed_by_xor[input] && !sig_fed_by_ff[input]) || - packed_reg_out[input]) - { - log("Buffering input to \"%s\"\n", cell->name.c_str()); - - auto xor_to_io_wire = makexorbuffer(module, input, cell->name.c_str()); - - cell->setPort(ID::I, xor_to_io_wire); - } - - // Buffer IOBUFE enables. This can only be fed from a pterm - // or a bufgts. - if (cell->hasPort(ID::E)) - { - SigBit oe; - oe = sigmap(cell->getPort(ID::E)[0]); - if (!sig_fed_by_pterm[oe] && !sig_fed_by_bufgts[oe]) - { - log("Buffering output enable to \"%s\"\n", cell->name.c_str()); - - auto pterm_to_oe_wire = makeptermbuffer(module, oe); - - cell->setPort(ID::E, pterm_to_oe_wire); - } - } - } - } - - // Now we have to fix up some cases where shared logic can - // cause XORs to have multiple fanouts to something other than - // pterms (which is not ok) - - // Find all the XOR outputs - dict xor_out_to_xor_cell; - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(MACROCELL_XOR)) - { - auto output = sigmap(cell->getPort(ID(OUT))[0]); - xor_out_to_xor_cell[output] = cell; - } - } - - // Find all of the sinks for each output from an XOR - pool xor_fanout_once; - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(ANDTERM)) - continue; - - for (auto &conn : cell->connections()) - { - if (cell->input(conn.first)) - { - for (auto wire_in : sigmap(conn.second)) - { - auto xor_cell = xor_out_to_xor_cell[wire_in]; - if (xor_cell) - { - if (xor_fanout_once[wire_in]) - { - log("Additional fanout found for %s into %s (type %s), duplicating\n", - xor_cell->name.c_str(), - cell->name.c_str(), - cell->type.c_str()); - - auto new_xor_cell = module->addCell( - module->uniquify(xor_cell->name), xor_cell); - auto new_wire = module->addWire( - module->uniquify(wire_in.wire->name)); - new_xor_cell->setPort(ID(OUT), new_wire); - cell->setPort(conn.first, new_wire); - } - xor_fanout_once.insert(wire_in); - } - } - } - } - } - - // Do the same fanout fixing for OR terms. By doing this - // after doing XORs, both pieces will be duplicated when necessary. - - // Find all the OR outputs - dict or_out_to_or_cell; - for (auto cell : module->selected_cells()) - { - if (cell->type == ID(ORTERM)) - { - auto output = sigmap(cell->getPort(ID(OUT))[0]); - or_out_to_or_cell[output] = cell; - } - } - - // Find all of the sinks for each output from an OR - pool or_fanout_once; - for (auto cell : module->selected_cells()) - { - for (auto &conn : cell->connections()) - { - if (cell->input(conn.first)) - { - for (auto wire_in : sigmap(conn.second)) - { - auto or_cell = or_out_to_or_cell[wire_in]; - if (or_cell) - { - if (or_fanout_once[wire_in]) - { - log("Additional fanout found for %s into %s (type %s), duplicating\n", - or_cell->name.c_str(), - cell->name.c_str(), - cell->type.c_str()); - - auto new_or_cell = module->addCell( - module->uniquify(or_cell->name), or_cell); - auto new_wire = module->addWire( - module->uniquify(wire_in.wire->name)); - new_or_cell->setPort(ID(OUT), new_wire); - cell->setPort(conn.first, new_wire); - } - or_fanout_once.insert(wire_in); - } - } - } - } - } - } - } -} Coolrunner2FixupPass; - -PRIVATE_NAMESPACE_END diff --git a/techlibs/coolrunner2/coolrunner2_sop.cc b/techlibs/coolrunner2/coolrunner2_sop.cc index 17e0d84325f..de0cbb29db0 100644 --- a/techlibs/coolrunner2/coolrunner2_sop.cc +++ b/techlibs/coolrunner2/coolrunner2_sop.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct Coolrunner2SopPass : public Pass { Coolrunner2SopPass() : Pass("coolrunner2_sop", "break $sop cells into ANDTERM/ORTERM cells") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" coolrunner2_sop [options] [selection]\n"); @@ -33,7 +33,7 @@ struct Coolrunner2SopPass : public Pass { log("Break $sop cells into ANDTERM/ORTERM cells.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing COOLRUNNER2_SOP pass (break $sop cells into ANDTERM/ORTERM cells).\n"); extra_args(args, 1, design); @@ -47,54 +47,52 @@ struct Coolrunner2SopPass : public Pass { dict> not_cells; for (auto cell : module->selected_cells()) { - if (cell->type == ID($_NOT_)) + if (cell->type == "$_NOT_") { - auto not_input = sigmap(cell->getPort(ID::A)[0]); - auto not_output = sigmap(cell->getPort(ID::Y)[0]); + auto not_input = sigmap(cell->getPort("\\A")[0]); + auto not_output = sigmap(cell->getPort("\\Y")[0]); not_cells[not_input] = tuple(not_output, cell); } } // Find wires that need to become special product terms - dict>> special_pterms_no_inv; - dict>> special_pterms_inv; + dict>> special_pterms_no_inv; + dict>> special_pterms_inv; for (auto cell : module->selected_cells()) { - if (cell->type.in(ID(FDCP), ID(FDCP_N), ID(FDDCP), ID(FTCP), ID(FTCP_N), ID(FTDCP), - ID(FDCPE), ID(FDCPE_N), ID(FDDCPE), ID(LDCP), ID(LDCP_N))) + if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\FTCP", "\\FTCP_N", "\\FTDCP", + "\\FDCPE", "\\FDCPE_N", "\\FDDCPE", "\\LDCP", "\\LDCP_N")) { - if (cell->hasPort(ID(PRE))) - special_pterms_no_inv[sigmap(cell->getPort(ID(PRE))[0])].insert( - make_tuple(cell, ID(PRE))); - if (cell->hasPort(ID::CLR)) - special_pterms_no_inv[sigmap(cell->getPort(ID::CLR)[0])].insert( - make_tuple(cell, ID::CLR)); - if (cell->hasPort(ID(CE))) - special_pterms_no_inv[sigmap(cell->getPort(ID(CE))[0])].insert( - make_tuple(cell, ID(CE))); - - if (cell->hasPort(ID::C)) - special_pterms_inv[sigmap(cell->getPort(ID::C)[0])].insert( - make_tuple(cell, ID::C)); - if (cell->hasPort(ID::G)) - special_pterms_inv[sigmap(cell->getPort(ID::G)[0])].insert( - make_tuple(cell, ID::G)); + if (cell->hasPort("\\PRE")) + special_pterms_no_inv[sigmap(cell->getPort("\\PRE")[0])].insert( + tuple(cell, "\\PRE")); + if (cell->hasPort("\\CLR")) + special_pterms_no_inv[sigmap(cell->getPort("\\CLR")[0])].insert( + tuple(cell, "\\CLR")); + if (cell->hasPort("\\CE")) + special_pterms_no_inv[sigmap(cell->getPort("\\CE")[0])].insert( + tuple(cell, "\\CE")); + + if (cell->hasPort("\\C")) + special_pterms_inv[sigmap(cell->getPort("\\C")[0])].insert( + tuple(cell, "\\C")); + if (cell->hasPort("\\G")) + special_pterms_inv[sigmap(cell->getPort("\\G")[0])].insert( + tuple(cell, "\\G")); } } // Process $sop cells for (auto cell : module->selected_cells()) { - if (cell->type == ID($sop)) + if (cell->type == "$sop") { // Read the inputs/outputs/parameters of the $sop cell - auto sop_inputs = sigmap(cell->getPort(ID::A)); - auto sop_output = sigmap(cell->getPort(ID::Y))[0]; - auto sop_depth = cell->getParam(ID::DEPTH).as_int(); - auto sop_width = cell->getParam(ID::WIDTH).as_int(); - auto sop_table = cell->getParam(ID::TABLE); - - auto sop_output_wire_name = sop_output.wire->name.c_str(); + auto sop_inputs = sigmap(cell->getPort("\\A")); + auto sop_output = sigmap(cell->getPort("\\Y"))[0]; + auto sop_depth = cell->getParam("\\DEPTH").as_int(); + auto sop_width = cell->getParam("\\WIDTH").as_int(); + auto sop_table = cell->getParam("\\TABLE"); // Check for a $_NOT_ at the output bool has_invert = false; @@ -110,15 +108,20 @@ struct Coolrunner2SopPass : public Pass { } // Check for special P-term usage - bool is_special_pterm = - special_pterms_no_inv.count(sop_output) || special_pterms_inv.count(sop_output); + bool is_special_pterm = false; + bool special_pterm_can_invert = false; + if (special_pterms_no_inv.count(sop_output) || special_pterms_inv.count(sop_output)) + { + is_special_pterm = true; + if (!special_pterms_no_inv[sop_output].size()) + special_pterm_can_invert = true; + } // Construct AND cells pool intermed_wires; for (int i = 0; i < sop_depth; i++) { // Wire for the output - auto and_out = module->addWire( - module->uniquify(stringf("$xc2sop$%s_AND%d_OUT", sop_output_wire_name, i))); + auto and_out = module->addWire(NEW_ID); intermed_wires.insert(and_out); // Signals for the inputs @@ -137,84 +140,107 @@ struct Coolrunner2SopPass : public Pass { } // Construct the cell - auto and_cell = module->addCell( - module->uniquify(stringf("$xc2sop$%s_AND%d", sop_output_wire_name, i)), - ID(ANDTERM)); - and_cell->setParam(ID(TRUE_INP), GetSize(and_in_true)); - and_cell->setParam(ID(COMP_INP), GetSize(and_in_comp)); - and_cell->setPort(ID(OUT), and_out); - and_cell->setPort(ID(IN), and_in_true); - and_cell->setPort(ID(IN_B), and_in_comp); + auto and_cell = module->addCell(NEW_ID, "\\ANDTERM"); + and_cell->setParam("\\TRUE_INP", GetSize(and_in_true)); + and_cell->setParam("\\COMP_INP", GetSize(and_in_comp)); + and_cell->setPort("\\OUT", and_out); + and_cell->setPort("\\IN", and_in_true); + and_cell->setPort("\\IN_B", and_in_comp); } if (sop_depth == 1) { // If there is only one term, don't construct an OR cell. Directly construct the XOR gate - auto xor_cell = module->addCell( - module->uniquify(stringf("$xc2sop$%s_XOR", sop_output_wire_name)), - ID(MACROCELL_XOR)); - xor_cell->setParam(ID(INVERT_OUT), has_invert); - xor_cell->setPort(ID(IN_PTC), *intermed_wires.begin()); - xor_cell->setPort(ID(OUT), sop_output); + auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR"); + xor_cell->setParam("\\INVERT_OUT", has_invert); + xor_cell->setPort("\\IN_PTC", *intermed_wires.begin()); + xor_cell->setPort("\\OUT", sop_output); // Special P-term handling if (is_special_pterm) { - // Can always connect the P-term directly if it's going - // into something invert-capable - for (const auto &x : special_pterms_inv[sop_output]) + if (!has_invert || special_pterm_can_invert) { - std::get<0>(x)->setPort(std::get<1>(x), *intermed_wires.begin()); + // Can connect the P-term directly to the special term sinks + for (auto x : special_pterms_inv[sop_output]) + std::get<0>(x)->setPort(std::get<1>(x), *intermed_wires.begin()); + for (auto x : special_pterms_no_inv[sop_output]) + std::get<0>(x)->setPort(std::get<1>(x), *intermed_wires.begin()); + } - // If this signal is indeed inverted, flip the cell polarity - if (has_invert) + if (has_invert) + { + if (special_pterm_can_invert) { - auto cell = std::get<0>(x); - if (cell->type == ID(FDCP)) cell->type = ID(FDCP_N); - else if (cell->type == ID(FDCP_N)) cell->type = ID(FDCP); - else if (cell->type == ID(FTCP)) cell->type = ID(FTCP_N); - else if (cell->type == ID(FTCP_N)) cell->type = ID(FTCP); - else if (cell->type == ID(FDCPE)) cell->type = ID(FDCPE_N); - else if (cell->type == ID(FDCPE_N)) cell->type = ID(FDCPE); - else if (cell->type == ID(LDCP)) cell->type = ID(LDCP_N); - else if (cell->type == ID(LDCP_N)) cell->type = ID(LDCP); - else log_assert(!"Internal error! Bad cell type!"); + log_assert(special_pterms_no_inv[sop_output].size() == 0); + + for (auto x : special_pterms_inv[sop_output]) + { + auto cell = std::get<0>(x); + // Need to invert the polarity of the cell + if (cell->type == "\\FDCP") cell->type = "\\FDCP_N"; + else if (cell->type == "\\FDCP_N") cell->type = "\\FDCP"; + else if (cell->type == "\\FTCP") cell->type = "\\FTCP_N"; + else if (cell->type == "\\FTCP_N") cell->type = "\\FTCP"; + else if (cell->type == "\\FDCPE") cell->type = "\\FDCPE_N"; + else if (cell->type == "\\FDCPE_N") cell->type = "\\FDCPE"; + else if (cell->type == "\\LDCP") cell->type = "\\LDCP_N"; + else if (cell->type == "\\LDCP_N") cell->type = "\\LDCP"; + else log_assert(!"Internal error! Bad cell type!"); + } } - } + else + { + // Need to construct a feed-through term + auto feedthrough_out = module->addWire(NEW_ID); + auto feedthrough_cell = module->addCell(NEW_ID, "\\ANDTERM"); + feedthrough_cell->setParam("\\TRUE_INP", 1); + feedthrough_cell->setParam("\\COMP_INP", 0); + feedthrough_cell->setPort("\\OUT", feedthrough_out); + feedthrough_cell->setPort("\\IN", sop_output); + feedthrough_cell->setPort("\\IN_B", SigSpec()); - // If it's going into something that's not invert-capable, - // connect it directly only if this signal isn't inverted - if (!has_invert) - { - for (auto x : special_pterms_no_inv[sop_output]) - std::get<0>(x)->setPort(std::get<1>(x), *intermed_wires.begin()); + for (auto x : special_pterms_inv[sop_output]) + std::get<0>(x)->setPort(std::get<1>(x), feedthrough_out); + for (auto x : special_pterms_no_inv[sop_output]) + std::get<0>(x)->setPort(std::get<1>(x), feedthrough_out); + } } - - // Otherwise, a feedthrough P-term has to be created. Leave that to happen - // in the coolrunner2_fixup pass. } } else { // Wire from OR to XOR - auto or_to_xor_wire = module->addWire( - module->uniquify(stringf("$xc2sop$%s_OR_OUT", sop_output_wire_name))); + auto or_to_xor_wire = module->addWire(NEW_ID); // Construct the OR cell - auto or_cell = module->addCell( - module->uniquify(stringf("$xc2sop$%s_OR", sop_output_wire_name)), - ID(ORTERM)); - or_cell->setParam(ID::WIDTH, sop_depth); - or_cell->setPort(ID(IN), intermed_wires); - or_cell->setPort(ID(OUT), or_to_xor_wire); + auto or_cell = module->addCell(NEW_ID, "\\ORTERM"); + or_cell->setParam("\\WIDTH", sop_depth); + or_cell->setPort("\\IN", intermed_wires); + or_cell->setPort("\\OUT", or_to_xor_wire); // Construct the XOR cell - auto xor_cell = module->addCell( - module->uniquify(stringf("$xc2sop$%s_XOR", sop_output_wire_name)), - ID(MACROCELL_XOR)); - xor_cell->setParam(ID(INVERT_OUT), has_invert); - xor_cell->setPort(ID(IN_ORTERM), or_to_xor_wire); - xor_cell->setPort(ID(OUT), sop_output); + auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR"); + xor_cell->setParam("\\INVERT_OUT", has_invert); + xor_cell->setPort("\\IN_ORTERM", or_to_xor_wire); + xor_cell->setPort("\\OUT", sop_output); + + if (is_special_pterm) + { + // Need to construct a feed-through term + auto feedthrough_out = module->addWire(NEW_ID); + auto feedthrough_cell = module->addCell(NEW_ID, "\\ANDTERM"); + feedthrough_cell->setParam("\\TRUE_INP", 1); + feedthrough_cell->setParam("\\COMP_INP", 0); + feedthrough_cell->setPort("\\OUT", feedthrough_out); + feedthrough_cell->setPort("\\IN", sop_output); + feedthrough_cell->setPort("\\IN_B", SigSpec()); + + for (auto x : special_pterms_inv[sop_output]) + std::get<0>(x)->setPort(std::get<1>(x), feedthrough_out); + for (auto x : special_pterms_no_inv[sop_output]) + std::get<0>(x)->setPort(std::get<1>(x), feedthrough_out); + } } // Finally, remove the $sop cell @@ -222,6 +248,60 @@ struct Coolrunner2SopPass : public Pass { } } + // In some cases we can get a FF feeding straight into an FF. This is not possible, so we need to insert + // some AND/XOR cells in the middle to make it actually work. + + // Find all the FF outputs + pool sig_fed_by_ff; + for (auto cell : module->selected_cells()) + { + if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N", + "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE")) + { + auto output = sigmap(cell->getPort("\\Q")[0]); + sig_fed_by_ff.insert(output); + } + } + + // Look at all the FF inputs + for (auto cell : module->selected_cells()) + { + if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N", + "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE")) + { + SigBit input; + if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP")) + input = sigmap(cell->getPort("\\T")[0]); + else + input = sigmap(cell->getPort("\\D")[0]); + + if (sig_fed_by_ff[input]) + { + printf("Buffering input to \"%s\"\n", cell->name.c_str()); + + auto and_to_xor_wire = module->addWire(NEW_ID); + auto xor_to_ff_wire = module->addWire(NEW_ID); + + auto and_cell = module->addCell(NEW_ID, "\\ANDTERM"); + and_cell->setParam("\\TRUE_INP", 1); + and_cell->setParam("\\COMP_INP", 0); + and_cell->setPort("\\OUT", and_to_xor_wire); + and_cell->setPort("\\IN", input); + and_cell->setPort("\\IN_B", SigSpec()); + + auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR"); + xor_cell->setParam("\\INVERT_OUT", false); + xor_cell->setPort("\\IN_PTC", and_to_xor_wire); + xor_cell->setPort("\\OUT", xor_to_ff_wire); + + if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP")) + cell->setPort("\\T", xor_to_ff_wire); + else + cell->setPort("\\D", xor_to_ff_wire); + } + } + } + // Actually do the removal now that we aren't iterating for (auto cell : cells_to_remove) { diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc index 47102fbb1f7..014c68622f1 100644 --- a/techlibs/coolrunner2/synth_coolrunner2.cc +++ b/techlibs/coolrunner2/synth_coolrunner2.cc @@ -29,7 +29,7 @@ struct SynthCoolrunner2Pass : public ScriptPass { SynthCoolrunner2Pass() : ScriptPass("synth_coolrunner2", "synthesis for Xilinx Coolrunner-II CPLDs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -55,7 +55,7 @@ struct SynthCoolrunner2Pass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -66,7 +66,7 @@ struct SynthCoolrunner2Pass : public ScriptPass string top_opt, json_file; bool flatten, retime; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; json_file = ""; @@ -74,7 +74,7 @@ struct SynthCoolrunner2Pass : public ScriptPass retime = false; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -121,7 +121,7 @@ struct SynthCoolrunner2Pass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { @@ -143,12 +143,9 @@ struct SynthCoolrunner2Pass : public ScriptPass if (check_label("fine")) { - run("extract_counter -dir up -allow_arst no"); - run("techmap -map +/coolrunner2/cells_counter_map.v"); - run("clean"); run("opt -fast -full"); - run("techmap -map +/techmap.v -map +/coolrunner2/cells_latch.v"); - run("opt -fast"); + run("techmap"); + run("techmap -map +/coolrunner2/cells_latch.v"); run("dfflibmap -prepare -liberty +/coolrunner2/xc2_dff.lib"); } @@ -164,7 +161,7 @@ struct SynthCoolrunner2Pass : public ScriptPass if (check_label("map_pla")) { - run("abc -sop -I 40 -P 56" + string(retime ? " -dff -D 1" : "")); + run("abc -sop -I 40 -P 56"); run("clean"); } @@ -178,11 +175,9 @@ struct SynthCoolrunner2Pass : public ScriptPass run("dffinit -ff LDCP Q INIT"); run("dffinit -ff LDCP_N Q INIT"); run("coolrunner2_sop"); - run("clean"); run("iopadmap -bits -inpad IBUF O:I -outpad IOBUFE I:IO -inoutpad IOBUFE O:IO -toutpad IOBUFE E:I:IO -tinoutpad IOBUFE E:O:I:IO"); run("attrmvcp -attr src -attr LOC t:IOBUFE n:*"); run("attrmvcp -attr src -attr LOC -driven t:IBUF n:*"); - run("coolrunner2_fixup"); run("splitnets"); run("clean"); } diff --git a/techlibs/easic/synth_easic.cc b/techlibs/easic/synth_easic.cc index 897bc1c40ed..dd9e3dab7e3 100644 --- a/techlibs/easic/synth_easic.cc +++ b/techlibs/easic/synth_easic.cc @@ -29,7 +29,7 @@ struct SynthEasicPass : public ScriptPass { SynthEasicPass() : ScriptPass("synth_easic", "synthesis for eASIC platform") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -56,7 +56,7 @@ struct SynthEasicPass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -67,7 +67,7 @@ struct SynthEasicPass : public ScriptPass string top_opt, vlog_file, etools_path; bool flatten, retime; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; vlog_file = ""; @@ -76,7 +76,7 @@ struct SynthEasicPass : public ScriptPass retime = false; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -127,7 +127,7 @@ struct SynthEasicPass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { string phys_clk_lib = stringf("%s/data_ruby28/design_libs/logical/timing/gp/n3x_phys_clk_0v893ff125c.lib", etools_path.c_str()); string logic_lut_lib = stringf("%s/data_ruby28/design_libs/logical/timing/gp/n3x_logic_lut_0v893ff125c.lib", etools_path.c_str()); @@ -158,7 +158,7 @@ struct SynthEasicPass : public ScriptPass run("techmap"); run("opt -fast"); if (retime || help_mode) { - run("abc -dff -D 1", " (only if -retime)"); + run("abc -dff", " (only if -retime)"); run("opt_clean", "(only if -retime)"); } } diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index 9d564c78cc3..46463f51051 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -2,28 +2,26 @@ OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \ techlibs/ecp5/ecp5_gsr.o -GENFILES += techlibs/ecp5/bram_init_1_2_4.vh -GENFILES += techlibs/ecp5/bram_init_9_18_36.vh -GENFILES += techlibs/ecp5/bram_conn_1.vh -GENFILES += techlibs/ecp5/bram_conn_2.vh -GENFILES += techlibs/ecp5/bram_conn_4.vh -GENFILES += techlibs/ecp5/bram_conn_9.vh -GENFILES += techlibs/ecp5/bram_conn_18.vh -GENFILES += techlibs/ecp5/bram_conn_36.vh - $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_ff.vh)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_io.vh)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_bb.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutrams_map.v)) -$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutrams.txt)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutram.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v)) -$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams.txt)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dsp_map.v)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_map.v)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_unmap.v)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_model.v)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_5g.box)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_5g.lut)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_5g_nowide.lut)) + EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk .SECONDARY: techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk diff --git a/techlibs/ecp5/abc9_5g.box b/techlibs/ecp5/abc9_5g.box new file mode 100644 index 00000000000..2bc945a54fa --- /dev/null +++ b/techlibs/ecp5/abc9_5g.box @@ -0,0 +1,43 @@ +# NB: Inputs/Outputs must be ordered alphabetically +# (with exceptions for carry in/out) + +# Box 1 : CCU2C (2xCARRY + 2xLUT4) +# Outputs: S0, S1, COUT +# (NB: carry chain input/output must be last +# input/output and bus has been moved +# there overriding the otherwise +# alphabetical ordering) +# name ID w/b ins outs +CCU2C 1 1 9 3 + +#A0 A1 B0 B1 C0 C1 D0 D1 CIN +379 - 379 - 275 - 141 - 257 +630 379 630 379 526 275 392 141 273 +516 516 516 516 412 412 278 278 43 + +# Box 2 : TRELLIS_DPR16X4_COMB (16x4 dist ram) +# Outputs: DO0, DO1, DO2, DO3 +# name ID w/b ins outs +$__ABC9_DPR16X4_COMB 2 0 8 4 + +#A0 A1 A2 A3 RAD0 RAD1 RAD2 RAD3 +0 0 0 0 141 379 275 379 +0 0 0 0 141 379 275 379 +0 0 0 0 141 379 275 379 +0 0 0 0 141 379 275 379 + +# Box 3 : PFUMX (MUX2) +# Outputs: Z +# name ID w/b ins outs +PFUMX 3 1 3 1 + +#ALUT BLUT C0 +98 98 151 + +# Box 4 : L6MUX21 (MUX2) +# Outputs: Z +# name ID w/b ins outs +L6MUX21 4 1 3 1 + +#D0 D1 SD +140 141 148 diff --git a/techlibs/ecp5/abc9_5g.lut b/techlibs/ecp5/abc9_5g.lut new file mode 100644 index 00000000000..e8aa9b35dd6 --- /dev/null +++ b/techlibs/ecp5/abc9_5g.lut @@ -0,0 +1,25 @@ +# ECP5-5G LUT library for ABC +# Note that ECP5 architecture assigns difference +# in LUT input delay to interconnect, so this is +# considered too + + +# Simple LUTs +# area D C B A +1 1 141 +2 1 141 275 +3 1 141 275 379 +4 1 141 275 379 379 + +# LUT5 = 2x LUT4 + PFUMX +# area M0 D C B A +5 2 151 239 373 477 477 + +# LUT6 = 2x LUT5 + MUX2 +# area M1 M0 D C B A +6 4 148 292 380 514 618 618 + +# LUT7 = 2x LUT6 + MUX2 +# area M2 M1 M0 D C B A +7 8 148 289 433 521 655 759 759 + diff --git a/techlibs/ecp5/abc9_5g_nowide.lut b/techlibs/ecp5/abc9_5g_nowide.lut new file mode 100644 index 00000000000..60352d892b1 --- /dev/null +++ b/techlibs/ecp5/abc9_5g_nowide.lut @@ -0,0 +1,12 @@ +# ECP5-5G LUT library for ABC +# Note that ECP5 architecture assigns difference +# in LUT input delay to interconnect, so this is +# considered too + + +# Simple LUTs +# area D C B A +1 1 141 +2 1 141 275 +3 1 141 275 379 +4 1 141 275 379 379 diff --git a/techlibs/ecp5/abc9_map.v b/techlibs/ecp5/abc9_map.v new file mode 100644 index 00000000000..d8d70f9f6bf --- /dev/null +++ b/techlibs/ecp5/abc9_map.v @@ -0,0 +1,24 @@ +// --------------------------------------- + +module TRELLIS_DPR16X4 ( + input [3:0] DI, + input [3:0] WAD, + input WRE, + input WCK, + input [3:0] RAD, + output [3:0] DO +); + parameter WCKMUX = "WCK"; + parameter WREMUX = "WRE"; + parameter [63:0] INITVAL = 64'h0000000000000000; + wire [3:0] \$DO ; + + TRELLIS_DPR16X4 #( + .WCKMUX(WCKMUX), .WREMUX(WREMUX), .INITVAL(INITVAL) + ) _TECHMAP_REPLACE_ ( + .DI(DI), .WAD(WAD), .WRE(WRE), .WCK(WCK), + .RAD(RAD), .DO(\$DO ) + ); + + \$__ABC9_DPR16X4_COMB do (.A(\$DO ), .S(RAD), .Y(DO)); +endmodule diff --git a/techlibs/ecp5/abc9_model.v b/techlibs/ecp5/abc9_model.v new file mode 100644 index 00000000000..1dc8b561776 --- /dev/null +++ b/techlibs/ecp5/abc9_model.v @@ -0,0 +1,5 @@ +// --------------------------------------- + +(* abc9_box_id=2 *) +module \$__ABC9_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y); +endmodule diff --git a/techlibs/ecp5/abc9_unmap.v b/techlibs/ecp5/abc9_unmap.v new file mode 100644 index 00000000000..9ae143c467b --- /dev/null +++ b/techlibs/ecp5/abc9_unmap.v @@ -0,0 +1,5 @@ +// --------------------------------------- + +module \$__ABC9_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y); + assign Y = A; +endmodule diff --git a/techlibs/ecp5/arith_map.v b/techlibs/ecp5/arith_map.v index ffd42469cef..17bde049754 100644 --- a/techlibs/ecp5/arith_map.v +++ b/techlibs/ecp5/arith_map.v @@ -26,20 +26,15 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; - (* force_downto *) output [Y_WIDTH-1:0] CO; wire _TECHMAP_FAIL_ = Y_WIDTH <= 4; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); @@ -53,15 +48,10 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO); localparam Y_WIDTH2 = round_up2(Y_WIDTH); - (* force_downto *) wire [Y_WIDTH2-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf; - (* force_downto *) wire [Y_WIDTH2-1:0] BX = B_buf; - (* force_downto *) wire [Y_WIDTH2-1:0] C = {CO, CI}; - (* force_downto *) wire [Y_WIDTH2-1:0] FCO, Y1; genvar i; diff --git a/techlibs/ecp5/bram.txt b/techlibs/ecp5/bram.txt new file mode 100644 index 00000000000..777ccaa2eba --- /dev/null +++ b/techlibs/ecp5/bram.txt @@ -0,0 +1,52 @@ +bram $__ECP5_PDPW16KD + init 1 + + abits 9 + dbits 36 + + groups 2 + ports 1 1 + wrmode 1 0 + enable 4 1 + transp 0 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__ECP5_DP16KD + init 1 + + abits 10 @a10d18 + dbits 18 @a10d18 + abits 11 @a11d9 + dbits 9 @a11d9 + abits 12 @a12d4 + dbits 4 @a12d4 + abits 13 @a13d2 + dbits 2 @a13d2 + abits 14 @a14d1 + dbits 1 @a14d1 + + groups 2 + ports 1 1 + wrmode 1 0 + enable 2 1 @a10d18 + enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 + transp 0 2 + clocks 2 3 + clkpol 2 3 +endbram + +match $__ECP5_PDPW16KD + min bits 2048 + min efficiency 5 + shuffle_enable A + make_transp + or_next_if_better +endmatch + +match $__ECP5_DP16KD + min bits 2048 + min efficiency 5 + shuffle_enable A +endmatch diff --git a/techlibs/ecp5/brams.txt b/techlibs/ecp5/brams.txt deleted file mode 100644 index d34d9ec0746..00000000000 --- a/techlibs/ecp5/brams.txt +++ /dev/null @@ -1,114 +0,0 @@ -bram $__ECP5_PDPW16KD - init 1 - - abits 9 - dbits 36 - - groups 2 - ports 1 1 - wrmode 1 0 - enable 4 1 - transp 0 0 - clocks 2 3 - clkpol 2 3 -endbram - -bram $__ECP5_DP16KD - init 1 - - abits 10 @a10d18 - dbits 18 @a10d18 - abits 11 @a11d9 - dbits 9 @a11d9 - abits 12 @a12d4 - dbits 4 @a12d4 - abits 13 @a13d2 - dbits 2 @a13d2 - abits 14 @a14d1 - dbits 1 @a14d1 - - groups 2 - ports 1 1 - wrmode 1 0 - enable 2 1 @a10d18 - enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 - transp 0 2 - clocks 2 3 - clkpol 2 3 -endbram - -# The syn_* attributes are described in: -# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx -attr_icase 1 - -match $__ECP5_PDPW16KD - # implicitly requested RAM or ROM - attribute !syn_ramstyle syn_ramstyle=auto - attribute !syn_romstyle syn_romstyle=auto - attribute !ram_block - attribute !rom_block - attribute !logic_block - min bits 2048 - min efficiency 5 - shuffle_enable A - make_transp - or_next_if_better -endmatch - -match $__ECP5_PDPW16KD - # explicitly requested RAM - attribute syn_ramstyle=block_ram ram_block - attribute !syn_romstyle - attribute !rom_block - attribute !logic_block - min wports 1 - shuffle_enable A - make_transp - or_next_if_better -endmatch - -match $__ECP5_PDPW16KD - # explicitly requested ROM - attribute syn_romstyle=ebr rom_block - attribute !syn_ramstyle - attribute !ram_block - attribute !logic_block - max wports 0 - shuffle_enable A - make_transp - or_next_if_better -endmatch - -match $__ECP5_DP16KD - # implicitly requested RAM or ROM - attribute !syn_ramstyle syn_ramstyle=auto - attribute !syn_romstyle syn_romstyle=auto - attribute !ram_block - attribute !rom_block - attribute !logic_block - min bits 2048 - min efficiency 5 - shuffle_enable A - or_next_if_better -endmatch - -match $__ECP5_DP16KD - # explicitly requested RAM - attribute syn_ramstyle=block_ram ram_block - attribute !syn_romstyle - attribute !rom_block - attribute !logic_block - min wports 1 - shuffle_enable A - or_next_if_better -endmatch - -match $__ECP5_DP16KD - # explicitly requested ROM - attribute syn_romstyle=ebr rom_block - attribute !syn_ramstyle - attribute !ram_block - attribute !logic_block - max wports 0 - shuffle_enable A -endmatch diff --git a/techlibs/ecp5/brams_map.v b/techlibs/ecp5/brams_map.v index edda17c02b1..310aedaf2f9 100644 --- a/techlibs/ecp5/brams_map.v +++ b/techlibs/ecp5/brams_map.v @@ -137,6 +137,8 @@ module \$__ECP5_PDPW16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN localparam CLKWMUX = CLKPOL2 ? "CLKA" : "INV"; localparam CLKRMUX = CLKPOL3 ? "CLKB" : "INV"; + localparam WRITEMODE_A = TRANSP2 ? "WRITETHROUGH" : "READBEFOREWRITE"; + PDPW16KD #( `include "bram_init_9_18_36.vh" .DATA_WIDTH_W(36), diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v index 756f0536621..ae124e7a384 100644 --- a/techlibs/ecp5/cells_bb.v +++ b/techlibs/ecp5/cells_bb.v @@ -652,10 +652,6 @@ module DCUA( parameter CH1_PROTOCOL = "8B10B"; parameter CH0_CDR_MAX_RATE = "2.5"; parameter CH1_CDR_MAX_RATE = "2.5"; - parameter CH0_TXDEPRE = "DISABLED"; - parameter CH1_TXDEPRE = "DISABLED"; - parameter CH0_TXDEPOST = "DISABLED"; - parameter CH1_TXDEPOST = "DISABLED"; endmodule (* blackbox *) diff --git a/techlibs/ecp5/cells_ff.vh b/techlibs/ecp5/cells_ff.vh index 6b745f391ee..501c1b3b294 100644 --- a/techlibs/ecp5/cells_ff.vh +++ b/techlibs/ecp5/cells_ff.vh @@ -1,12 +1,12 @@ // Diamond flip-flops -module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule module FD1P3BX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule module FD1P3DX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule module FD1P3IX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule module FD1P3JX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .DI(D), .Q(Q)); endmodule -module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .DI(D), .Q(Q)); endmodule +module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule module FD1S3BX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule module FD1S3DX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule module FD1S3IX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index 80f497cc39d..71ae9237be3 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -17,50 +17,35 @@ module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_SDFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_SDFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_SDFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_SDFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule - -module \$_SDFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_SDFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_SDFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_SDFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule - -module \$_DFFE_NN0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_DFFE_NN1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_DFFE_PN0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_DFFE_PN1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule - -module \$_DFFE_NP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_DFFE_NP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_DFFE_PP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule - -module \$_SDFFE_NN0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_SDFFE_NN1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_SDFFE_PN0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_SDFFE_PN1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule - -module \$_SDFFE_NP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_SDFFE_NP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_SDFFE_PP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule - -`ifdef ASYNC_PRLD -module \$_DLATCH_N_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(!E), .DI(1'b0), .M(D), .Q(Q)); endmodule -module \$_DLATCH_P_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(E), .DI(1'b0), .M(D), .Q(Q)); endmodule - -module \$_DFFSR_NNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule -module \$_DFFSR_NNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule -module \$_DFFSR_NPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule -module \$_DFFSR_NPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule - -module \$_DFFSR_PNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule -module \$_DFFSR_PNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule -module \$_DFFSR_PPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule -module \$_DFFSR_PPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule -`endif +module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule + +module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule + +module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule + +module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule + +module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule + +module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule `include "cells_ff.vh" `include "cells_io.vh" @@ -70,84 +55,105 @@ module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; + // Need to swap input ordering, and fix init accordingly, + // to match ABC's expectation of LUT inputs in non-decreasing + // delay order + localparam P_WIDTH = WIDTH < 4 ? 4 : WIDTH; + function [P_WIDTH-1:0] permute_index; + input [P_WIDTH-1:0] i; + integer j; + begin + permute_index = 0; + for (j = 0; j < P_WIDTH; j = j + 1) + permute_index[P_WIDTH-1 - j] = i[j]; + end + endfunction + + function [2**P_WIDTH-1:0] permute_init; + integer i; + begin + permute_init = 0; + for (i = 0; i < 2**P_WIDTH; i = i + 1) + permute_init[i] = LUT[permute_index(i)]; + end + endfunction + + parameter [2**P_WIDTH-1:0] P_LUT = permute_init(); + generate if (WIDTH == 1) begin - localparam [15:0] INIT = {{8{LUT[1]}}, {8{LUT[0]}}}; - LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y), + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), .A(1'b0), .B(1'b0), .C(1'b0), .D(A[0])); end else if (WIDTH == 2) begin - localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}}; - LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y), - .A(1'b0), .B(1'b0), .C(A[0]), .D(A[1])); + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), + .A(1'b0), .B(1'b0), .C(A[1]), .D(A[0])); end else if (WIDTH == 3) begin - localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[6]}}, {2{LUT[5]}}, {2{LUT[4]}}, {2{LUT[3]}}, {2{LUT[2]}}, {2{LUT[1]}}, {2{LUT[0]}}}; - LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y), - .A(1'b0), .B(A[0]), .C(A[1]), .D(A[2])); + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), + .A(1'b0), .B(A[2]), .C(A[1]), .D(A[0])); end else if (WIDTH == 4) begin - LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), + .A(A[3]), .B(A[2]), .C(A[1]), .D(A[0])); `ifndef NO_PFUMUX end else if (WIDTH == 5) begin wire f0, f1; - LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(Y)); + LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), + .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1])); + LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), + .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1])); + PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[0]), .Z(Y)); end else if (WIDTH == 6) begin wire f0, f1, f2, f3, g0, g1; - LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - - LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - - PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0)); - PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1)); - L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[5]), .Z(Y)); + LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), + .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); + LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), + .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); + + LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2), + .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); + LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3), + .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); + + PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[1]), .Z(g0)); + PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[1]), .Z(g1)); + L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[0]), .Z(Y)); end else if (WIDTH == 7) begin wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1; - LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - - LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - - LUT4 #(.INIT(LUT[79:64])) lut4 (.Z(f4), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[95:80])) lut5 (.Z(f5), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - - LUT4 #(.INIT(LUT[111: 96])) lut6 (.Z(f6), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[127:112])) lut7 (.Z(f7), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - - PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0)); - PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1)); - PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[4]), .Z(g2)); - PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[4]), .Z(g3)); - L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[5]), .Z(h0)); - L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[5]), .Z(h1)); - L6MUX21 mux7 (.D0(h0), .D1(h1), .SD(A[6]), .Z(Y)); + LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + + LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + + LUT4 #(.INIT(P_LUT[79:64])) lut4 (.Z(f4), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + LUT4 #(.INIT(P_LUT[95:80])) lut5 (.Z(f5), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + + LUT4 #(.INIT(P_LUT[111: 96])) lut6 (.Z(f6), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + LUT4 #(.INIT(P_LUT[127:112])) lut7 (.Z(f7), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + + PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[2]), .Z(g0)); + PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[2]), .Z(g1)); + PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[2]), .Z(g2)); + PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[2]), .Z(g3)); + L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[1]), .Z(h0)); + L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[1]), .Z(h1)); + L6MUX21 mux7 (.D0(h0), .D1(h1), .SD(A[0]), .Z(Y)); `endif end else begin wire _TECHMAP_FAIL_ = 1; diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 357fd917302..f467218cc02 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -1,78 +1,21 @@ // --------------------------------------- -(* abc9_lut=1, lib_whitebox *) module LUT4(input A, B, C, D, output Z); parameter [15:0] INIT = 16'h0000; wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0]; wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0]; wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0]; assign Z = A ? s1[1] : s1[0]; - specify - (A => Z) = 141; - (B => Z) = 275; - (C => Z) = 379; - (D => Z) = 379; - endspecify -endmodule - -// This is a placeholder for ABC9 to extract the area/delay -// cost of 5-input LUTs and is not intended to be instantiated -// LUT5 = 2x LUT4 + PFUMX -(* abc9_lut=2 *) -module \$__ABC9_LUT5 (input M0, D, C, B, A, output Z); - specify - (M0 => Z) = 151; - (D => Z) = 239; - (C => Z) = 373; - (B => Z) = 477; - (A => Z) = 477; - endspecify -endmodule - -// This is a placeholder for ABC9 to extract the area/delay -// of 6-input LUTs and is not intended to be instantiated -// LUT6 = 2x LUT5 + MUX2 -(* abc9_lut=4 *) -module \$__ABC9_LUT6 (input M1, M0, D, C, B, A, output Z); - specify - (M1 => Z) = 148; - (M0 => Z) = 292; - (D => Z) = 380; - (C => Z) = 514; - (B => Z) = 618; - (A => Z) = 618; - endspecify -endmodule - -// This is a placeholder for ABC9 to extract the area/delay -// of 7-input LUTs and is not intended to be instantiated -// LUT7 = 2x LUT6 + MUX2 -(* abc9_lut=8 *) -module \$__ABC9_LUT7 (input M2, M1, M0, D, C, B, A, output Z); - specify - (M2 => Z) = 148; - (M1 => Z) = 289; - (M0 => Z) = 433; - (D => Z) = 521; - (C => Z) = 655; - (B => Z) = 759; - (A => Z) = 759; - endspecify endmodule // --------------------------------------- -(* abc9_box, lib_whitebox *) +(* abc9_box_id=4, lib_whitebox *) module L6MUX21 (input D0, D1, SD, output Z); assign Z = SD ? D1 : D0; - specify - (D0 => Z) = 140; - (D1 => Z) = 141; - (SD => Z) = 148; - endspecify endmodule // --------------------------------------- -(* abc9_box, lib_whitebox *) +(* abc9_box_id=1, lib_whitebox *) module CCU2C( (* abc9_carry *) input CIN, @@ -88,8 +31,13 @@ module CCU2C( // First half wire LUT4_0, LUT2_0; +`ifdef _ABC + assign LUT4_0 = INIT0[{D0, C0, B0, A0}]; + assign LUT2_0 = INIT0[{2'b00, B0, A0}]; +`else LUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0)); LUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0)); +`endif wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN; assign S0 = LUT4_0 ^ gated_cin_0; @@ -98,39 +46,19 @@ module CCU2C( // Second half wire LUT4_1, LUT2_1; +`ifdef _ABC + assign LUT4_1 = INIT1[{D1, C1, B1, A1}]; + assign LUT2_1 = INIT1[{2'b00, B1, A1}]; +`else LUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1)); LUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1)); +`endif wire gated_cin_1 = (INJECT1_1 == "YES") ? 1'b0 : cout_0; assign S1 = LUT4_1 ^ gated_cin_1; wire gated_lut2_1 = (INJECT1_1 == "YES") ? 1'b0 : LUT2_1; assign COUT = (~LUT4_1 & gated_lut2_1) | (LUT4_1 & cout_0); - specify - (A0 => S0) = 379; - (B0 => S0) = 379; - (C0 => S0) = 275; - (D0 => S0) = 141; - (CIN => S0) = 257; - (A0 => S1) = 630; - (B0 => S1) = 630; - (C0 => S1) = 526; - (D0 => S1) = 392; - (A1 => S1) = 379; - (B1 => S1) = 379; - (C1 => S1) = 275; - (D1 => S1) = 141; - (CIN => S1) = 273; - (A0 => COUT) = 516; - (B0 => COUT) = 516; - (C0 => COUT) = 412; - (D0 => COUT) = 278; - (A1 => COUT) = 516; - (B1 => COUT) = 516; - (C1 => COUT) = 412; - (D1 => COUT) = 278; - (CIN => COUT) = 43; - endspecify endmodule // --------------------------------------- @@ -175,24 +103,19 @@ module TRELLIS_RAM16X2 ( endmodule // --------------------------------------- -(* abc9_box, lib_whitebox *) +(* abc9_box_id=3, lib_whitebox *) module PFUMX (input ALUT, BLUT, C0, output Z); assign Z = C0 ? ALUT : BLUT; - specify - (ALUT => Z) = 98; - (BLUT => Z) = 98; - (C0 => Z) = 151; - endspecify endmodule // --------------------------------------- -(* abc9_box, lib_whitebox *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, input WRE, input WCK, input [3:0] RAD, + /* (* abc9_arrival= *) */ output [3:0] DO ); parameter WCKMUX = "WCK"; @@ -223,16 +146,10 @@ module TRELLIS_DPR16X4 ( mem[WAD] <= DI; assign DO = mem[RAD]; - - specify - // TODO - (RAD *> DO) = 0; - endspecify endmodule // --------------------------------------- -(* abc9_box, lib_whitebox *) module DPR16X4C ( input [3:0] DI, input WCK, WRE, @@ -288,15 +205,10 @@ module DPR16X4C ( assign DO = ram[RAD]; - specify - // TODO - (RAD *> DO) = 0; - endspecify endmodule // --------------------------------------- -(* lib_whitebox *) module LUT2(input A, B, output Z); parameter [3:0] INIT = 4'h0; wire [1:0] s1 = B ? INIT[ 3:2] : INIT[1:0]; @@ -305,9 +217,6 @@ endmodule // --------------------------------------- -`ifdef YOSYS -(* abc9_flop=(SRMODE != "ASYNC"), abc9_box=(SRMODE == "ASYNC"), lib_whitebox *) -`endif module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); parameter GSR = "ENABLED"; parameter [127:0] CEMUX = "1"; @@ -354,38 +263,6 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); Q <= DI; end endgenerate - - generate - // TODO - if (CLKMUX == "INV") - specify - $setup(DI, negedge CLK, 0); - $setup(CE, negedge CLK, 0); - $setup(LSR, negedge CLK, 0); -`ifndef YOSYS - if (SRMODE == "ASYNC" && muxlsr) (negedge CLK => (Q : srval)) = 0; -`else - if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - if (!muxlsr && muxce) (negedge CLK => (Q : DI)) = 0; - endspecify - else - specify - $setup(DI, posedge CLK, 0); - $setup(CE, posedge CLK, 0); - $setup(LSR, posedge CLK, 0); -`ifndef YOSYS - if (SRMODE == "ASYNC" && muxlsr) (posedge CLK => (Q : srval)) = 0; -`else - if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - if (!muxlsr && muxce) (posedge CLK => (Q : DI)) = 0; - endspecify - endgenerate endmodule // --------------------------------------- diff --git a/techlibs/ecp5/dsp_map.v b/techlibs/ecp5/dsp_map.v index df54d1d9f9f..cb95ddb1c7d 100644 --- a/techlibs/ecp5/dsp_map.v +++ b/techlibs/ecp5/dsp_map.v @@ -10,7 +10,7 @@ module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); .A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .A4(A[4]), .A5(A[5]), .A6(A[6]), .A7(A[7]), .A8(A[8]), .A9(A[9]), .A10(A[10]), .A11(A[11]), .A12(A[12]), .A13(A[13]), .A14(A[14]), .A15(A[15]), .A16(A[16]), .A17(A[17]), .B0(B[0]), .B1(B[1]), .B2(B[2]), .B3(B[3]), .B4(B[4]), .B5(B[5]), .B6(B[6]), .B7(B[7]), .B8(B[8]), .B9(B[9]), .B10(B[10]), .B11(B[11]), .B12(B[12]), .B13(B[13]), .B14(B[14]), .B15(B[15]), .B16(B[16]), .B17(B[17]), .C17(1'b0), .C16(1'b0), .C15(1'b0), .C14(1'b0), .C13(1'b0), .C12(1'b0), .C11(1'b0), .C10(1'b0), .C9(1'b0), .C8(1'b0), .C7(1'b0), .C6(1'b0), .C5(1'b0), .C4(1'b0), .C3(1'b0), .C2(1'b0), .C1(1'b0), .C0(1'b0), - .SIGNEDA(A_SIGNED ? 1'b1 : 1'b0), .SIGNEDB(B_SIGNED ? 1'b1 : 1'b0), .SOURCEA(1'b0), .SOURCEB(1'b0), + .SIGNEDA(A_SIGNED), .SIGNEDB(B_SIGNED), .SOURCEA(1'b0), .SOURCEB(1'b0), .P0(Y[0]), .P1(Y[1]), .P2(Y[2]), .P3(Y[3]), .P4(Y[4]), .P5(Y[5]), .P6(Y[6]), .P7(Y[7]), .P8(Y[8]), .P9(Y[9]), .P10(Y[10]), .P11(Y[11]), .P12(Y[12]), .P13(Y[13]), .P14(Y[14]), .P15(Y[15]), .P16(Y[16]), .P17(Y[17]), .P18(Y[18]), .P19(Y[19]), .P20(Y[20]), .P21(Y[21]), .P22(Y[22]), .P23(Y[23]), .P24(Y[24]), .P25(Y[25]), .P26(Y[26]), .P27(Y[27]), .P28(Y[28]), .P29(Y[29]), .P30(Y[30]), .P31(Y[31]), .P32(Y[32]), .P33(Y[33]), .P34(Y[34]), .P35(Y[35]) ); diff --git a/techlibs/ecp5/ecp5_ffinit.cc b/techlibs/ecp5/ecp5_ffinit.cc index 0ecc8638848..dbd16cac913 100644 --- a/techlibs/ecp5/ecp5_ffinit.cc +++ b/techlibs/ecp5/ecp5_ffinit.cc @@ -26,7 +26,7 @@ PRIVATE_NAMESPACE_BEGIN struct Ecp5FfinitPass : public Pass { Ecp5FfinitPass() : Pass("ecp5_ffinit", "ECP5: handle FF init values") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -36,7 +36,7 @@ struct Ecp5FfinitPass : public Pass { log("If reset is not used, set the reset value to the init value, otherwise\n"); log("unmap out the reset (if not an async reset).\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ECP5_FFINIT pass (implement FF init values).\n"); @@ -63,11 +63,11 @@ struct Ecp5FfinitPass : public Pass { for (auto wire : module->selected_wires()) { - if (wire->attributes.count(ID::init) == 0) + if (wire->attributes.count("\\init") == 0) continue; SigSpec wirebits = sigmap(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); init_wires.insert(wire); for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) @@ -94,11 +94,11 @@ struct Ecp5FfinitPass : public Pass { } for (auto cell : module->selected_cells()) { - if (cell->type != ID(TRELLIS_FF)) + if (cell->type != "\\TRELLIS_FF") continue; - SigSpec sig_d = cell->getPort(ID(DI)); - SigSpec sig_q = cell->getPort(ID::Q); - SigSpec sig_lsr = cell->getPort(ID(LSR)); + SigSpec sig_d = cell->getPort("\\DI"); + SigSpec sig_q = cell->getPort("\\Q"); + SigSpec sig_lsr = cell->getPort("\\LSR"); if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1) continue; @@ -106,7 +106,9 @@ struct Ecp5FfinitPass : public Pass { SigBit bit_d = sigmap(sig_d[0]); SigBit bit_q = sigmap(sig_q[0]); - std::string regset = cell->getParam(ID(REGSET)).decode_string(); + std::string regset = "RESET"; + if (cell->hasParam("\\REGSET")) + regset = cell->getParam("\\REGSET").decode_string(); State resetState; if (regset == "SET") resetState = State::S1; @@ -133,7 +135,9 @@ struct Ecp5FfinitPass : public Pass { } if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) { - std::string srmode = cell->getParam(ID(SRMODE)).decode_string(); + std::string srmode = "LSR_OVER_CE"; + if (cell->hasParam("\\SRMODE")) + srmode = cell->getParam("\\SRMODE").decode_string(); if (srmode == "ASYNC") { log("Async reset value %c for FF cell %s inconsistent with init value %c.\n", resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0'); @@ -146,12 +150,14 @@ struct Ecp5FfinitPass : public Pass { module->addOrGate(NEW_ID, bit_d, bit_lsr, new_bit_d); } - cell->setPort(ID(DI), new_bit_d); - cell->setPort(ID(LSR), State::S0); + cell->setPort("\\DI", new_bit_d); + cell->setPort("\\LSR", State::S0); - if(cell->hasPort(ID(CE))) { - std::string cemux = cell->getParam(ID(CEMUX)).decode_string(); - SigSpec sig_ce = cell->getPort(ID(CE)); + if(cell->hasPort("\\CE")) { + std::string cemux = "CE"; + if (cell->hasParam("\\CEMUX")) + cemux = cell->getParam("\\CEMUX").decode_string(); + SigSpec sig_ce = cell->getPort("\\CE"); if (GetSize(sig_ce) >= 1) { SigBit bit_ce = sigmap(sig_ce[0]); Wire *new_bit_ce = module->addWire(NEW_ID); @@ -159,25 +165,25 @@ struct Ecp5FfinitPass : public Pass { module->addAndnotGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce); else module->addOrGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce); - cell->setPort(ID(CE), new_bit_ce); + cell->setPort("\\CE", new_bit_ce); } } - cell->setParam(ID(REGSET), val != State::S0 ? Const("SET") : Const("RESET")); + cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET")); handled_initbits.insert(bit_q); } } else { - cell->setParam(ID(REGSET), val != State::S0 ? Const("SET") : Const("RESET")); + cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET")); handled_initbits.insert(bit_q); } } for (auto wire : init_wires) { - if (wire->attributes.count(ID::init) == 0) + if (wire->attributes.count("\\init") == 0) continue; SigSpec wirebits = sigmap(wire); - Const &initval = wire->attributes.at(ID::init); + Const &initval = wire->attributes.at("\\init"); bool remove_attribute = true; for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) { @@ -188,7 +194,7 @@ struct Ecp5FfinitPass : public Pass { } if (remove_attribute) - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); } } } diff --git a/techlibs/ecp5/ecp5_gsr.cc b/techlibs/ecp5/ecp5_gsr.cc index 18d99cfb25f..2bc714b6fee 100644 --- a/techlibs/ecp5/ecp5_gsr.cc +++ b/techlibs/ecp5/ecp5_gsr.cc @@ -26,7 +26,7 @@ PRIVATE_NAMESPACE_BEGIN struct Ecp5GsrPass : public Pass { Ecp5GsrPass() : Pass("ecp5_gsr", "ECP5: handle GSR") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -40,7 +40,7 @@ struct Ecp5GsrPass : public Pass { log("is not set, otherwise it will be resolved to \"DISABLED\".\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ECP5_GSR pass (implement FF init values).\n"); @@ -85,7 +85,7 @@ struct Ecp5GsrPass : public Pass { continue; bool gsren = found_gsr; - if (cell->get_bool_attribute(ID(nogsr))) + if (cell->get_bool_attribute("\\nogsr")) gsren = false; cell->setParam(ID(GSR), gsren ? Const("ENABLED") : Const("DISABLED")); @@ -102,7 +102,7 @@ struct Ecp5GsrPass : public Pass { { if (cell->type != ID($_NOT_)) continue; - SigSpec sig_a = cell->getPort(ID::A), sig_y = cell->getPort(ID::Y); + SigSpec sig_a = cell->getPort(ID(A)), sig_y = cell->getPort(ID(Y)); if (GetSize(sig_a) < 1 || GetSize(sig_y) < 1) continue; SigBit a = sigmap(sig_a[0]); @@ -114,9 +114,9 @@ struct Ecp5GsrPass : public Pass { { if (cell->type != ID(TRELLIS_FF)) continue; - if (cell->getParam(ID(GSR)).decode_string() != "ENABLED") + if (!cell->hasParam(ID(GSR)) || cell->getParam(ID(GSR)).decode_string() != "ENABLED") continue; - if (cell->getParam(ID(SRMODE)).decode_string() != "ASYNC") + if (!cell->hasParam(ID(SRMODE)) || cell->getParam(ID(SRMODE)).decode_string() != "ASYNC") continue; SigSpec sig_lsr = cell->getPort(ID(LSR)); if (GetSize(sig_lsr) < 1) diff --git a/techlibs/xilinx/lut4_lutrams.txt b/techlibs/ecp5/lutram.txt similarity index 67% rename from techlibs/xilinx/lut4_lutrams.txt rename to techlibs/ecp5/lutram.txt index 2b344a9eecb..b943574290e 100644 --- a/techlibs/xilinx/lut4_lutrams.txt +++ b/techlibs/ecp5/lutram.txt @@ -1,7 +1,7 @@ -bram $__XILINX_RAM16X1D +bram $__TRELLIS_DPR16X4 init 1 abits 4 - dbits 1 + dbits 4 groups 2 ports 1 1 wrmode 0 1 @@ -11,9 +11,7 @@ bram $__XILINX_RAM16X1D clkpol 0 2 endbram - -match $__XILINX_RAM16X1D - min bits 2 - min wports 1 +match $__TRELLIS_DPR16X4 make_outreg + min wports 1 endmatch diff --git a/techlibs/ecp5/lutrams.txt b/techlibs/ecp5/lutrams.txt deleted file mode 100644 index 9e6a23eba7e..00000000000 --- a/techlibs/ecp5/lutrams.txt +++ /dev/null @@ -1,26 +0,0 @@ -bram $__TRELLIS_DPR16X4 - init 1 - abits 4 - dbits 4 - groups 2 - ports 1 1 - wrmode 0 1 - enable 0 1 - transp 0 0 - clocks 0 1 - clkpol 0 2 -endbram - -# The syn_* attributes are described in: -# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx -attr_icase 1 - -match $__TRELLIS_DPR16X4 - attribute !syn_ramstyle syn_ramstyle=auto syn_ramstyle=distributed - attribute !syn_romstyle syn_romstyle=auto - attribute !ram_block - attribute !rom_block - attribute !logic_block - make_outreg - min wports 1 -endmatch diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 0874b954a8a..4cbb56ea16c 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -30,12 +30,7 @@ struct SynthEcp5Pass : public ScriptPass { SynthEcp5Pass() : ScriptPass("synth_ecp5", "synthesis for ECP5 FPGAs") { } - void on_register() override - { - RTLIL::constpad["synth_ecp5.abc9.W"] = "300"; - } - - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -66,11 +61,8 @@ struct SynthEcp5Pass : public ScriptPass log(" -noflatten\n"); log(" do not flatten design before synthesis\n"); log("\n"); - log(" -dff\n"); - log(" run 'abc'/'abc9' with -dff option\n"); - log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log(" -noccu2\n"); log(" do not use CCU2 cells in output netlist\n"); @@ -87,9 +79,6 @@ struct SynthEcp5Pass : public ScriptPass log(" -nowidelut\n"); log(" do not use PFU muxes to implement LUTs larger than LUT4s\n"); log("\n"); - log(" -asyncprld\n"); - log(" use async PRLD mode to implement DLATCH and DFFSR (EXPERIMENTAL)\n"); - log("\n"); log(" -abc2\n"); log(" run two passes of 'abc' for slightly improved logic density\n"); log("\n"); @@ -110,9 +99,9 @@ struct SynthEcp5Pass : public ScriptPass } string top_opt, blif_file, edif_file, json_file; - bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, nodsp, vpr; + bool noccu2, nodffe, nobram, nolutram, nowidelut, flatten, retime, abc2, abc9, nodsp, vpr; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; blif_file = ""; @@ -123,9 +112,7 @@ struct SynthEcp5Pass : public ScriptPass nobram = false; nolutram = false; nowidelut = false; - asyncprld = false; flatten = true; - dff = false; retime = false; abc2 = false; vpr = false; @@ -133,7 +120,7 @@ struct SynthEcp5Pass : public ScriptPass nodsp = false; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -173,10 +160,6 @@ struct SynthEcp5Pass : public ScriptPass flatten = false; continue; } - if (args[argidx] == "-dff") { - dff = true; - continue; - } if (args[argidx] == "-retime") { retime = true; continue; @@ -193,10 +176,6 @@ struct SynthEcp5Pass : public ScriptPass nobram = true; continue; } - if (args[argidx] == "-asyncprld") { - asyncprld = true; - continue; - } if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") { nolutram = true; continue; @@ -239,11 +218,11 @@ struct SynthEcp5Pass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { - run("read_verilog -lib -specify +/ecp5/cells_sim.v +/ecp5/cells_bb.v"); + run("read_verilog -D_ABC -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); } @@ -279,22 +258,20 @@ struct SynthEcp5Pass : public ScriptPass if (!nobram && check_label("map_bram", "(skip if -nobram)")) { - run("memory_bram -rules +/ecp5/brams.txt"); + run("memory_bram -rules +/ecp5/bram.txt"); run("techmap -map +/ecp5/brams_map.v"); } if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { - run("memory_bram -rules +/ecp5/lutrams.txt"); + run("memory_bram -rules +/ecp5/lutram.txt"); run("techmap -map +/ecp5/lutrams_map.v"); } if (check_label("map_ffram")) { run("opt -fast -mux_undef -undriven -fine"); - run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block " - "-attr syn_ramstyle=auto -attr syn_ramstyle=registers " - "-attr syn_romstyle=auto -attr syn_romstyle=logic"); + run("memory_map"); run("opt -undriven -fine"); } @@ -304,20 +281,18 @@ struct SynthEcp5Pass : public ScriptPass run("techmap"); else run("techmap -map +/techmap.v -map +/ecp5/arith_map.v"); - run("opt -fast"); if (retime || help_mode) - run("abc -dff -D 1", "(only if -retime)"); + run("abc -dff", "(only if -retime)"); } if (check_label("map_ffs")) { + run("dffsr2dff"); run("dff2dffs"); run("opt_clean"); if (!nodffe) - run("dff2dffe -direct-match $_DFF_* -direct-match $_SDFF_*"); - if ((abc9 && dff) || help_mode) - run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff"); - run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : ""))); + run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); + run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); run("opt_expr -undriven -mux_undef"); run("simplemap"); run("ecp5_ffinit"); @@ -328,45 +303,37 @@ struct SynthEcp5Pass : public ScriptPass if (check_label("map_luts")) { - if (abc2 || help_mode) + if (abc2 || help_mode) { run("abc", " (only if -abc2)"); - if (!asyncprld || help_mode) - run("techmap -map +/ecp5/latches_map.v", "(skip if -asyncprld)"); + } + std::string techmap_args = "-map +/ecp5/latches_map.v"; + if (abc9) + techmap_args += " -map +/ecp5/abc9_map.v -max_iter 1"; + run("techmap " + techmap_args); if (abc9) { - std::string abc9_opts; + run("read_verilog -icells -lib +/ecp5/abc9_model.v"); if (nowidelut) - abc9_opts += " -maxlut 4"; - std::string k = "synth_ecp5.abc9.W"; - if (active_design && active_design->scratchpad.count(k)) - abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str()); + run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs"); else - abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); - if (nowidelut) - abc9_opts += " -maxlut 4"; - if (dff) - abc9_opts += " -dff"; - run("abc9" + abc9_opts); + run("abc9 -lut +/ecp5/abc9_5g.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs"); + run("techmap -map +/ecp5/abc9_unmap.v"); } else { - std::string abc_args = " -dress"; if (nowidelut) - abc_args += " -lut 4"; + run("abc -lut 4 -dress"); else - abc_args += " -lut 4:7"; - if (dff) - abc_args += " -dff"; - run("abc" + abc_args); + run("abc -lut 4:7 -dress"); } run("clean"); } if (check_label("map_cells")) { - if (help_mode) - run("techmap -map +/ecp5/cells_map.v", "(skip if -vpr)"); - else if (!vpr) - run("techmap -map +/ecp5/cells_map.v"); - run("opt_lut_ins -tech ecp5"); + if (vpr) + run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); + else + run("techmap -map +/ecp5/cells_map.v", "(with -D NO_LUT in vpr mode)"); + run("clean"); } diff --git a/techlibs/efinix/Makefile.inc b/techlibs/efinix/Makefile.inc index 69665982c88..5013f7fc135 100644 --- a/techlibs/efinix/Makefile.inc +++ b/techlibs/efinix/Makefile.inc @@ -7,4 +7,4 @@ $(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_sim.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/brams_map.v)) -$(eval $(call add_share_file,share/efinix,techlibs/efinix/brams.txt)) +$(eval $(call add_share_file,share/efinix,techlibs/efinix/bram.txt)) diff --git a/techlibs/efinix/arith_map.v b/techlibs/efinix/arith_map.v index 4dac360b964..178f57bc570 100644 --- a/techlibs/efinix/arith_map.v +++ b/techlibs/efinix/arith_map.v @@ -26,33 +26,24 @@ module _80_efinix_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; - (* force_downto *) output [Y_WIDTH-1:0] CO; wire CIx; - (* force_downto *) wire [Y_WIDTH-1:0] COx; wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; - (* force_downto *) wire [Y_WIDTH-1:0] C = { COx, CIx }; EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) @@ -85,4 +76,4 @@ module _80_efinix_alu (A, B, CI, BI, X, Y, CO); /* End implementation */ assign X = AA ^ BB; -endmodule +endmodule \ No newline at end of file diff --git a/techlibs/efinix/brams.txt b/techlibs/efinix/bram.txt similarity index 100% rename from techlibs/efinix/brams.txt rename to techlibs/efinix/bram.txt diff --git a/techlibs/efinix/cells_map.v b/techlibs/efinix/cells_map.v index 1090f8b279d..3ecec3bac0b 100644 --- a/techlibs/efinix/cells_map.v +++ b/techlibs/efinix/cells_map.v @@ -34,7 +34,6 @@ module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; diff --git a/techlibs/efinix/efinix_fixcarry.cc b/techlibs/efinix/efinix_fixcarry.cc index 486b8e89cf0..b7cd995b8e3 100644 --- a/techlibs/efinix/efinix_fixcarry.cc +++ b/techlibs/efinix/efinix_fixcarry.cc @@ -39,12 +39,12 @@ static void fix_carry_chain(Module *module) for (auto cell : module->cells()) { - if (cell->type == ID(EFX_ADD)) { - SigBit bit_i0 = get_bit_or_zero(cell->getPort(ID(I0))); - SigBit bit_i1 = get_bit_or_zero(cell->getPort(ID(I1))); + if (cell->type == "\\EFX_ADD") { + SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0")); + SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1")); if (bit_i0 == State::S0 && bit_i1== State::S0) { - SigBit bit_ci = get_bit_or_zero(cell->getPort(ID::CI)); - SigBit bit_o = sigmap(cell->getPort(ID::O)); + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI")); + SigBit bit_o = sigmap(cell->getPort("\\O")); ci_bits.insert(bit_ci); mapping_bits[bit_ci] = bit_o; } @@ -54,10 +54,10 @@ static void fix_carry_chain(Module *module) vector adders_to_fix_cells; for (auto cell : module->cells()) { - if (cell->type == ID(EFX_ADD)) { - SigBit bit_ci = get_bit_or_zero(cell->getPort(ID::CI)); - SigBit bit_i0 = get_bit_or_zero(cell->getPort(ID(I0))); - SigBit bit_i1 = get_bit_or_zero(cell->getPort(ID(I1))); + if (cell->type == "\\EFX_ADD") { + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI")); + SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0")); + SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1")); SigBit canonical_bit = sigmap(bit_ci); if (!ci_bits.count(canonical_bit)) continue; @@ -71,26 +71,26 @@ static void fix_carry_chain(Module *module) for (auto cell : adders_to_fix_cells) { - SigBit bit_ci = get_bit_or_zero(cell->getPort(ID::CI)); + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI")); SigBit canonical_bit = sigmap(bit_ci); auto bit = mapping_bits.at(canonical_bit); log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell)); - Cell *c = module->addCell(NEW_ID, ID(EFX_ADD)); + Cell *c = module->addCell(NEW_ID, "\\EFX_ADD"); SigBit new_bit = module->addWire(NEW_ID); - c->setParam(ID(I0_POLARITY), State::S1); - c->setParam(ID(I1_POLARITY), State::S1); - c->setPort(ID(I0), bit); - c->setPort(ID(I1), State::S1); - c->setPort(ID::CI, State::S0); - c->setPort(ID::CO, new_bit); + c->setParam("\\I0_POLARITY", State::S1); + c->setParam("\\I1_POLARITY", State::S1); + c->setPort("\\I0", bit); + c->setPort("\\I1", State::S1); + c->setPort("\\CI", State::S0); + c->setPort("\\CO", new_bit); - cell->setPort(ID::CI, new_bit); + cell->setPort("\\CI", new_bit); } } struct EfinixCarryFixPass : public Pass { EfinixCarryFixPass() : Pass("efinix_fixcarry", "Efinix: fix carry chain") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -99,9 +99,9 @@ struct EfinixCarryFixPass : public Pass { log("Add Efinix adders to fix carry chain if needed.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing EFINIX_FIXCARRY pass (fix invalid carry chain).\n"); + log_header(design, "Executing efinix_fixcarry pass (fix invalid carry chain).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) diff --git a/techlibs/efinix/efinix_gbuf.cc b/techlibs/efinix/efinix_gbuf.cc index ae191359a70..e75fb3f4d9a 100644 --- a/techlibs/efinix/efinix_gbuf.cc +++ b/techlibs/efinix/efinix_gbuf.cc @@ -34,14 +34,14 @@ static void handle_gbufs(Module *module) for (auto cell : module->cells()) { - if (cell->type == ID(EFX_FF)) { - for (auto bit : sigmap(cell->getPort(ID::CLK))) + if (cell->type == "\\EFX_FF") { + for (auto bit : sigmap(cell->getPort("\\CLK"))) clk_bits.insert(bit); } - if (cell->type == ID(EFX_RAM_5K)) { - for (auto bit : sigmap(cell->getPort(ID(RCLK)))) + if (cell->type == "\\EFX_RAM_5K") { + for (auto bit : sigmap(cell->getPort("\\RCLK"))) clk_bits.insert(bit); - for (auto bit : sigmap(cell->getPort(ID(WCLK)))) + for (auto bit : sigmap(cell->getPort("\\WCLK"))) clk_bits.insert(bit); } } @@ -59,11 +59,11 @@ static void handle_gbufs(Module *module) if (!clk_bits.count(canonical_bit)) continue; - Cell *c = module->addCell(NEW_ID, ID(EFX_GBUFCE)); + Cell *c = module->addCell(NEW_ID, "\\EFX_GBUFCE"); SigBit new_bit = module->addWire(NEW_ID); - c->setParam(ID(CE_POLARITY), State::S1); - c->setPort(ID::O, new_bit); - c->setPort(ID(CE), State::S1); + c->setParam("\\CE_POLARITY", State::S1); + c->setPort("\\O", new_bit); + c->setPort("\\CE", State::S1); pad_bits.push_back(make_pair(c, bit)); rewrite_bits[canonical_bit] = new_bit; @@ -82,12 +82,12 @@ static void handle_gbufs(Module *module) module->rewrite_sigspecs(rewrite_function); for (auto &it : pad_bits) - it.first->setPort(ID::I, it.second); + it.first->setPort("\\I", it.second); } struct EfinixGbufPass : public Pass { EfinixGbufPass() : Pass("efinix_gbuf", "Efinix: insert global clock buffers") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -96,7 +96,7 @@ struct EfinixGbufPass : public Pass { log("Add Efinix global clock buffers to top module as needed.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing efinix_gbuf pass (insert global clock buffers).\n"); diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index 6ca44eed140..26a8d4edac0 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -30,7 +30,7 @@ struct SynthEfinixPass : public ScriptPass { SynthEfinixPass() : ScriptPass("synth_efinix", "synthesis for Efinix FPGAs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -58,10 +58,7 @@ struct SynthEfinixPass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); - log("\n"); - log(" -nobram\n"); - log(" do not use EFX_RAM_5K cells in output netlist\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -70,19 +67,18 @@ struct SynthEfinixPass : public ScriptPass } string top_opt, edif_file, json_file; - bool flatten, retime, nobram; + bool flatten, retime; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; edif_file = ""; json_file = ""; flatten = true; retime = false; - nobram = false; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -118,10 +114,6 @@ struct SynthEfinixPass : public ScriptPass retime = true; continue; } - if (args[argidx] == "-nobram") { - nobram = true; - continue; - } break; } extra_args(args, argidx, design); @@ -137,7 +129,7 @@ struct SynthEfinixPass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { @@ -158,30 +150,26 @@ struct SynthEfinixPass : public ScriptPass run("synth -run coarse"); } - if (!nobram || check_label("map_bram", "(skip if -nobram)")) + if (check_label("map_bram", "(skip if -nobram)")) { - run("memory_bram -rules +/efinix/brams.txt"); + run("memory_bram -rules +/efinix/bram.txt"); run("techmap -map +/efinix/brams_map.v"); run("setundef -zero -params t:EFX_RAM_5K"); } - if (check_label("map_ffram")) + if (check_label("fine")) { run("opt -fast -mux_undef -undriven -fine"); run("memory_map"); run("opt -undriven -fine"); - } - - if (check_label("map_gates")) - { run("techmap -map +/techmap.v -map +/efinix/arith_map.v"); - run("opt -fast"); if (retime || help_mode) - run("abc -dff -D 1", "(only if -retime)"); + run("abc -dff", "(only if -retime)"); } if (check_label("map_ffs")) { + run("dffsr2dff"); run("techmap -D NO_LUT -map +/efinix/cells_map.v"); run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit"); run("opt_expr -mux_undef"); @@ -206,7 +194,7 @@ struct SynthEfinixPass : public ScriptPass run("efinix_fixcarry"); run("clean"); } - + if (check_label("check")) { run("hierarchy -check"); diff --git a/techlibs/gowin/Makefile.inc b/techlibs/gowin/Makefile.inc index 0756e3bcf35..d2853704bc2 100644 --- a/techlibs/gowin/Makefile.inc +++ b/techlibs/gowin/Makefile.inc @@ -2,15 +2,16 @@ OBJS += techlibs/gowin/synth_gowin.o OBJS += techlibs/gowin/determine_init.o -GENFILES += techlibs/gowin/bram_init_16.vh $(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_map.v)) $(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_sim.v)) $(eval $(call add_share_file,share/gowin,techlibs/gowin/arith_map.v)) $(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_map.v)) -$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams.txt)) -$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams_map.v)) -$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams.txt)) +$(eval $(call add_share_file,share/gowin,techlibs/gowin/bram.txt)) +$(eval $(call add_share_file,share/gowin,techlibs/gowin/drams_map.v)) +$(eval $(call add_share_file,share/gowin,techlibs/gowin/dram.txt)) + + $(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_init3.vh)) diff --git a/techlibs/gowin/arith_map.v b/techlibs/gowin/arith_map.v index 42aaba8700a..b6f9e8c3862 100644 --- a/techlibs/gowin/arith_map.v +++ b/techlibs/gowin/arith_map.v @@ -26,29 +26,21 @@ module _80_gw1n_alu(A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; - (* force_downto *) output [Y_WIDTH-1:0] CO; wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = B_buf; - (* force_downto *) wire [Y_WIDTH-1:0] C = {CO, CI}; genvar i; diff --git a/techlibs/gowin/brams.txt b/techlibs/gowin/bram.txt similarity index 100% rename from techlibs/gowin/brams.txt rename to techlibs/gowin/bram.txt diff --git a/techlibs/gowin/cells_map.v b/techlibs/gowin/cells_map.v index 5460274cacf..aee912256c4 100644 --- a/techlibs/gowin/cells_map.v +++ b/techlibs/gowin/cells_map.v @@ -67,82 +67,82 @@ module \$_DFFE_NN_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, outp endmodule // DFFR D Flip-Flop with Synchronous Reset -module \$_SDFF_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +module \$__DFFS_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule -module \$_SDFF_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +module \$__DFFS_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule // DFFNR D Flip-Flop with Negative-Edge Clock and Synchronous Reset -module \$_SDFF_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +module \$__DFFS_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule -module \$_SDFF_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +module \$__DFFS_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule // DFFRE D Flip-Flop with Clock Enable and Synchronous Reset -module \$_SDFFE_PN0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFSE_PN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule -module \$_SDFFE_PP0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFSE_PP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule // DFFNRE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset -module \$_SDFFE_NN0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFSE_NN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule -module \$_SDFFE_NP0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFSE_NP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule // DFFS D Flip-Flop with Synchronous Set -module \$_SDFF_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +module \$__DFFS_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule -module \$_SDFF_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +module \$__DFFS_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule // DFFNS D Flip-Flop with Negative-Edge Clock and Synchronous Set -module \$_SDFF_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +module \$__DFFS_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule -module \$_SDFF_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +module \$__DFFS_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule // DFFSE D Flip-Flop with Clock Enable and Synchronous Set -module \$_SDFFE_PN1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFSE_PN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule -module \$_SDFFE_PP1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFSE_PP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule // DFFNSE D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set -module \$_SDFFE_NN1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFSE_NN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule -module \$_SDFFE_NP1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFSE_NP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule @@ -188,41 +188,41 @@ module \$_DFF_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, outp endmodule // DFFPE D Flip-Flop with Clock Enable and Asynchronous Preset -module \$_DFFE_PP1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFE_PP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule -module \$_DFFE_PN1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFE_PN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule // DFFNPE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset -module \$_DFFE_NP1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFE_NP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule -module \$_DFFE_NN1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFE_NN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; endmodule // DFFCE D Flip-Flop with Clock Enable and Asynchronous Clear -module \$_DFFE_PP0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFE_PP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule -module \$_DFFE_PN0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFE_PN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule // DFFNCE D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear -module \$_DFFE_NP0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFE_NP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule -module \$_DFFE_NN0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +module \$__DFFE_NN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; endmodule @@ -232,7 +232,6 @@ module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; diff --git a/techlibs/gowin/determine_init.cc b/techlibs/gowin/determine_init.cc index 15ff115debb..d9a0880f6cc 100644 --- a/techlibs/gowin/determine_init.cc +++ b/techlibs/gowin/determine_init.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct DetermineInitPass : public Pass { DetermineInitPass() : Pass("determine_init", "Determine the init value of cells") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" determine_init [selection]\n"); @@ -44,7 +44,7 @@ struct DetermineInitPass : public Pass { return init; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing DETERMINE_INIT pass (determine init value for cells).\n"); @@ -55,12 +55,12 @@ struct DetermineInitPass : public Pass { { for (auto cell : module->selected_cells()) { - if (cell->type == ID(RAM16S4)) + if (cell->type == "\\RAM16S4") { - cell->setParam(ID(INIT_0), determine_init(cell->getParam(ID(INIT_0)))); - cell->setParam(ID(INIT_1), determine_init(cell->getParam(ID(INIT_1)))); - cell->setParam(ID(INIT_2), determine_init(cell->getParam(ID(INIT_2)))); - cell->setParam(ID(INIT_3), determine_init(cell->getParam(ID(INIT_3)))); + cell->setParam("\\INIT_0", determine_init(cell->getParam("\\INIT_0"))); + cell->setParam("\\INIT_1", determine_init(cell->getParam("\\INIT_1"))); + cell->setParam("\\INIT_2", determine_init(cell->getParam("\\INIT_2"))); + cell->setParam("\\INIT_3", determine_init(cell->getParam("\\INIT_3"))); cnt++; } } diff --git a/techlibs/gowin/lutrams.txt b/techlibs/gowin/dram.txt similarity index 100% rename from techlibs/gowin/lutrams.txt rename to techlibs/gowin/dram.txt diff --git a/techlibs/gowin/lutrams_map.v b/techlibs/gowin/drams_map.v similarity index 100% rename from techlibs/gowin/lutrams_map.v rename to techlibs/gowin/drams_map.v diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc index 32d9cc0a5d9..6cf058f292a 100644 --- a/techlibs/gowin/synth_gowin.cc +++ b/techlibs/gowin/synth_gowin.cc @@ -29,7 +29,7 @@ struct SynthGowinPass : public ScriptPass { SynthGowinPass() : ScriptPass("synth_gowin", "synthesis for Gowin FPGAs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -55,23 +55,23 @@ struct SynthGowinPass : public ScriptPass log(" -nobram\n"); log(" do not use BRAM cells in output netlist\n"); log("\n"); - log(" -nolutram\n"); + log(" -nodram\n"); log(" do not use distributed RAM cells in output netlist\n"); log("\n"); log(" -noflatten\n"); log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log(" -nowidelut\n"); log(" do not use muxes to implement LUTs larger than LUT4s\n"); log("\n"); log(" -noiopads\n"); log(" do not emit IOB at top level ports\n"); - //log("\n"); - //log(" -abc9\n"); - //log(" use new ABC9 flow (EXPERIMENTAL)\n"); + log("\n"); + log(" -abc9\n"); + log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -80,9 +80,9 @@ struct SynthGowinPass : public ScriptPass } string top_opt, vout_file; - bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads; + bool retime, nobram, nodram, flatten, nodffe, nowidelut, abc9, noiopads; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; vout_file = ""; @@ -90,13 +90,13 @@ struct SynthGowinPass : public ScriptPass flatten = true; nobram = false; nodffe = false; - nolutram = false; + nodram = false; nowidelut = false; abc9 = false; noiopads = false; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -128,8 +128,8 @@ struct SynthGowinPass : public ScriptPass nobram = true; continue; } - if (args[argidx] == "-nolutram" || /*deprecated*/args[argidx] == "-nodram") { - nolutram = true; + if (args[argidx] == "-nodram") { + nodram = true; continue; } if (args[argidx] == "-nodffe") { @@ -144,10 +144,10 @@ struct SynthGowinPass : public ScriptPass nowidelut = true; continue; } - //if (args[argidx] == "-abc9") { - // abc9 = true; - // continue; - //} + if (args[argidx] == "-abc9") { + abc9 = true; + continue; + } if (args[argidx] == "-noiopads") { noiopads = true; continue; @@ -167,7 +167,7 @@ struct SynthGowinPass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { @@ -188,41 +188,38 @@ struct SynthGowinPass : public ScriptPass run("synth -run coarse"); } - if (!nobram && check_label("map_bram", "(skip if -nobram)")) + if (!nobram && check_label("bram", "(skip if -nobram)")) { - run("memory_bram -rules +/gowin/brams.txt"); - run("techmap -map +/gowin/brams_map.v"); + run("memory_bram -rules +/gowin/bram.txt"); + run("techmap -map +/gowin/brams_map.v -map +/gowin/cells_sim.v"); } - if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) + if (!nodram && check_label("dram", "(skip if -nodram)")) { - run("memory_bram -rules +/gowin/lutrams.txt"); - run("techmap -map +/gowin/lutrams_map.v"); + run("memory_bram -rules +/gowin/dram.txt"); + run("techmap -map +/gowin/drams_map.v"); run("determine_init"); } - if (check_label("map_ffram")) + if (check_label("fine")) { run("opt -fast -mux_undef -undriven -fine"); run("memory_map"); run("opt -undriven -fine"); - } - - if (check_label("map_gates")) - { run("techmap -map +/techmap.v -map +/gowin/arith_map.v"); - run("opt -fast"); + run("techmap -map +/techmap.v"); if (retime || help_mode) - run("abc -dff -D 1", "(only if -retime)"); + run("abc -dff", "(only if -retime)"); run("splitnets"); } if (check_label("map_ffs")) { + run("dffsr2dff"); run("dff2dffs -match-init"); run("opt_clean"); if (!nodffe) - run("dff2dffe -direct-match $_DFF_* -direct-match $_SDFF_*"); + run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); run("techmap -map +/gowin/cells_map.v"); run("opt_expr -mux_undef"); run("simplemap"); @@ -230,13 +227,13 @@ struct SynthGowinPass : public ScriptPass if (check_label("map_luts")) { - /*if (nowidelut && abc9) { + if (nowidelut && abc9) { run("abc9 -lut 4"); - } else*/ if (nowidelut && !abc9) { + } else if (nowidelut && !abc9) { run("abc -lut 4"); - } else /*if (!nowidelut && abc9) { + } else if (!nowidelut && abc9) { run("abc9 -lut 4:8"); - } else*/ if (!nowidelut && !abc9) { + } else if (!nowidelut && !abc9) { run("abc -lut 4:8"); } run("clean"); @@ -245,13 +242,13 @@ struct SynthGowinPass : public ScriptPass if (check_label("map_cells")) { run("techmap -map +/gowin/cells_map.v"); - run("opt_lut_ins -tech gowin"); run("setundef -undriven -params -zero"); run("hilomap -singleton -hicell VCC V -locell GND G"); if (!noiopads || help_mode) run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O " "-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)"); run("clean"); + } if (check_label("check")) diff --git a/techlibs/greenpak4/cells_map.v b/techlibs/greenpak4/cells_map.v index 316be3f7364..51c85183d29 100644 --- a/techlibs/greenpak4/cells_map.v +++ b/techlibs/greenpak4/cells_map.v @@ -115,7 +115,6 @@ module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; @@ -151,7 +150,6 @@ module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP); input wire CE; input wire CLK; output reg OUT; - (* force_downto *) output reg[WIDTH-1:0] POUT; input wire RST; input wire UP; diff --git a/techlibs/greenpak4/greenpak4_dffinv.cc b/techlibs/greenpak4/greenpak4_dffinv.cc index b8797bc1993..d57e978a0ad 100644 --- a/techlibs/greenpak4/greenpak4_dffinv.cc +++ b/techlibs/greenpak4/greenpak4_dffinv.cc @@ -33,37 +33,37 @@ void invert_gp_dff(Cell *cell, bool invert_input) if (!invert_input) { - Const initval = cell->getParam(ID::INIT); + Const initval = cell->getParam("\\INIT"); if (GetSize(initval) >= 1) { if (initval.bits[0] == State::S0) initval.bits[0] = State::S1; else if (initval.bits[0] == State::S1) initval.bits[0] = State::S0; - cell->setParam(ID::INIT, initval); + cell->setParam("\\INIT", initval); } if (cell_type_r && cell_type_s) { - Const srmode = cell->getParam(ID(SRMODE)); + Const srmode = cell->getParam("\\SRMODE"); if (GetSize(srmode) >= 1) { if (srmode.bits[0] == State::S0) srmode.bits[0] = State::S1; else if (srmode.bits[0] == State::S1) srmode.bits[0] = State::S0; - cell->setParam(ID(SRMODE), srmode); + cell->setParam("\\SRMODE", srmode); } } else { if (cell_type_r) { - cell->setPort(ID(nSET), cell->getPort(ID(nRST))); - cell->unsetPort(ID(nRST)); + cell->setPort("\\nSET", cell->getPort("\\nRST")); + cell->unsetPort("\\nRST"); cell_type_r = false; cell_type_s = true; } else if (cell_type_s) { - cell->setPort(ID(nRST), cell->getPort(ID(nSET))); - cell->unsetPort(ID(nSET)); + cell->setPort("\\nRST", cell->getPort("\\nSET")); + cell->unsetPort("\\nSET"); cell_type_r = true; cell_type_s = false; } @@ -71,12 +71,12 @@ void invert_gp_dff(Cell *cell, bool invert_input) } if (cell_type_i) { - cell->setPort(ID::Q, cell->getPort(ID(nQ))); - cell->unsetPort(ID(nQ)); + cell->setPort("\\Q", cell->getPort("\\nQ")); + cell->unsetPort("\\nQ"); cell_type_i = false; } else { - cell->setPort(ID(nQ), cell->getPort(ID::Q)); - cell->unsetPort(ID::Q); + cell->setPort("\\nQ", cell->getPort("\\Q")); + cell->unsetPort("\\Q"); cell_type_i = true; } @@ -91,7 +91,7 @@ void invert_gp_dff(Cell *cell, bool invert_input) struct Greenpak4DffInvPass : public Pass { Greenpak4DffInvPass() : Pass("greenpak4_dffinv", "merge greenpak4 inverters and DFF/latches") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" greenpak4_dffinv [options] [selection]\n"); @@ -99,7 +99,7 @@ struct Greenpak4DffInvPass : public Pass { log("Merge GP_INV cells with GP_DFF* and GP_DLATCH* cells.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing GREENPAK4_DFFINV pass (merge input/output inverters into FF/latch cells).\n"); @@ -115,23 +115,23 @@ struct Greenpak4DffInvPass : public Pass { extra_args(args, argidx, design); pool gp_dff_types; - gp_dff_types.insert(ID(GP_DFF)); - gp_dff_types.insert(ID(GP_DFFI)); - gp_dff_types.insert(ID(GP_DFFR)); - gp_dff_types.insert(ID(GP_DFFRI)); - gp_dff_types.insert(ID(GP_DFFS)); - gp_dff_types.insert(ID(GP_DFFSI)); - gp_dff_types.insert(ID(GP_DFFSR)); - gp_dff_types.insert(ID(GP_DFFSRI)); - - gp_dff_types.insert(ID(GP_DLATCH)); - gp_dff_types.insert(ID(GP_DLATCHI)); - gp_dff_types.insert(ID(GP_DLATCHR)); - gp_dff_types.insert(ID(GP_DLATCHRI)); - gp_dff_types.insert(ID(GP_DLATCHS)); - gp_dff_types.insert(ID(GP_DLATCHSI)); - gp_dff_types.insert(ID(GP_DLATCHSR)); - gp_dff_types.insert(ID(GP_DLATCHSRI)); + gp_dff_types.insert("\\GP_DFF"); + gp_dff_types.insert("\\GP_DFFI"); + gp_dff_types.insert("\\GP_DFFR"); + gp_dff_types.insert("\\GP_DFFRI"); + gp_dff_types.insert("\\GP_DFFS"); + gp_dff_types.insert("\\GP_DFFSI"); + gp_dff_types.insert("\\GP_DFFSR"); + gp_dff_types.insert("\\GP_DFFSRI"); + + gp_dff_types.insert("\\GP_DLATCH"); + gp_dff_types.insert("\\GP_DLATCHI"); + gp_dff_types.insert("\\GP_DLATCHR"); + gp_dff_types.insert("\\GP_DLATCHRI"); + gp_dff_types.insert("\\GP_DLATCHS"); + gp_dff_types.insert("\\GP_DLATCHSI"); + gp_dff_types.insert("\\GP_DLATCHSR"); + gp_dff_types.insert("\\GP_DLATCHSRI"); for (auto module : design->selected_modules()) { @@ -163,9 +163,9 @@ struct Greenpak4DffInvPass : public Pass { continue; } - if (cell->type == ID(GP_INV)) { - SigBit in_bit = sigmap(cell->getPort(ID(IN))); - SigBit out_bit = sigmap(cell->getPort(ID(OUT))); + if (cell->type == "\\GP_INV") { + SigBit in_bit = sigmap(cell->getPort("\\IN")); + SigBit out_bit = sigmap(cell->getPort("\\OUT")); inv_in2out[in_bit] = out_bit; inv_out2in[out_bit] = in_bit; inv_in2cell[in_bit] = cell; @@ -175,15 +175,15 @@ struct Greenpak4DffInvPass : public Pass { for (auto cell : dff_cells) { - SigBit d_bit = sigmap(cell->getPort(ID::D)); - SigBit q_bit = sigmap(cell->hasPort(ID::Q) ? cell->getPort(ID::Q) : cell->getPort(ID(nQ))); + SigBit d_bit = sigmap(cell->getPort("\\D")); + SigBit q_bit = sigmap(cell->hasPort("\\Q") ? cell->getPort("\\Q") : cell->getPort("\\nQ")); while (inv_out2in.count(d_bit)) { sig_use_cnt[d_bit]--; invert_gp_dff(cell, true); d_bit = inv_out2in.at(d_bit); - cell->setPort(ID::D, d_bit); + cell->setPort("\\D", d_bit); sig_use_cnt[d_bit]++; } @@ -197,10 +197,10 @@ struct Greenpak4DffInvPass : public Pass { inv_in2cell.erase(q_bit); invert_gp_dff(cell, false); - if (cell->hasPort(ID::Q)) - cell->setPort(ID::Q, new_q_bit); + if (cell->hasPort("\\Q")) + cell->setPort("\\Q", new_q_bit); else - cell->setPort(ID(nQ), new_q_bit); + cell->setPort("\\nQ", new_q_bit); } } } diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc index 17b5d4782da..eeb001b4640 100644 --- a/techlibs/greenpak4/synth_greenpak4.cc +++ b/techlibs/greenpak4/synth_greenpak4.cc @@ -29,7 +29,7 @@ struct SynthGreenPAK4Pass : public ScriptPass { SynthGreenPAK4Pass() : ScriptPass("synth_greenpak4", "synthesis for GreenPAK4 FPGAs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -59,7 +59,7 @@ struct SynthGreenPAK4Pass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -70,7 +70,7 @@ struct SynthGreenPAK4Pass : public ScriptPass string top_opt, part, json_file; bool flatten, retime; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; part = "SLG46621V"; @@ -79,7 +79,7 @@ struct SynthGreenPAK4Pass : public ScriptPass retime = false; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -133,7 +133,7 @@ struct SynthGreenPAK4Pass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { @@ -160,11 +160,12 @@ struct SynthGreenPAK4Pass : public ScriptPass run("opt -fast -mux_undef -undriven -fine"); run("memory_map"); run("opt -undriven -fine"); - run("techmap -map +/techmap.v -map +/greenpak4/cells_latch.v"); + run("techmap"); + run("techmap -map +/greenpak4/cells_latch.v"); run("dfflibmap -prepare -liberty +/greenpak4/gp_dff.lib"); run("opt -fast"); if (retime || help_mode) - run("abc -dff -D 1", "(only if -retime)"); + run("abc -dff", "(only if -retime)"); } if (check_label("map_luts")) diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index 1a8caf9a9cc..31478e80e88 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -23,13 +23,18 @@ techlibs/ice40/brams_init3.vh: techlibs/ice40/brams_init.mk $(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/ff_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/dsp_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_model.v)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_hx.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_hx.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_lp.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_lp.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_u.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_u.lut)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh)) diff --git a/techlibs/ice40/abc9_hx.box b/techlibs/ice40/abc9_hx.box new file mode 100644 index 00000000000..3ea70bc9178 --- /dev/null +++ b/techlibs/ice40/abc9_hx.box @@ -0,0 +1,13 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt + +# NB: Inputs/Outputs must be ordered alphabetically +# (with exceptions for carry in/out) + +# Inputs: A B I0 I3 CI +# Outputs: O CO +# (NB: carry chain input/output must be last +# input/output and have been moved there +# overriding the alphabetical ordering) +$__ICE40_CARRY_WRAPPER 1 1 5 2 +400 379 449 316 316 +259 231 - - 126 diff --git a/techlibs/ice40/abc9_hx.lut b/techlibs/ice40/abc9_hx.lut new file mode 100644 index 00000000000..3b3bb11e2ba --- /dev/null +++ b/techlibs/ice40/abc9_hx.lut @@ -0,0 +1,6 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt +# I3 I2 I1 I0 +1 1 316 +2 1 316 379 +3 1 316 379 400 +4 1 316 379 400 449 diff --git a/techlibs/ice40/abc9_lp.box b/techlibs/ice40/abc9_lp.box new file mode 100644 index 00000000000..473e92fe9b6 --- /dev/null +++ b/techlibs/ice40/abc9_lp.box @@ -0,0 +1,13 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt + +# NB: Inputs/Outputs must be ordered alphabetically +# (with exceptions for carry in/out) + +# Inputs: A B I0 I3 CI +# Outputs: O CO +# (NB: carry chain input/output must be last +# input/output and have been moved there +# overriding the alphabetical ordering) +$__ICE40_CARRY_WRAPPER 1 1 5 2 +589 558 661 465 465 +675 609 - - 186 diff --git a/techlibs/ice40/abc9_lp.lut b/techlibs/ice40/abc9_lp.lut new file mode 100644 index 00000000000..e72f760a255 --- /dev/null +++ b/techlibs/ice40/abc9_lp.lut @@ -0,0 +1,6 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt +# I3 I2 I1 I0 +1 1 465 +2 1 465 558 +3 1 465 558 589 +4 1 465 558 589 661 diff --git a/techlibs/ice40/abc9_model.v b/techlibs/ice40/abc9_model.v index 84923d381fa..26cf6cc220d 100644 --- a/techlibs/ice40/abc9_model.v +++ b/techlibs/ice40/abc9_model.v @@ -1,4 +1,4 @@ -(* abc9_box, lib_whitebox *) +(* abc9_box_id = 1, lib_whitebox *) module \$__ICE40_CARRY_WRAPPER ( (* abc9_carry *) output CO, @@ -9,8 +9,6 @@ module \$__ICE40_CARRY_WRAPPER ( input I0, I3 ); parameter LUT = 0; - parameter I3_IS_CI = 0; - wire I3_OR_CI = I3_IS_CI ? CI : I3; SB_CARRY carry ( .I0(A), .I1(B), @@ -23,64 +21,7 @@ module \$__ICE40_CARRY_WRAPPER ( .I0(I0), .I1(A), .I2(B), - .I3(I3_OR_CI), + .I3(I3), .O(O) ); -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L79 - (CI => CO) = (126, 105); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L80 - (I0 => O) = (449, 386); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L82 - (A => CO) = (259, 245); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L83 - (A => O) = (400, 379); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L85 - (B => CO) = (231, 133); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L86 - (B => O) = (379, 351); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L88 - (I3 => O) = (316, 288); - (CI => O) = (316, 288); - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L79 - (CI => CO) = (186, 155); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L80 - (I0 => O) = (662, 569); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L82 - (A => CO) = (382, 362); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L83 - (A => O) = (589, 558); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L85 - (B => CO) = (341, 196); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L86 - (B => O) = (558, 517); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L88 - (I3 => O) = (465, 423); - (CI => O) = (465, 423); - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L91 - (CI => CO) = (278, 278); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L92 - (I0 => O) = (1245, 1285); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L94 - (A => CO) = (675, 662); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L95 - (A => O) = (1179, 1232); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L97 - (B => CO) = (609, 358); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L98 - (B => O) = (1179, 1205); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L100 - (I3 => O) = (861, 874); - (CI => O) = (861, 874); - endspecify -`endif endmodule diff --git a/techlibs/ice40/abc9_u.box b/techlibs/ice40/abc9_u.box new file mode 100644 index 00000000000..f00e247b867 --- /dev/null +++ b/techlibs/ice40/abc9_u.box @@ -0,0 +1,13 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt + +# NB: Inputs/Outputs must be ordered alphabetically +# (with exceptions for carry in/out) + +# Inputs: A B I0 I3 CI +# Outputs: O CO +# (NB: carry chain input/output must be last +# input/output and have been moved there +# overriding the alphabetical ordering) +$__ICE40_CARRY_WRAPPER 1 1 5 2 +1231 1205 1285 874 874 +675 609 - - 278 diff --git a/techlibs/ice40/abc9_u.lut b/techlibs/ice40/abc9_u.lut new file mode 100644 index 00000000000..1e4fcadb69a --- /dev/null +++ b/techlibs/ice40/abc9_u.lut @@ -0,0 +1,6 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt +# I3 I2 I1 I0 +1 1 874 +2 1 874 1205 +3 1 874 1205 1231 +4 1 874 1205 1231 1285 diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v index 3950e882be7..26b24db9e3c 100644 --- a/techlibs/ice40/arith_map.v +++ b/techlibs/ice40/arith_map.v @@ -25,29 +25,21 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; - (* force_downto *) output [Y_WIDTH-1:0] CO; wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; - (* force_downto *) wire [Y_WIDTH-1:0] C = {CO, CI}; genvar i; @@ -57,14 +49,13 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO); // A[1]: 1100 1100 1100 1100 // A[2]: 1111 0000 1111 0000 // A[3]: 1111 1111 0000 0000 - .LUT(16'b 0110_1001_1001_0110), - .I3_IS_CI(1'b1) - ) carry ( + .LUT(16'b 0110_1001_1001_0110) + ) fadd ( .A(AA[i]), .B(BB[i]), .CI(C[i]), .I0(1'b0), - .I3(1'bx), + .I3(C[i]), .CO(CO[i]), .O(Y[i]) ); diff --git a/techlibs/ice40/brams.txt b/techlibs/ice40/brams.txt index 36dfddab25b..03d596111fc 100644 --- a/techlibs/ice40/brams.txt +++ b/techlibs/ice40/brams.txt @@ -28,73 +28,13 @@ bram $__ICE40_RAM4K_M123 clkpol 2 3 endbram -# The syn_* attributes are described in: -# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx -attr_icase 1 - match $__ICE40_RAM4K_M0 - # implicitly requested RAM or ROM - attribute !syn_ramstyle syn_ramstyle=auto - attribute !syn_romstyle syn_romstyle=auto - attribute !ram_block - attribute !rom_block - attribute !logic_block min efficiency 2 make_transp or_next_if_better endmatch -match $__ICE40_RAM4K_M0 - # explicitly requested RAM - attribute syn_ramstyle=block_ram ram_block - attribute !syn_romstyle - attribute !rom_block - attribute !logic_block - min wports 1 - make_transp - or_next_if_better -endmatch - -match $__ICE40_RAM4K_M0 - # explicitly requested ROM - attribute syn_romstyle=ebr rom_block - attribute !syn_ramstyle - attribute !ram_block - attribute !logic_block - max wports 0 - make_transp - or_next_if_better -endmatch - match $__ICE40_RAM4K_M123 - # implicitly requested RAM or ROM - attribute !syn_ramstyle syn_ramstyle=auto - attribute !syn_romstyle syn_romstyle=auto - attribute !ram_block - attribute !rom_block - attribute !logic_block min efficiency 2 make_transp - or_next_if_better -endmatch - -match $__ICE40_RAM4K_M123 - # explicitly requested RAM - attribute syn_ramstyle=block_ram ram_block - attribute !syn_romstyle - attribute !rom_block - attribute !logic_block - min wports 1 - make_transp - or_next_if_better -endmatch - -match $__ICE40_RAM4K_M123 - # explicitly requested ROM - attribute syn_romstyle=ebr rom_block - attribute !syn_ramstyle - attribute !ram_block - attribute !logic_block - max wports 0 - make_transp endmatch diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index 7e5c078790e..662423f0ae2 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -1,8 +1,37 @@ +module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule +module \$_DFF_P_ (input D, C, output Q); SB_DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule + +module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule +module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule + +module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule +module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule + +module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule +module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule + +module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule +module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule +module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule + +module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule +module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule +module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule +module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule + +module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule +module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule +module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule +module \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule + +`ifndef NO_LUT module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; @@ -13,20 +42,41 @@ module \$lut (A, Y); .I0(1'b0), .I1(1'b0), .I2(1'b0), .I3(A[0])); end else if (WIDTH == 2) begin - localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}}; + localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[1]}}, {4{LUT[2]}}, {4{LUT[0]}}}; SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(1'b0), .I1(1'b0), .I2(A[0]), .I3(A[1])); + .I0(1'b0), .I1(1'b0), .I2(A[1]), .I3(A[0])); end else if (WIDTH == 3) begin - localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[6]}}, {2{LUT[5]}}, {2{LUT[4]}}, {2{LUT[3]}}, {2{LUT[2]}}, {2{LUT[1]}}, {2{LUT[0]}}}; + localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[3]}}, {2{LUT[5]}}, {2{LUT[1]}}, {2{LUT[6]}}, {2{LUT[2]}}, {2{LUT[4]}}, {2{LUT[0]}}}; SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(1'b0), .I1(A[0]), .I2(A[1]), .I3(A[2])); + .I0(1'b0), .I1(A[2]), .I2(A[1]), .I3(A[0])); end else if (WIDTH == 4) begin - SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3])); + localparam [15:0] INIT = {LUT[15], LUT[7], LUT[11], LUT[3], LUT[13], LUT[5], LUT[9], LUT[1], LUT[14], LUT[6], LUT[10], LUT[2], LUT[12], LUT[4], LUT[8], LUT[0]}; + SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0])); end else begin wire _TECHMAP_FAIL_ = 1; end endgenerate endmodule +`endif + +`ifndef NO_ADDER +module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3); + parameter LUT = 0; + SB_CARRY carry ( + .I0(A), + .I1(B), + .CI(CI), + .CO(CO) + ); + \$lut #( + .WIDTH(4), + .LUT(LUT) + ) lut ( + .A({I0,A,B,I3}), + .Y(O) + ); +endmodule +`endif diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 7ee809262b0..7d1b37fd695 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -2,6 +2,10 @@ `define SB_DFF_REG reg Q = 0 // `define SB_DFF_REG reg Q +`define ABC9_ARRIVAL_HX(TIME) `ifdef ICE40_HX (* abc9_arrival=TIME *) `endif +`define ABC9_ARRIVAL_LP(TIME) `ifdef ICE40_LP (* abc9_arrival=TIME *) `endif +`define ABC9_ARRIVAL_U(TIME) `ifdef ICE40_U (* abc9_arrival=TIME *) `endif + // SiliconBlue IO Cells module SB_IO ( @@ -163,169 +167,53 @@ endmodule // SiliconBlue Logic Cells -(* abc9_lut=1, lib_whitebox *) +(* lib_whitebox *) module SB_LUT4 (output O, input I0, I1, I2, I3); parameter [15:0] LUT_INIT = 0; wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0]; wire [3:0] s2 = I2 ? s3[ 7:4] : s3[3:0]; wire [1:0] s1 = I1 ? s2[ 3:2] : s2[1:0]; assign O = I0 ? s1[1] : s1[0]; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L80 - (I0 => O) = (449, 386); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L83 - (I1 => O) = (400, 379); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L86 - (I2 => O) = (379, 351); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L88 - (I3 => O) = (316, 288); - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L80 - (I0 => O) = (662, 569); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L83 - (I1 => O) = (589, 558); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L86 - (I2 => O) = (558, 517); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L88 - (I3 => O) = (465, 423); - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L92 - (I0 => O) = (1245, 1285); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L95 - (I1 => O) = (1179, 1232); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L98 - (I2 => O) = (1179, 1205); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L100 - (I3 => O) = (861, 874); - endspecify -`endif endmodule (* lib_whitebox *) module SB_CARRY (output CO, input I0, I1, CI); assign CO = (I0 && I1) || ((I0 || I1) && CI); -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L79 - (CI => CO) = (126, 105); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L82 - (I0 => CO) = (259, 245); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L85 - (I1 => CO) = (231, 133); - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L79 - (CI => CO) = (186, 155); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L82 - (I0 => CO) = (382, 362); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L85 - (I0 => CO) = (341, 196); - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L91 - (CI => CO) = (278, 278); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L94 - (I0 => CO) = (675, 662); - // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L97 - (I0 => CO) = (609, 358); - endspecify -`endif endmodule +// Max delay from: https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 +// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 +// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 + // Positive Edge SiliconBlue FF Cells -(* abc9_flop, lib_whitebox *) module SB_DFF ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, D ); always @(posedge C) Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFE ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, D ); always @(posedge C) if (E) Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C &&& E, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E) (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E) (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E) (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFSR ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, R, D ); @@ -334,46 +222,12 @@ module SB_DFFSR ( Q <= 0; else Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78 - $setup(R, posedge C, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if ( R) (posedge C => (Q : 1'b0)) = 540; - if (!R) (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78 - $setup(R, posedge C, 299); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if ( R) (posedge C => (Q : 1'b0)) = 796; - if (!R) (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90 - $setup(R, posedge C, 530); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if ( R) (posedge C => (Q : 1'b0)) = 1391; - if (!R) (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_box, lib_whitebox *) module SB_DFFR ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, R, D ); @@ -382,67 +236,12 @@ module SB_DFFR ( Q <= 0; else Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 - $setup(negedge R, posedge C, 160); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 599; -`else - if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (!R) (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 - $setup(negedge R, posedge C, 235); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 883; -`else - if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (!R) (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 - $setup(negedge R, posedge C, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 1589; -`else - if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (!R) (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFSS ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, S, D ); @@ -451,46 +250,12 @@ module SB_DFFSS ( Q <= 1; else Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78 - $setup(S, posedge C, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if ( S) (posedge C => (Q : 1'b1)) = 540; - if (!S) (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78 - $setup(S, posedge C, 299); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if ( S) (posedge C => (Q : 1'b1)) = 796; - if (!S) (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90 - $setup(S, posedge C, 530); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if ( S) (posedge C => (Q : 1'b1)) = 1391; - if (!S) (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_box, lib_whitebox *) module SB_DFFS ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, S, D ); @@ -499,67 +264,12 @@ module SB_DFFS ( Q <= 1; else Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 - $setup(negedge S, posedge C, 160); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 599; -`else - if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (!S) (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 - $setup(negedge S, posedge C, 235); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 883; -`else - if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (!S) (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 - $setup(negedge S, posedge C, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 1589; -`else - if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (!S) (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFESR ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, R, D ); @@ -570,52 +280,12 @@ module SB_DFFESR ( else Q <= D; end -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C &&& E && !R, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78 - $setup(R, posedge C &&& E, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E && R) (posedge C => (Q : 1'b0)) = 540; - if (E && !R) (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E && !R, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78 - $setup(R, posedge C &&& E, 299); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E && R) (posedge C => (Q : 1'b0)) = 796; - if (E && !R) (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90 - $setup(R, posedge C &&& E, 530); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E && R) (posedge C => (Q : 1'b0)) = 1391; - if (E && !R) (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_box, lib_whitebox *) module SB_DFFER ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, R, D ); @@ -624,73 +294,12 @@ module SB_DFFER ( Q <= 0; else if (E) Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C &&& E, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 - $setup(negedge R, posedge C, 160); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 599; -`else - if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E && !R) (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 - $setup(negedge R, posedge C, 235); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 883; -`else - if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E && !R) (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 - $setup(negedge R, posedge C, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 1589; -`else - if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E && !R) (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFESS ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, S, D ); @@ -701,52 +310,12 @@ module SB_DFFESS ( else Q <= D; end -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C &&& E && !S, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78 - $setup(S, posedge C &&& E, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E && S) (posedge C => (Q : 1'b1)) = 540; - if (E && !S) (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E && !S, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78 - $setup(S, posedge C &&& E, 299); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E && S) (posedge C => (Q : 1'b1)) = 796; - if (E && !S) (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90 - $setup(S, posedge C &&& E, 530); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E && S) (posedge C => (Q : 1'b1)) = 1391; - if (E && !S) (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_box, lib_whitebox *) module SB_DFFES ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, S, D ); @@ -755,154 +324,37 @@ module SB_DFFES ( Q <= 1; else if (E) Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, posedge C &&& E, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 - $setup(posedge S, posedge C, 160); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 599; -`else - if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E && !S) (posedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 - $setup(posedge S, posedge C, 235); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 883; -`else - if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E && !S) (posedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, posedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 - $setup(posedge S, posedge C, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 1589; -`else - if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E && !S) (posedge C => (Q : D)) = 1391; - endspecify -`endif endmodule // Negative Edge SiliconBlue FF Cells -(* abc9_flop, lib_whitebox *) module SB_DFFN ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, D ); always @(negedge C) Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFNE ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, D ); always @(negedge C) if (E) Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C &&& E, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E) (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E) (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E) (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFNSR ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, R, D ); @@ -911,46 +363,12 @@ module SB_DFFNSR ( Q <= 0; else Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(R, negedge C, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if ( R) (negedge C => (Q : 1'b0)) = 540; - if (!R) (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78 - $setup(R, negedge C, 299); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if ( R) (negedge C => (Q : 1'b0)) = 796; - if (!R) (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90 - $setup(R, negedge C, 530); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if ( R) (negedge C => (Q : 1'b0)) = 1391; - if (!R) (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFNR ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, R, D ); @@ -959,67 +377,12 @@ module SB_DFFNR ( Q <= 0; else Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 - $setup(negedge R, negedge C, 160); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 599; -`else - if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (!R) (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 - $setup(negedge R, negedge C, 235); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 883; -`else - if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (!R) (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 - $setup(negedge R, negedge C, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 1589; -`else - if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (!R) (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFNSS ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, S, D ); @@ -1028,46 +391,12 @@ module SB_DFFNSS ( Q <= 1; else Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(S, negedge C, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if ( S) (negedge C => (Q : 1'b1)) = 540; - if (!S) (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78 - $setup(S, negedge C, 299); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if ( S) (negedge C => (Q : 1'b1)) = 796; - if (!S) (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90 - $setup(S, negedge C, 530); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if ( S) (negedge C => (Q : 1'b1)) = 1391; - if (!S) (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_box, lib_whitebox *) module SB_DFFNS ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, S, D ); @@ -1076,67 +405,12 @@ module SB_DFFNS ( Q <= 1; else Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 - $setup(negedge S, negedge C, 160); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 599; -`else - if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (!S) (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 - $setup(negedge S, negedge C, 235); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 883; -`else - if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (!S) (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 - $setup(negedge S, negedge C, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 1589; -`else - if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (!S) (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFNESR ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, R, D ); @@ -1147,52 +421,12 @@ module SB_DFFNESR ( else Q <= D; end -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C &&& E && !R, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78 - $setup(R, negedge C &&& E, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E && R) (negedge C => (Q : 1'b0)) = 540; - if (E && !R) (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E && !R, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78 - $setup(R, negedge C &&& E, 299); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E && R) (negedge C => (Q : 1'b0)) = 796; - if (E && !R) (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90 - $setup(R, negedge C &&& E, 530); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E && R) (negedge C => (Q : 1'b0)) = 1391; - if (E && !R) (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_box, lib_whitebox *) module SB_DFFNER ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, R, D ); @@ -1201,73 +435,12 @@ module SB_DFFNER ( Q <= 0; else if (E) Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C &&& E, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 - $setup(R, negedge C, 2160); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 599; -`else - if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E && !R) (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 - $setup(R, negedge C, 235); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 883; -`else - if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E && !R) (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 - $setup(negedge R, negedge C, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 -`ifndef YOSYS - (posedge R => (Q : 1'b0)) = 1589; -`else - if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E && !R) (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_flop, lib_whitebox *) module SB_DFFNESS ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, S, D ); @@ -1278,52 +451,12 @@ module SB_DFFNESS ( else Q <= D; end -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C &&& E && !S, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78 - $setup(S, negedge C &&& E, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E && S) (negedge C => (Q : 1'b1)) = 540; - if (E && !S) (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E && !S, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78 - $setup(S, negedge C &&& E, 299); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E && S) (negedge C => (Q : 1'b1)) = 796; - if (E && !S) (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90 - $setup(S, negedge C &&& E, 530); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E && S) (negedge C => (Q : 1'b1)) = 1391; - if (E && !S) (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule -(* abc9_box, lib_whitebox *) module SB_DFFNES ( + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output `SB_DFF_REG, input C, E, S, D ); @@ -1332,75 +465,14 @@ module SB_DFFNES ( Q <= 1; else if (E) Q <= D; -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - $setup(D, negedge C &&& E, 470 - 449); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 - $setup(negedge S, negedge C, 160); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 599; -`else - if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - if (E && !S) (negedge C => (Q : D)) = 540; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E, 693 - 662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 - $setup(negedge S, negedge C, 235); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 883; -`else - if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - if (E && !S) (negedge C => (Q : D)) = 796; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - $setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setup(E, negedge C, 0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 - $setup(negedge S, negedge C, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 -`ifndef YOSYS - (posedge S => (Q : 1'b1)) = 1589; -`else - if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - if (E && !S) (negedge C => (Q : D)) = 1391; - endspecify -`endif endmodule // SiliconBlue RAM Cells module SB_RAM40_4K ( + `ABC9_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401 + `ABC9_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401 + `ABC9_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026 output [15:0] RDATA, input RCLK, RCLKE, RE, input [10:0] RADDR, @@ -1566,75 +638,12 @@ module SB_RAM40_4K ( end end `endif -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358 - $setup(MASK, posedge WCLK &&& WE && WCLKE, 274); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369 - $setup(RADDR, posedge RCLK &&& RE && RCLKE, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370 - $setup(RCLKE, posedge RCLK, 267); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371 - $setup(RE, posedge RCLK, 98); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382 - $setup(WADDR, posedge WCLK &&& WE && WCLKE, 224); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383 - $setup(WCLKE, posedge WCLK, 267); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399 - $setup(WDATA, posedge WCLK &&& WE && WCLKE, 161); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400 - $setup(WE, posedge WCLK, 133); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401 - (posedge RCLK => (RDATA : 16'bx)) = 2146; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358 - $setup(MASK, posedge WCLK &&& WE && WCLKE, 403); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369 - $setup(RADDR, posedge RCLK &&& RE && RCLKE, 300); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370 - $setup(RCLKE, posedge RCLK, 393); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371 - $setup(RE, posedge RCLK, 145); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382 - $setup(WADDR, posedge WCLK &&& WE && WCLKE, 331); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383 - $setup(WCLKE, posedge WCLK, 393); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399 - $setup(WDATA, posedge WCLK &&& WE && WCLKE, 238); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400 - $setup(WE, posedge WCLK, 196); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401 - (posedge RCLK => (RDATA : 16'bx)) = 3163; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983 - $setup(MASK, posedge WCLK &&& WE && WCLKE, 517); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994 - $setup(RADDR, posedge RCLK &&& RE && RCLKE, 384); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995 - $setup(RCLKE, posedge RCLK, 503); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996 - $setup(RE, posedge RCLK, 185); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007 - $setup(WADDR, posedge WCLK &&& WE && WCLKE, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008 - $setup(WCLKE, posedge WCLK, 503); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024 - $setup(WDATA, posedge WCLK &&& WE && WCLKE, 305); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025 - $setup(WE, posedge WCLK, 252); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026 - (posedge RCLK => (RDATA : 16'bx)) = 1179; - endspecify -`endif endmodule module SB_RAM40_4KNR ( + `ABC9_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401 + `ABC9_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401 + `ABC9_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026 output [15:0] RDATA, input RCLKN, RCLKE, RE, input [10:0] RADDR, @@ -1697,75 +706,12 @@ module SB_RAM40_4KNR ( .MASK (MASK ), .WDATA(WDATA) ); -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358 - $setup(MASK, posedge WCLK &&& WE && WCLKE, 274); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369 - $setup(RADDR, posedge RCLKN &&& RE && RCLKE, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370 - $setup(RCLKE, posedge RCLKN, 267); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371 - $setup(RE, posedge RCLKN, 98); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382 - $setup(WADDR, posedge WCLK &&& WE && WCLKE, 224); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383 - $setup(WCLKE, posedge WCLK, 267); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399 - $setup(WDATA, posedge WCLK &&& WE && WCLKE, 161); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400 - $setup(WE, posedge WCLK, 133); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401 - (posedge RCLKN => (RDATA : 16'bx)) = 2146; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358 - $setup(MASK, posedge WCLK &&& WE && WCLKE, 403); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369 - $setup(RADDR, posedge RCLKN &&& RE && RCLKE, 300); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370 - $setup(RCLKE, posedge RCLKN, 393); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371 - $setup(RE, posedge RCLKN, 145); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382 - $setup(WADDR, posedge WCLK &&& WE && WCLKE, 331); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383 - $setup(WCLKE, posedge WCLK, 393); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399 - $setup(WDATA, posedge WCLK &&& WE && WCLKE, 238); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400 - $setup(WE, posedge WCLK, 196); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401 - (posedge RCLKN => (RDATA : 16'bx)) = 3163; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983 - $setup(MASK, posedge WCLK &&& WE && WCLKE, 517); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994 - $setup(RADDR, posedge RCLKN &&& RE && RCLKE, 384); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995 - $setup(RCLKE, posedge RCLKN, 503); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996 - $setup(RE, posedge RCLKN, 185); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007 - $setup(WADDR, posedge WCLK &&& WE && WCLKE, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008 - $setup(WCLKE, posedge WCLK, 503); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024 - $setup(WDATA, posedge WCLK &&& WE && WCLKE, 305); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025 - $setup(WE, posedge WCLK, 252); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026 - (posedge RCLKN => (RDATA : 16'bx)) = 1179; - endspecify -`endif endmodule module SB_RAM40_4KNW ( + `ABC9_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401 + `ABC9_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401 + `ABC9_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026 output [15:0] RDATA, input RCLK, RCLKE, RE, input [10:0] RADDR, @@ -1828,75 +774,12 @@ module SB_RAM40_4KNW ( .MASK (MASK ), .WDATA(WDATA) ); -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358 - $setup(MASK, posedge WCLKN &&& WE && WCLKE, 274); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369 - $setup(RADDR, posedge RCLK &&& RE && RCLKE, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370 - $setup(RCLKE, posedge RCLK, 267); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371 - $setup(RE, posedge RCLK, 98); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382 - $setup(WADDR, posedge WCLKN &&& WE && WCLKE, 224); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383 - $setup(WCLKE, posedge WCLKN, 267); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399 - $setup(WDATA, posedge WCLKN &&& WE && WCLKE, 161); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400 - $setup(WE, posedge WCLKN, 133); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401 - (posedge RCLK => (RDATA : 16'bx)) = 2146; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358 - $setup(MASK, posedge WCLKN &&& WE && WCLKE, 403); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369 - $setup(RADDR, posedge RCLK &&& RE && RCLKE, 300); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370 - $setup(RCLKE, posedge RCLK, 393); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371 - $setup(RE, posedge RCLK, 145); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382 - $setup(WADDR, posedge WCLKN &&& WE && WCLKE, 331); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383 - $setup(WCLKE, posedge WCLKN, 393); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399 - $setup(WDATA, posedge WCLKN &&& WE && WCLKE, 238); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400 - $setup(WE, posedge WCLKN, 196); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401 - (posedge RCLK => (RDATA : 16'bx)) = 3163; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983 - $setup(MASK, posedge WCLKN &&& WE && WCLKE, 517); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994 - $setup(RADDR, posedge RCLK &&& RE && RCLKE, 384); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995 - $setup(RCLKE, posedge RCLK, 503); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996 - $setup(RE, posedge RCLK, 185); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007 - $setup(WADDR, posedge WCLKN &&& WE && WCLKE, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008 - $setup(WCLKE, posedge WCLKN, 503); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024 - $setup(WDATA, posedge WCLKN &&& WE && WCLKE, 305); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025 - $setup(WE, posedge WCLKN, 252); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026 - (posedge RCLK => (RDATA : 16'bx)) = 1179; - endspecify -`endif endmodule module SB_RAM40_4KNRNW ( + `ABC9_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401 + `ABC9_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401 + `ABC9_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026 output [15:0] RDATA, input RCLKN, RCLKE, RE, input [10:0] RADDR, @@ -1959,72 +842,6 @@ module SB_RAM40_4KNRNW ( .MASK (MASK ), .WDATA(WDATA) ); -`ifdef ICE40_HX - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358 - $setup(MASK, posedge WCLKN &&& WE && WCLKE, 274); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369 - $setup(RADDR, posedge RCLKN &&& RE && RCLKE, 203); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370 - $setup(RCLKE, posedge RCLKN, 267); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371 - $setup(RE, posedge RCLKN, 98); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382 - $setup(WADDR, posedge WCLKN &&& WE && WCLKE, 224); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383 - $setup(WCLKE, posedge WCLKN, 267); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399 - $setup(WDATA, posedge WCLKN &&& WE && WCLKE, 161); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400 - $setup(WE, posedge WCLKN, 133); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401 - (posedge RCLKN => (RDATA : 16'bx)) = 2146; - endspecify -`endif -`ifdef ICE40_LP - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358 - $setup(MASK, posedge WCLKN &&& WE && WCLKE, 403); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369 - $setup(RADDR, posedge RCLKN &&& RE && RCLKE, 300); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370 - $setup(RCLKE, posedge RCLKN, 393); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371 - $setup(RE, posedge RCLKN, 145); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382 - $setup(WADDR, posedge WCLKN &&& WE && WCLKE, 331); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383 - $setup(WCLKE, posedge WCLKN, 393); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399 - $setup(WDATA, posedge WCLKN &&& WE && WCLKE, 238); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400 - $setup(WE, posedge WCLKN, 196); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401 - (posedge RCLKN => (RDATA : 16'bx)) = 3163; - endspecify -`endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983 - $setup(MASK, posedge WCLKN &&& WE && WCLKE, 517); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994 - $setup(RADDR, posedge RCLKN &&& RE && RCLKE, 384); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995 - $setup(RCLKE, posedge RCLKN, 503); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996 - $setup(RE, posedge RCLKN, 185); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007 - $setup(WADDR, posedge WCLKN &&& WE && WCLKE, 424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008 - $setup(WCLKE, posedge WCLKN, 503); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024 - $setup(WDATA, posedge WCLKN &&& WE && WCLKE, 305); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025 - $setup(WE, posedge WCLKN, 252); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026 - (posedge RCLKN => (RDATA : 16'bx)) = 1179; - endspecify -`endif endmodule // Packed IceStorm Logic Cells @@ -2032,6 +849,9 @@ endmodule module ICESTORM_LC ( input I0, I1, I2, I3, CIN, CLK, CEN, SR, output LO, + `ABC9_ARRIVAL_HX(540) + `ABC9_ARRIVAL_LP(796) + `ABC9_ARRIVAL_U(1391) output O, output COUT ); @@ -2073,7 +893,7 @@ module ICESTORM_LC ( o_reg <= SR_pd ? SET_NORESET : lut_o; reg o_reg_async = 1'b0; - always @(posedge polarized_clk, posedge SR_pd) + always @(posedge polarized_clk, posedge SR) if (SR_pd) o_reg_async <= SET_NORESET; else if (CEN_pu) @@ -2121,198 +941,6 @@ specify $setuphold(negedge CLK, negedge SR, 0:0:0, 0:0:0); endspecify `endif -`ifdef ICE40_HX -specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L79 - (CIN => COUT) = (101:112:126, 85:94:105); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80 - (I0 => O) = (361:399:449, 310:343:386); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L81 - (I0 => LO) = (293:324:365, 310:343:386); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L82 - (I1 => COUT) = (209:231:259, 197:218:245); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L83 - (I1 => O) = (321:355:400, 304:337:379); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L84 - (I1 => LO) = (259:287:323, 304:337:379); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L85 - (I2 => COUT) = (186:206:231, 107:118:133); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L86 - (I2 => O) = (304:337:379, 282:312:351); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L87 - (I2 => LO) = (254:281:316, 231:256:288); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L88 - (I3 => O) = (254:281:316, 231:256:288); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L89 - (I3 => LO) = (214:237:267, 220:243:274); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 - (posedge CLK => (O : 1'bx)) = (434:480:540, 434:480:540); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91-L92 - (SR => O) = (482:535:599, 482:533:599); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74 - $setuphold(posedge CLK, posedge I0, 378:418:470, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L68 - $setuphold(posedge CLK, negedge I0, 321:355:400, 0:0:0); - $setuphold(negedge CLK, posedge I0, 378:418:470, 0:0:0); - $setuphold(negedge CLK, negedge I0, 321:355:400, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L75 - $setuphold(posedge CLK, posedge I1, 321:355:400, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L69 - $setuphold(posedge CLK, negedge I1, 304:337:379, 0:0:0); - $setuphold(negedge CLK, posedge I1, 321:355:400, 0:0:0); - $setuphold(negedge CLK, negedge I1, 304:337:379, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L76 - $setuphold(posedge CLK, posedge I2, 299:330:372, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L70 - $setuphold(posedge CLK, negedge I2, 259:287:323, 0:0:0); - $setuphold(negedge CLK, posedge I2, 299:330:372, 0:0:0); - $setuphold(negedge CLK, negedge I2, 259:287:323, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L77 - $setuphold(posedge CLK, posedge I3, 220:243:274, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L71 - $setuphold(posedge CLK, negedge I3, 175:183:217, 0:0:0); - $setuphold(negedge CLK, posedge I3, 220:243:274, 0:0:0); - $setuphold(negedge CLK, negedge I3, 175:183:217, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73 - $setuphold(posedge CLK, negedge CEN, 0:0:0, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L67 - $setuphold(posedge CLK, posedge CEN, 0:0:0, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78 - $setuphold(posedge CLK, posedge SR, 163:181:203, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L72 - $setuphold(posedge CLK, negedge SR, 113:125:140, 0:0:0); - $setuphold(negedge CLK, posedge SR, 163:181:203, 0:0:0); - $setuphold(negedge CLK, negedge SR, 113:125:140, 0:0:0); -endspecify -`endif -`ifdef ICE40_LP -specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L79 - (CIN => COUT) = (118:153:186, 98:128:155); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80 - (I0 => O) = (419:545:662, 360:468:569); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L81 - (I0 => LO) = (340:442:538, 360:468:569); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L82 - (I1 => COUT) = (242:315:382, 229:298:362); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L83 - (I1 => O) = (372:485:589, 353:459:558); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L84 - (I1 => LO) = (301:391:475, 353:459:558); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L85 - (I2 => COUT) = (216:281:341, 124:162:196); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86 - (I2 => O) = (353:459:558, 327:425:517); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L87 - (I2 => LO) = (288:374:455, 321:417:507); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L88 - (I3 => O) = (294:383:465, 268:349:424); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L89 - (I3 => LO) = (249:323:393, 255:332:403); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 - (posedge CLK => (O : 1'bx)) = (504:655:796, 504:655:796); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91-L92 - (SR => O) = (559:726:883, 559:726:883); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74 - $setuphold(posedge CLK, posedge I0, 438:570:693, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L68 - $setuphold(posedge CLK, negedge I0, 373:485:589, 0:0:0); - $setuphold(negedge CLK, posedge I0, 438:570:693, 0:0:0); - $setuphold(negedge CLK, negedge I0, 373:485:589, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L75 - $setuphold(posedge CLK, posedge I1, 373:485:589, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L69 - $setuphold(posedge CLK, negedge I1, 353:459:558, 0:0:0); - $setuphold(negedge CLK, posedge I1, 373:485:589, 0:0:0); - $setuphold(negedge CLK, negedge I1, 353:459:558, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L76 - $setuphold(posedge CLK, posedge I2, 347:451:548, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L70 - $setuphold(posedge CLK, negedge I2, 301:391:475, 0:0:0); - $setuphold(negedge CLK, posedge I2, 347:451:548, 0:0:0); - $setuphold(negedge CLK, negedge I2, 301:391:475, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L77 - $setuphold(posedge CLK, posedge I3, 255:332:403, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L71 - $setuphold(posedge CLK, negedge I3, 203:264:320, 0:0:0); - $setuphold(negedge CLK, posedge I3, 255:332:403, 0:0:0); - $setuphold(negedge CLK, negedge I3, 203:264:320, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73 - $setuphold(posedge CLK, negedge CEN, 0:0:0, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L67 - $setuphold(posedge CLK, posedge CEN, 0:0:0, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78 - $setuphold(posedge CLK, posedge SR, 190:247:300, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L72 - $setuphold(posedge CLK, negedge SR, 131:170:207, 0:0:0); - $setuphold(negedge CLK, posedge SR, 190:247:300, 0:0:0); - $setuphold(negedge CLK, negedge SR, 131:170:207, 0:0:0); -endspecify -`endif -`ifdef ICE40_U -specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L91 - (CIN => COUT) = (103:181:278, 103:181:278); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L92 - (I0 => O) = (462:808:1255, 477:834:1285); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L93 - (I0 => LO) = (315:550:848, 334:585:901); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L94 - (I1 => COUT) = (251:438:675, 246:430:662); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L95 - (I1 => O) = (438:765:1179, 457:799:1232); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L96 - (I1 => LO) = (275:481:742, 329:576:887); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L97 - (I2 => COUT) = (226:395:609, 133:232:358); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L98 - (I2 => O) = (438:765:1179, 447:782:1205); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L99 - (I2 => LO) = (261:456:702, 290:507:781); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L100 - (I3 => O) = (320:559:861, 226:370:874); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L101 - (I3 => LO) = (216:378:583, 226:395:609); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 - (posedge CLK => (O : 1'bx)) = (516:903:1391, 516:903:1391); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103-104 - (SR => O) = (420:734:1131, 590:1032:1589); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86 - $setuphold(posedge CLK, posedge I0, 457:799:1232, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L80 - $setuphold(posedge CLK, negedge I0, 393:688:1060, 0:0:0); - $setuphold(negedge CLK, posedge I0, 457:799:1232, 0:0:0); - $setuphold(negedge CLK, negedge I0, 393:688:1060, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L87 - $setuphold(posedge CLK, posedge I1, 393:688:1060, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L81 - $setuphold(posedge CLK, negedge I1, 373:653:1007, 0:0:0); - $setuphold(negedge CLK, posedge I1, 393:688:1060, 0:0:0); - $setuphold(negedge CLK, negedge I1, 373:653:1007, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L88 - $setuphold(posedge CLK, posedge I2, 364:636:980, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L82 - $setuphold(posedge CLK, negedge I2, 320:559:861, 0:0:0); - $setuphold(negedge CLK, posedge I2, 364:636:980, 0:0:0); - $setuphold(negedge CLK, negedge I2, 320:559:861, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L89 - $setuphold(posedge CLK, posedge I3, 279:473:728, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L83 - $setuphold(posedge CLK, negedge I3, 216:378:583, 0:0:0); - $setuphold(negedge CLK, posedge I3, 279:473:728, 0:0:0); - $setuphold(negedge CLK, negedge I3, 216:378:583, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L85 - $setuphold(posedge CLK, negedge CEN, 0:0:0, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L79 - $setuphold(posedge CLK, posedge CEN, 0:0:0, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90 - $setuphold(posedge CLK, posedge SR, 197:344:530, 0:0:0); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L84 - $setuphold(posedge CLK, negedge SR, 143:249:384, 0:0:0); - $setuphold(negedge CLK, posedge SR, 197:344:530, 0:0:0); - $setuphold(negedge CLK, negedge SR, 131:170:207, 0:0:0); -endspecify -`endif endmodule // SiliconBlue PLL Cells @@ -2508,52 +1136,27 @@ module SB_SPRAM256KA ( always @(negedge POWEROFF) begin for (i = 0; i <= 16383; i = i+1) - mem[i] = 16'bx; + mem[i] = 'bx; end always @(posedge CLOCK, posedge off) begin if (off) begin DATAOUT <= 0; end else - if (STANDBY) begin - DATAOUT <= 16'bx; - end else - if (CHIPSELECT) begin - if (!WREN) begin - DATAOUT <= mem[ADDRESS]; - end else begin - if (MASKWREN[0]) mem[ADDRESS][ 3: 0] <= DATAIN[ 3: 0]; - if (MASKWREN[1]) mem[ADDRESS][ 7: 4] <= DATAIN[ 7: 4]; - if (MASKWREN[2]) mem[ADDRESS][11: 8] <= DATAIN[11: 8]; - if (MASKWREN[3]) mem[ADDRESS][15:12] <= DATAIN[15:12]; - DATAOUT <= 16'bx; + if (CHIPSELECT && !STANDBY && !WREN) begin + DATAOUT <= mem[ADDRESS]; + end else begin + if (CHIPSELECT && !STANDBY && WREN) begin + if (MASKWREN[0]) mem[ADDRESS][ 3: 0] = DATAIN[ 3: 0]; + if (MASKWREN[1]) mem[ADDRESS][ 7: 4] = DATAIN[ 7: 4]; + if (MASKWREN[2]) mem[ADDRESS][11: 8] = DATAIN[11: 8]; + if (MASKWREN[3]) mem[ADDRESS][15:12] = DATAIN[15:12]; end + DATAOUT <= 'bx; end end `endif `endif -`ifdef ICE40_U - specify - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13169-L13182 - $setup(posedge ADDRESS, posedge CLOCK, 268); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13183 - $setup(CHIPSELECT, posedge CLOCK, 404); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13184-L13199 - $setup(DATAIN, posedge CLOCK, 143); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13200-L13203 - $setup(MASKWREN, posedge CLOCK, 143); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13167 - //$setup(negedge SLEEP, posedge CLOCK, 41505); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13167 - //$setup(negedge STANDBY, posedge CLOCK, 1715); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13206 - $setup(WREN, posedge CLOCK, 289); - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13207-L13222 - (posedge CLOCK => (DATAOUT : 16'bx)) = 1821; - // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13223-L13238 - (posedge SLEEP => (DATAOUT : 16'b0)) = 1099; - endspecify -`endif endmodule (* blackbox *) @@ -2888,7 +1491,6 @@ module SB_IO_OD ( `endif endmodule -//(* abc9_box, lib_whitebox *) // TODO module SB_MAC16 ( input CLK, CE, input [15:0] C, A, B, D, diff --git a/techlibs/ice40/ff_map.v b/techlibs/ice40/ff_map.v deleted file mode 100644 index 990cd74f18a..00000000000 --- a/techlibs/ice40/ff_map.v +++ /dev/null @@ -1,28 +0,0 @@ -module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule -module \$_DFF_P_ (input D, C, output Q); SB_DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule - -module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule -module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule - -module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule -module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule - -module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule - -module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule -module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule - -module \$_DFFE_NN0P_ (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule -module \$_DFFE_NN1P_ (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule -module \$_DFFE_PN0P_ (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule -module \$_DFFE_PN1P_ (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule - -module \$_DFFE_NP0P_ (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule -module \$_DFFE_NP1P_ (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule -module \$_DFFE_PP1P_ (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule diff --git a/techlibs/ice40/ice40_braminit.cc b/techlibs/ice40/ice40_braminit.cc index e5d1f7e2475..1a139ffea7a 100644 --- a/techlibs/ice40/ice40_braminit.cc +++ b/techlibs/ice40/ice40_braminit.cc @@ -33,15 +33,15 @@ static void run_ice40_braminit(Module *module) uint16_t mem[256]; /* Only consider cells we're interested in */ - if (cell->type != ID(SB_RAM40_4K) && - cell->type != ID(SB_RAM40_4KNR) && - cell->type != ID(SB_RAM40_4KNW) && - cell->type != ID(SB_RAM40_4KNRNW)) + if (cell->type != "\\SB_RAM40_4K" && + cell->type != "\\SB_RAM40_4KNR" && + cell->type != "\\SB_RAM40_4KNW" && + cell->type != "\\SB_RAM40_4KNRNW") continue; - if (!cell->hasParam(ID(INIT_FILE))) + if (!cell->hasParam("\\INIT_FILE")) continue; - std::string init_file = cell->getParam(ID(INIT_FILE)).decode_string(); - cell->unsetParam(ID(INIT_FILE)); + std::string init_file = cell->getParam("\\INIT_FILE").decode_string(); + cell->unsetParam("\\INIT_FILE"); if (init_file == "") continue; @@ -128,7 +128,7 @@ static void run_ice40_braminit(Module *module) struct Ice40BRAMInitPass : public Pass { Ice40BRAMInitPass() : Pass("ice40_braminit", "iCE40: perform SB_RAM40_4K initialization from file") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -138,7 +138,7 @@ struct Ice40BRAMInitPass : public Pass { log("parameter and converts it into the required INIT_x attributes\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ICE40_BRAMINIT pass.\n"); diff --git a/techlibs/ice40/ice40_ffinit.cc b/techlibs/ice40/ice40_ffinit.cc index 2eef3fa93b5..3089d893277 100644 --- a/techlibs/ice40/ice40_ffinit.cc +++ b/techlibs/ice40/ice40_ffinit.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct Ice40FfinitPass : public Pass { Ice40FfinitPass() : Pass("ice40_ffinit", "iCE40: handle FF init values") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -35,7 +35,7 @@ struct Ice40FfinitPass : public Pass { log("nonzero init values.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ICE40_FFINIT pass (implement FF init values).\n"); @@ -62,11 +62,11 @@ struct Ice40FfinitPass : public Pass { for (auto wire : module->selected_wires()) { - if (wire->attributes.count(ID::init) == 0) + if (wire->attributes.count("\\init") == 0) continue; SigSpec wirebits = sigmap(wire); - Const initval = wire->attributes.at(ID::init); + Const initval = wire->attributes.at("\\init"); init_wires.insert(wire); for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) @@ -78,12 +78,10 @@ struct Ice40FfinitPass : public Pass { continue; if (initbits.count(bit)) { - if (initbits.at(bit) != val) { - log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n", + if (initbits.at(bit) != val) + log_error("Conflicting init values for signal %s (%s = %s, %s = %s).\n", log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val), log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit))); - initbits.at(bit) = State::Sx; - } continue; } @@ -93,9 +91,9 @@ struct Ice40FfinitPass : public Pass { } pool sb_dff_types = { - ID(SB_DFF), ID(SB_DFFE), ID(SB_DFFSR), ID(SB_DFFR), ID(SB_DFFSS), ID(SB_DFFS), ID(SB_DFFESR), - ID(SB_DFFER), ID(SB_DFFESS), ID(SB_DFFES), ID(SB_DFFN), ID(SB_DFFNE), ID(SB_DFFNSR), ID(SB_DFFNR), - ID(SB_DFFNSS), ID(SB_DFFNS), ID(SB_DFFNESR), ID(SB_DFFNER), ID(SB_DFFNESS), ID(SB_DFFNES) + "\\SB_DFF", "\\SB_DFFE", "\\SB_DFFSR", "\\SB_DFFR", "\\SB_DFFSS", "\\SB_DFFS", "\\SB_DFFESR", + "\\SB_DFFER", "\\SB_DFFESS", "\\SB_DFFES", "\\SB_DFFN", "\\SB_DFFNE", "\\SB_DFFNSR", "\\SB_DFFNR", + "\\SB_DFFNSS", "\\SB_DFFNS", "\\SB_DFFNESR", "\\SB_DFFNER", "\\SB_DFFNESS", "\\SB_DFFNES" }; for (auto cell : module->selected_cells()) @@ -103,8 +101,8 @@ struct Ice40FfinitPass : public Pass { if (!sb_dff_types.count(cell->type)) continue; - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); + SigSpec sig_d = cell->getPort("\\D"); + SigSpec sig_q = cell->getPort("\\Q"); if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1) continue; @@ -116,10 +114,6 @@ struct Ice40FfinitPass : public Pass { continue; State val = initbits.at(bit_q); - - if (val == State::Sx) - continue; - handled_initbits.insert(bit_q); log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type), @@ -133,14 +127,14 @@ struct Ice40FfinitPass : public Pass { if (type_str.back() == 'S') { type_str.back() = 'R'; cell->type = type_str; - cell->setPort(ID::R, cell->getPort(ID::S)); - cell->unsetPort(ID::S); + cell->setPort("\\R", cell->getPort("\\S")); + cell->unsetPort("\\S"); } else if (type_str.back() == 'R') { type_str.back() = 'S'; cell->type = type_str; - cell->setPort(ID::S, cell->getPort(ID::R)); - cell->unsetPort(ID::R); + cell->setPort("\\S", cell->getPort("\\R")); + cell->unsetPort("\\R"); } Wire *new_bit_d = module->addWire(NEW_ID); @@ -149,17 +143,17 @@ struct Ice40FfinitPass : public Pass { module->addNotGate(NEW_ID, bit_d, new_bit_d); module->addNotGate(NEW_ID, new_bit_q, bit_q); - cell->setPort(ID::D, new_bit_d); - cell->setPort(ID::Q, new_bit_q); + cell->setPort("\\D", new_bit_d); + cell->setPort("\\Q", new_bit_q); } for (auto wire : init_wires) { - if (wire->attributes.count(ID::init) == 0) + if (wire->attributes.count("\\init") == 0) continue; SigSpec wirebits = sigmap(wire); - Const &initval = wire->attributes.at(ID::init); + Const &initval = wire->attributes.at("\\init"); bool remove_attribute = true; for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) { @@ -170,7 +164,7 @@ struct Ice40FfinitPass : public Pass { } if (remove_attribute) - wire->attributes.erase(ID::init); + wire->attributes.erase("\\init"); } } } diff --git a/techlibs/ice40/ice40_ffssr.cc b/techlibs/ice40/ice40_ffssr.cc index 492029b77fe..a7649d7a0c8 100644 --- a/techlibs/ice40/ice40_ffssr.cc +++ b/techlibs/ice40/ice40_ffssr.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct Ice40FfssrPass : public Pass { Ice40FfssrPass() : Pass("ice40_ffssr", "iCE40: merge synchronous set/reset into FF cells") { } - void help() override + void help() YS_OVERRIDE { log("\n"); log(" ice40_ffssr [options] [selection]\n"); @@ -33,7 +33,7 @@ struct Ice40FfssrPass : public Pass { log("Merge synchronous set/reset $_MUX_ cells into iCE40 FFs.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ICE40_FFSSR pass (merge synchronous set/reset into FF cells).\n"); @@ -49,10 +49,10 @@ struct Ice40FfssrPass : public Pass { extra_args(args, argidx, design); pool sb_dff_types; - sb_dff_types.insert(ID(SB_DFF)); - sb_dff_types.insert(ID(SB_DFFE)); - sb_dff_types.insert(ID(SB_DFFN)); - sb_dff_types.insert(ID(SB_DFFNE)); + sb_dff_types.insert("\\SB_DFF"); + sb_dff_types.insert("\\SB_DFFE"); + sb_dff_types.insert("\\SB_DFFN"); + sb_dff_types.insert("\\SB_DFFNE"); for (auto module : design->selected_modules()) { @@ -69,22 +69,22 @@ struct Ice40FfssrPass : public Pass { continue; } - if (cell->type != ID($_MUX_)) + if (cell->type != "$_MUX_") continue; - SigBit bit_a = sigmap(cell->getPort(ID::A)); - SigBit bit_b = sigmap(cell->getPort(ID::B)); + SigBit bit_a = sigmap(cell->getPort("\\A")); + SigBit bit_b = sigmap(cell->getPort("\\B")); if (bit_a.wire == nullptr || bit_b.wire == nullptr) - sr_muxes[sigmap(cell->getPort(ID::Y))] = cell; + sr_muxes[sigmap(cell->getPort("\\Y"))] = cell; } for (auto cell : ff_cells) { - if (cell->get_bool_attribute(ID(dont_touch))) + if (cell->get_bool_attribute("\\dont_touch")) continue; - SigSpec sig_d = cell->getPort(ID::D); + SigSpec sig_d = cell->getPort("\\D"); if (GetSize(sig_d) < 1) continue; @@ -95,9 +95,9 @@ struct Ice40FfssrPass : public Pass { continue; Cell *mux_cell = sr_muxes.at(bit_d); - SigBit bit_a = sigmap(mux_cell->getPort(ID::A)); - SigBit bit_b = sigmap(mux_cell->getPort(ID::B)); - SigBit bit_s = sigmap(mux_cell->getPort(ID::S)); + SigBit bit_a = sigmap(mux_cell->getPort("\\A")); + SigBit bit_b = sigmap(mux_cell->getPort("\\B")); + SigBit bit_s = sigmap(mux_cell->getPort("\\S")); log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell), log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type)); @@ -116,12 +116,12 @@ struct Ice40FfssrPass : public Pass { if (sr_val == State::S1) { cell->type = cell->type.str() + "SS"; - cell->setPort(ID::S, sr_sig); - cell->setPort(ID::D, bit_d); + cell->setPort("\\S", sr_sig); + cell->setPort("\\D", bit_d); } else { cell->type = cell->type.str() + "SR"; - cell->setPort(ID::R, sr_sig); - cell->setPort(ID::D, bit_d); + cell->setPort("\\R", sr_sig); + cell->setPort("\\D", bit_d); } } } diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index 1a70fa8c0f9..ea56d3f4d1f 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -41,26 +41,21 @@ static void run_ice40_opts(Module *module) for (auto cell : module->selected_cells()) { - if (!cell->type.in(ID(SB_LUT4), ID(SB_CARRY), ID($__ICE40_CARRY_WRAPPER))) - continue; - if (cell->has_keep_attr()) - continue; - - if (cell->type == ID(SB_LUT4)) + if (cell->type == "\\SB_LUT4") { sb_lut_cells.push_back(cell); continue; } - if (cell->type == ID(SB_CARRY)) + if (cell->type == "\\SB_CARRY") { SigSpec non_const_inputs, replacement_output; int count_zeros = 0, count_ones = 0; SigBit inbit[3] = { - get_bit_or_zero(cell->getPort(ID(I0))), - get_bit_or_zero(cell->getPort(ID(I1))), - get_bit_or_zero(cell->getPort(ID::CI)) + get_bit_or_zero(cell->getPort("\\I0")), + get_bit_or_zero(cell->getPort("\\I1")), + get_bit_or_zero(cell->getPort("\\CI")) }; for (int i = 0; i < 3; i++) if (inbit[i].wire == nullptr) { @@ -79,8 +74,8 @@ static void run_ice40_opts(Module *module) replacement_output = non_const_inputs; if (GetSize(replacement_output)) { - optimized_co.insert(sigmap(cell->getPort(ID::CO)[0])); - module->connect(cell->getPort(ID::CO)[0], replacement_output); + optimized_co.insert(sigmap(cell->getPort("\\CO")[0])); + module->connect(cell->getPort("\\CO")[0], replacement_output); module->design->scratchpad_set_bool("opt.did_something", true); log("Optimized away SB_CARRY cell %s.%s: CO=%s\n", log_id(module), log_id(cell), log_signal(replacement_output)); @@ -89,15 +84,15 @@ static void run_ice40_opts(Module *module) continue; } - if (cell->type == ID($__ICE40_CARRY_WRAPPER)) + if (cell->type == "$__ICE40_CARRY_WRAPPER") { SigSpec non_const_inputs, replacement_output; int count_zeros = 0, count_ones = 0; SigBit inbit[3] = { - cell->getPort(ID::A), - cell->getPort(ID::B), - cell->getPort(ID::CI) + cell->getPort("\\A"), + cell->getPort("\\B"), + cell->getPort("\\CI") }; for (int i = 0; i < 3; i++) if (inbit[i].wire == nullptr) { @@ -116,40 +111,21 @@ static void run_ice40_opts(Module *module) replacement_output = non_const_inputs; if (GetSize(replacement_output)) { - optimized_co.insert(sigmap(cell->getPort(ID::CO)[0])); - auto it = cell->attributes.find(ID(SB_LUT4.name)); - if (it != cell->attributes.end()) { - module->rename(cell, it->second.decode_string()); - decltype(Cell::attributes) new_attr; - for (const auto &a : cell->attributes) - if (a.first.begins_with("\\SB_LUT4.\\")) - new_attr[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; - else if (a.first == ID::src) - new_attr.insert(std::make_pair(a.first, a.second)); - else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID::module_not_derived)) - continue; - else if (a.first.begins_with("\\SB_CARRY.\\")) - continue; - else - log_abort(); - cell->attributes = std::move(new_attr); - } - module->connect(cell->getPort(ID::CO)[0], replacement_output); + optimized_co.insert(sigmap(cell->getPort("\\CO")[0])); + module->connect(cell->getPort("\\CO")[0], replacement_output); module->design->scratchpad_set_bool("opt.did_something", true); log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n", log_id(module), log_id(cell), log_signal(replacement_output)); - cell->type = ID($lut); - auto I3 = get_bit_or_zero(cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID::CI : ID(I3))); - cell->setPort(ID::A, { I3, inbit[1], inbit[0], get_bit_or_zero(cell->getPort(ID(I0))) }); - cell->setPort(ID::Y, cell->getPort(ID::O)); - cell->unsetPort(ID::B); - cell->unsetPort(ID::CI); - cell->unsetPort(ID(I0)); - cell->unsetPort(ID(I3)); - cell->unsetPort(ID::CO); - cell->unsetPort(ID::O); - cell->setParam(ID::WIDTH, 4); - cell->unsetParam(ID(I3_IS_CI)); + cell->type = "$lut"; + cell->setPort("\\A", { cell->getPort("\\I0"), inbit[0], inbit[1], cell->getPort("\\I3") }); + cell->setPort("\\Y", cell->getPort("\\O")); + cell->unsetPort("\\B"); + cell->unsetPort("\\CI"); + cell->unsetPort("\\I0"); + cell->unsetPort("\\I3"); + cell->unsetPort("\\CO"); + cell->unsetPort("\\O"); + cell->setParam("\\WIDTH", 4); } continue; } @@ -159,10 +135,10 @@ static void run_ice40_opts(Module *module) { SigSpec inbits; - inbits.append(get_bit_or_zero(cell->getPort(ID(I0)))); - inbits.append(get_bit_or_zero(cell->getPort(ID(I1)))); - inbits.append(get_bit_or_zero(cell->getPort(ID(I2)))); - inbits.append(get_bit_or_zero(cell->getPort(ID(I3)))); + inbits.append(get_bit_or_zero(cell->getPort("\\I0"))); + inbits.append(get_bit_or_zero(cell->getPort("\\I1"))); + inbits.append(get_bit_or_zero(cell->getPort("\\I2"))); + inbits.append(get_bit_or_zero(cell->getPort("\\I3"))); sigmap.apply(inbits); if (optimized_co.count(inbits[0])) goto remap_lut; @@ -177,23 +153,23 @@ static void run_ice40_opts(Module *module) module->design->scratchpad_set_bool("opt.did_something", true); log("Mapping SB_LUT4 cell %s.%s back to logic.\n", log_id(module), log_id(cell)); - cell->type = ID($lut); - cell->setParam(ID::WIDTH, 4); - cell->setParam(ID::LUT, cell->getParam(ID(LUT_INIT))); - cell->unsetParam(ID(LUT_INIT)); + cell->type ="$lut"; + cell->setParam("\\WIDTH", 4); + cell->setParam("\\LUT", cell->getParam("\\LUT_INIT")); + cell->unsetParam("\\LUT_INIT"); - cell->setPort(ID::A, SigSpec({ - get_bit_or_zero(cell->getPort(ID(I3))), - get_bit_or_zero(cell->getPort(ID(I2))), - get_bit_or_zero(cell->getPort(ID(I1))), - get_bit_or_zero(cell->getPort(ID(I0))) + cell->setPort("\\A", SigSpec({ + get_bit_or_zero(cell->getPort("\\I3")), + get_bit_or_zero(cell->getPort("\\I2")), + get_bit_or_zero(cell->getPort("\\I1")), + get_bit_or_zero(cell->getPort("\\I0")) })); - cell->setPort(ID::Y, cell->getPort(ID::O)[0]); - cell->unsetPort(ID(I0)); - cell->unsetPort(ID(I1)); - cell->unsetPort(ID(I2)); - cell->unsetPort(ID(I3)); - cell->unsetPort(ID::O); + cell->setPort("\\Y", cell->getPort("\\O")[0]); + cell->unsetPort("\\I0"); + cell->unsetPort("\\I1"); + cell->unsetPort("\\I2"); + cell->unsetPort("\\I3"); + cell->unsetPort("\\O"); cell->check(); simplemap_lut(module, cell); @@ -203,7 +179,7 @@ static void run_ice40_opts(Module *module) struct Ice40OptPass : public Pass { Ice40OptPass() : Pass("ice40_opt", "iCE40: perform simple optimizations") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -220,7 +196,7 @@ struct Ice40OptPass : public Pass { log(" while \n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string opt_expr_args = "-mux_undef -undriven"; diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 6464368ebe3..901194b0638 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -29,14 +29,7 @@ struct SynthIce40Pass : public ScriptPass { SynthIce40Pass() : ScriptPass("synth_ice40", "synthesis for iCE40 FPGAs") { } - void on_register() override - { - RTLIL::constpad["synth_ice40.abc9.hx.W"] = "250"; - RTLIL::constpad["synth_ice40.abc9.lp.W"] = "400"; - RTLIL::constpad["synth_ice40.abc9.u.W"] = "750"; - } - - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -71,11 +64,8 @@ struct SynthIce40Pass : public ScriptPass log(" -noflatten\n"); log(" do not flatten design before synthesis\n"); log("\n"); - log(" -dff\n"); - log(" run 'abc'/'abc9' with -dff option\n"); - log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log(" -nocarry\n"); log(" do not use SB_CARRY cells in output netlist\n"); @@ -106,20 +96,17 @@ struct SynthIce40Pass : public ScriptPass log(" -abc9\n"); log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); - log(" -flowmap\n"); - log(" use FlowMap LUT techmapping instead of abc (EXPERIMENTAL)\n"); - log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); log("\n"); } - string top_opt, blif_file, edif_file, json_file, device_opt; - bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9, dff, flowmap; + string top_opt, blif_file, edif_file, json_file, abc, device_opt; + bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr; int min_ce_use; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; blif_file = ""; @@ -135,12 +122,11 @@ struct SynthIce40Pass : public ScriptPass noabc = false; abc2 = false; vpr = false; - abc9 = false; - flowmap = false; + abc = "abc"; device_opt = "hx"; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -221,21 +207,13 @@ struct SynthIce40Pass : public ScriptPass continue; } if (args[argidx] == "-abc9") { - abc9 = true; - continue; - } - if (args[argidx] == "-dff") { - dff = true; + abc = "abc9"; continue; } if (args[argidx] == "-device" && argidx+1 < args.size()) { device_opt = args[++argidx]; continue; } - if (args[argidx] == "-flowmap") { - flowmap = true; - continue; - } break; } extra_args(args, argidx, design); @@ -245,14 +223,8 @@ struct SynthIce40Pass : public ScriptPass if (device_opt != "hx" && device_opt != "lp" && device_opt !="u") log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str()); - if (abc9 && retime) + if (abc == "abc9" && retime) log_cmd_error("-retime option not currently compatible with -abc9!\n"); - if (abc9 && noabc) - log_cmd_error("-abc9 is incompatible with -noabc!\n"); - if (abc9 && flowmap) - log_cmd_error("-abc9 is incompatible with -flowmap!\n"); - if (flowmap && noabc) - log_cmd_error("-flowmap is incompatible with -noabc!\n"); log_header(design, "Executing SYNTH_ICE40 pass.\n"); log_push(); @@ -262,18 +234,18 @@ struct SynthIce40Pass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { - std::string define; - if (device_opt == "lp") - define = "-D ICE40_LP"; - else if (device_opt == "u") - define = "-D ICE40_U"; - else - define = "-D ICE40_HX"; if (check_label("begin")) { - run("read_verilog " + define + " -lib -specify +/ice40/cells_sim.v"); + std::string define; + if (device_opt == "lp") + define = "-D ICE40_LP"; + else if (device_opt == "u") + define = "-D ICE40_U"; + else + define = "-D ICE40_HX"; + run("read_verilog " + define + " -lib +/ice40/cells_sim.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); run("proc"); } @@ -301,8 +273,7 @@ struct SynthIce40Pass : public ScriptPass run("opt_expr"); run("opt_clean"); if (help_mode || dsp) { - run("memory_dff"); // ice40_dsp will merge registers, reserve memory port registers first - run("wreduce t:$mul"); + run("memory_dff"); run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); @@ -332,9 +303,7 @@ struct SynthIce40Pass : public ScriptPass if (check_label("map_ffram")) { run("opt -fast -mux_undef -undriven -fine"); - run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block " - "-attr syn_ramstyle=auto -attr syn_ramstyle=registers " - "-attr syn_romstyle=auto -attr syn_romstyle=logic"); + run("memory_map"); run("opt -undriven -fine"); } @@ -346,24 +315,21 @@ struct SynthIce40Pass : public ScriptPass run("ice40_wrapcarry"); run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); } - run("opt -fast"); if (retime || help_mode) - run("abc -dff -D 1", "(only if -retime)"); + run(abc + " -dff", "(only if -retime)"); run("ice40_opt"); } if (check_label("map_ffs")) { + run("dffsr2dff"); if (!nodffe) run("dff2dffe -direct-match $_DFF_*"); if (min_ce_use >= 0) { run("opt_merge"); run(stringf("dff2dffe -unmap-mince %d", min_ce_use)); - run("simplemap t:$dff"); } - if ((abc9 && dff) || help_mode) - run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff"); - run("techmap -map +/ice40/ff_map.v"); + run("techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v"); run("opt_expr -mux_undef"); run("simplemap"); run("ice40_ffinit"); @@ -374,47 +340,41 @@ struct SynthIce40Pass : public ScriptPass if (check_label("map_luts")) { if (abc2 || help_mode) { - run("abc", " (only if -abc2)"); + run(abc, " (only if -abc2)"); run("ice40_opt", "(only if -abc2)"); } run("techmap -map +/ice40/latches_map.v"); - if (noabc || flowmap || help_mode) { - run("simplemap", " (if -noabc or -flowmap)"); - if (noabc || help_mode) - run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)"); - if (flowmap || help_mode) - run("flowmap -maxlut 4", "(only if -flowmap)"); + if (noabc || help_mode) { + run("simplemap", " (only if -noabc)"); + run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)"); } if (!noabc) { - if (abc9) { - run("read_verilog " + define + " -icells -lib -specify +/ice40/abc9_model.v"); - std::string abc9_opts; - std::string k = "synth_ice40.abc9.W"; - if (active_design && active_design->scratchpad.count(k)) - abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str()); - else { - k = stringf("synth_ice40.abc9.%s.W", device_opt.c_str()); - abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); - } - if (dff) - abc9_opts += " -dff"; - run("abc9 " + abc9_opts); + if (abc == "abc9") { + run("read_verilog -icells -lib +/ice40/abc9_model.v"); + int wire_delay; + if (device_opt == "lp") + wire_delay = 400; + else if (device_opt == "u") + wire_delay = 750; + else + wire_delay = 250; + run(abc + stringf(" -W %d -lut +/ice40/abc9_%s.lut -box +/ice40/abc9_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); } else - run(stringf("abc -dress -lut 4 %s", dff ? "-dff" : ""), "(skip if -noabc)"); + run(abc + " -dress -lut 4", "(skip if -noabc)"); } - run("ice40_wrapcarry -unwrap"); - run("techmap -map +/ice40/ff_map.v"); + run("techmap -D NO_LUT -map +/ice40/cells_map.v"); run("clean"); run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0"); } if (check_label("map_cells")) { - if (help_mode) - run("techmap -map +/ice40/cells_map.v", "(skip if -vpr)"); - else if (!vpr) - run("techmap -map +/ice40/cells_map.v"); + if (vpr) + run("techmap -D NO_LUT -map +/ice40/cells_map.v"); + else + run("techmap -map +/ice40/cells_map.v", "(with -D NO_LUT in vpr mode)"); + run("clean"); } diff --git a/techlibs/intel/Makefile.inc b/techlibs/intel/Makefile.inc index f751e341f81..4e8f423c87b 100644 --- a/techlibs/intel/Makefile.inc +++ b/techlibs/intel/Makefile.inc @@ -7,7 +7,8 @@ $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k. $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v)) # Add the cell models and mappings for the VQM backend -families := max10 arria10gx cyclonev cyclone10lp cycloneiv cycloneive +families := max10 a10gx cyclonev cyclone10 cycloneiv cycloneive $(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v))) $(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v))) #$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v)) + diff --git a/techlibs/intel/arria10gx/cells_arith.v b/techlibs/intel/a10gx/cells_arith.v similarity index 95% rename from techlibs/intel/arria10gx/cells_arith.v rename to techlibs/intel/a10gx/cells_arith.v index 6a52a0f954d..89fb4561f83 100644 --- a/techlibs/intel/arria10gx/cells_arith.v +++ b/techlibs/intel/a10gx/cells_arith.v @@ -26,11 +26,8 @@ module _80_altera_a10gx_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; @@ -39,14 +36,11 @@ module _80_altera_a10gx_alu (A, B, CI, BI, X, Y, CO); wire _TECHMAP_FAIL_ = Y_WIDTH <= 4; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; //wire [Y_WIDTH:0] C = {CO, CI}; wire [Y_WIDTH+1:0] COx; diff --git a/techlibs/intel/arria10gx/cells_map.v b/techlibs/intel/a10gx/cells_map.v similarity index 98% rename from techlibs/intel/arria10gx/cells_map.v rename to techlibs/intel/a10gx/cells_map.v index 83f5881daba..1430e85514b 100644 --- a/techlibs/intel/arria10gx/cells_map.v +++ b/techlibs/intel/a10gx/cells_map.v @@ -30,7 +30,6 @@ endmodule module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; generate diff --git a/techlibs/intel/arria10gx/cells_sim.v b/techlibs/intel/a10gx/cells_sim.v similarity index 100% rename from techlibs/intel/arria10gx/cells_sim.v rename to techlibs/intel/a10gx/cells_sim.v diff --git a/techlibs/intel/cyclone10lp/cells_arith.v b/techlibs/intel/cyclone10/cells_arith.v similarity index 95% rename from techlibs/intel/cyclone10lp/cells_arith.v rename to techlibs/intel/cyclone10/cells_arith.v index d8c46e865b6..5ae8d6cea4a 100644 --- a/techlibs/intel/cyclone10lp/cells_arith.v +++ b/techlibs/intel/cyclone10/cells_arith.v @@ -26,11 +26,8 @@ module _80_altera_a10gx_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; @@ -39,14 +36,11 @@ module _80_altera_a10gx_alu (A, B, CI, BI, X, Y, CO); wire _TECHMAP_FAIL_ = Y_WIDTH <= 4; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; //wire [Y_WIDTH:0] C = {CO, CI}; wire [Y_WIDTH+1:0] COx; diff --git a/techlibs/intel/cyclone10lp/cells_map.v b/techlibs/intel/cyclone10/cells_map.v similarity index 98% rename from techlibs/intel/cyclone10lp/cells_map.v rename to techlibs/intel/cyclone10/cells_map.v index 25d73711c49..c2f6f403c14 100644 --- a/techlibs/intel/cyclone10lp/cells_map.v +++ b/techlibs/intel/cyclone10/cells_map.v @@ -48,7 +48,7 @@ module \$_DFF_PP0_ (input D, C, R, output Q); dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); endmodule -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); +module \$__DFFE_PP0 (input D, C, E, R, output Q); parameter WYSIWYG="TRUE"; parameter power_up=1'bx; wire E_i = ~ E; @@ -71,7 +71,6 @@ endmodule module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; generate diff --git a/techlibs/intel/cyclone10lp/cells_sim.v b/techlibs/intel/cyclone10/cells_sim.v similarity index 100% rename from techlibs/intel/cyclone10lp/cells_sim.v rename to techlibs/intel/cyclone10/cells_sim.v diff --git a/techlibs/intel/cycloneiv/cells_arith.v b/techlibs/intel/cycloneiv/cells_arith.v index f7bc3cd6599..010a4b5da92 100644 --- a/techlibs/intel/cycloneiv/cells_arith.v +++ b/techlibs/intel/cycloneiv/cells_arith.v @@ -70,11 +70,8 @@ module _80_cycloneiv_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; @@ -82,14 +79,11 @@ module _80_cycloneiv_alu (A, B, CI, BI, X, Y, CO); wire _TECHMAP_FAIL_ = Y_WIDTH < 6; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; wire [Y_WIDTH:0] C = {CO, CI}; diff --git a/techlibs/intel/cycloneiv/cells_map.v b/techlibs/intel/cycloneiv/cells_map.v index 56d32e58646..19148843030 100644 --- a/techlibs/intel/cycloneiv/cells_map.v +++ b/techlibs/intel/cycloneiv/cells_map.v @@ -48,7 +48,7 @@ module \$_DFF_PP0_ (input D, C, R, output Q); dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); endmodule -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); +module \$__DFFE_PP0 (input D, C, E, R, output Q); parameter WYSIWYG="TRUE"; parameter power_up=1'bx; wire E_i = ~ E; @@ -71,7 +71,6 @@ endmodule module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; generate diff --git a/techlibs/intel/cycloneive/arith_map.v b/techlibs/intel/cycloneive/arith_map.v index a755e10db73..49e36aa2519 100644 --- a/techlibs/intel/cycloneive/arith_map.v +++ b/techlibs/intel/cycloneive/arith_map.v @@ -66,11 +66,8 @@ module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; @@ -78,14 +75,11 @@ module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO); wire _TECHMAP_FAIL_ = Y_WIDTH < 5; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; wire [Y_WIDTH:0] C = {CO, CI}; diff --git a/techlibs/intel/cycloneive/cells_map.v b/techlibs/intel/cycloneive/cells_map.v index 43a1183dede..abeb92eefef 100644 --- a/techlibs/intel/cycloneive/cells_map.v +++ b/techlibs/intel/cycloneive/cells_map.v @@ -48,7 +48,7 @@ module \$_DFF_PP0_ (input D, C, R, output Q); dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); endmodule -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); +module \$__DFFE_PP0 (input D, C, E, R, output Q); parameter WYSIWYG="TRUE"; parameter power_up=1'bx; wire E_i = ~ E; @@ -71,7 +71,6 @@ endmodule module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; generate diff --git a/techlibs/intel/cyclonev/cells_arith.v b/techlibs/intel/cyclonev/cells_arith.v index 6a52a0f954d..89fb4561f83 100644 --- a/techlibs/intel/cyclonev/cells_arith.v +++ b/techlibs/intel/cyclonev/cells_arith.v @@ -26,11 +26,8 @@ module _80_altera_a10gx_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; @@ -39,14 +36,11 @@ module _80_altera_a10gx_alu (A, B, CI, BI, X, Y, CO); wire _TECHMAP_FAIL_ = Y_WIDTH <= 4; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; //wire [Y_WIDTH:0] C = {CO, CI}; wire [Y_WIDTH+1:0] COx; diff --git a/techlibs/intel/cyclonev/cells_map.v b/techlibs/intel/cyclonev/cells_map.v index 8223df3c6e0..f8d142bc9a9 100644 --- a/techlibs/intel/cyclonev/cells_map.v +++ b/techlibs/intel/cyclonev/cells_map.v @@ -50,7 +50,7 @@ module \$_DFF_PP0_ (input D, C, R, output Q); dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); endmodule -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); +module \$__DFFE_PP0 (input D, C, E, R, output Q); parameter WYSIWYG="TRUE"; parameter power_up=1'bx; wire E_i = ~ E; @@ -71,7 +71,6 @@ endmodule module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; wire VCC; diff --git a/techlibs/intel/max10/cells_arith.v b/techlibs/intel/max10/cells_arith.v index 8529706a7dd..e2194cbd7ba 100644 --- a/techlibs/intel/max10/cells_arith.v +++ b/techlibs/intel/max10/cells_arith.v @@ -26,11 +26,8 @@ module _80_altera_max10_alu (A, B, CI, BI, X, Y, CO); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; @@ -39,14 +36,11 @@ module _80_altera_max10_alu (A, B, CI, BI, X, Y, CO); wire _TECHMAP_FAIL_ = Y_WIDTH <= 4; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; //wire [Y_WIDTH:0] C = {CO, CI}; wire [Y_WIDTH+1:0] COx; diff --git a/techlibs/intel/max10/cells_map.v b/techlibs/intel/max10/cells_map.v index 55b39308068..6d604e0727b 100644 --- a/techlibs/intel/max10/cells_map.v +++ b/techlibs/intel/max10/cells_map.v @@ -48,7 +48,7 @@ module \$_DFF_PP0_ (input D, C, R, output Q); dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0)); endmodule -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); +module \$__DFFE_PP0 (input D, C, E, R, output Q); parameter WYSIWYG="TRUE"; parameter power_up=1'bx; wire E_i = ~ E; @@ -71,7 +71,6 @@ endmodule module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; generate diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index f3709498cb6..e5dc1adc753 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -26,9 +26,9 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct SynthIntelPass : public ScriptPass { - SynthIntelPass() : ScriptPass("synth_intel", "synthesis for Intel (Altera) FPGAs.") { experimental(); } + SynthIntelPass() : ScriptPass("synth_intel", "synthesis for Intel (Altera) FPGAs.") {} - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -36,10 +36,10 @@ struct SynthIntelPass : public ScriptPass { log("\n"); log("This command runs synthesis for Intel FPGAs.\n"); log("\n"); - log(" -family \n"); + log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n"); log(" generate the synthesis netlist for the specified family.\n"); log(" MAX10 is the default target if no family argument specified.\n"); - log(" For Cyclone IV GX devices, use cycloneiv argument; for Cyclone IV E, use cycloneive.\n"); + log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n"); log(" Cyclone V and Arria 10 GX devices are experimental.\n"); log("\n"); log(" -top \n"); @@ -71,7 +71,7 @@ struct SynthIntelPass : public ScriptPass { log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -81,7 +81,7 @@ struct SynthIntelPass : public ScriptPass { string top_opt, family_opt, vout_file, blif_file; bool retime, flatten, nobram, iopads; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; family_opt = "max10"; @@ -93,7 +93,7 @@ struct SynthIntelPass : public ScriptPass { iopads = false; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -148,11 +148,11 @@ struct SynthIntelPass : public ScriptPass { if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); if (family_opt != "max10" && - family_opt != "arria10gx" && + family_opt != "a10gx" && family_opt != "cyclonev" && family_opt != "cycloneiv" && family_opt != "cycloneive" && - family_opt != "cyclone10lp") + family_opt != "cyclone10") log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str()); log_header(design, "Executing SYNTH_INTEL pass.\n"); @@ -163,7 +163,7 @@ struct SynthIntelPass : public ScriptPass { log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { if (check_label("family")) @@ -187,10 +187,10 @@ struct SynthIntelPass : public ScriptPass { } if (!nobram && check_label("map_bram", "(skip if -nobram)")) { - if (family_opt == "cycloneiv" || - family_opt == "cycloneive" || - family_opt == "max10" || - help_mode) { + if (family_opt == "cycloneiv" || + family_opt == "cycloneive" || + family_opt == "max10" || + help_mode) { run("memory_bram -rules +/intel/common/brams_m9k.txt", "(if applicable for family)"); run("techmap -map +/intel/common/brams_map_m9k.v", "(if applicable for family)"); } else { @@ -202,6 +202,7 @@ struct SynthIntelPass : public ScriptPass { run("opt -fast -mux_undef -undriven -fine -full"); run("memory_map"); run("opt -undriven -fine"); + run("dffsr2dff"); run("dff2dffe -direct-match $_DFF_*"); run("opt -fine"); run("techmap -map +/techmap.v"); @@ -209,11 +210,11 @@ struct SynthIntelPass : public ScriptPass { run("clean -purge"); run("setundef -undriven -zero"); if (retime || help_mode) - run("abc -markgroups -dff -D 1", "(only if -retime)"); + run("abc -markgroups -dff", "(only if -retime)"); } if (check_label("map_luts")) { - if (family_opt == "arria10gx" || family_opt == "cyclonev") + if (family_opt == "a10gx" || family_opt == "cyclonev") run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); else run("abc -lut 4" + string(retime ? " -dff" : "")); @@ -223,7 +224,7 @@ struct SynthIntelPass : public ScriptPass { if (check_label("map_cells")) { if (iopads || help_mode) run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(if -iopads)"); - run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str())); + run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str())); run("dffinit -highlow -ff dffeas q power_up"); run("clean -purge"); } diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc deleted file mode 100644 index ed6c4510b95..00000000000 --- a/techlibs/intel_alm/Makefile.inc +++ /dev/null @@ -1,20 +0,0 @@ - -OBJS += techlibs/intel_alm/synth_intel_alm.o - -# Techmap -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_map.v)) -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_sim.v)) -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v)) -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_map.v)) -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_sim.v)) -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/mem_sim.v)) - -# RAM -bramtypes := m10k m20k -$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype).txt))) -$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype)_map.v))) -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab.txt)) - -# Miscellaneous -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/megafunction_bb.v)) -$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/quartus_rename.v)) diff --git a/techlibs/intel_alm/common/alm_map.v b/techlibs/intel_alm/common/alm_map.v deleted file mode 100644 index 6697b2e785c..00000000000 --- a/techlibs/intel_alm/common/alm_map.v +++ /dev/null @@ -1,57 +0,0 @@ -module \$lut (A, Y); - -parameter WIDTH = 1; -parameter LUT = 0; - -(* force_downto *) -input [WIDTH-1:0] A; -output Y; - -generate - if (WIDTH == 1) begin - generate - if (LUT == 2'b00) begin - assign Y = 1'b0; - end - else if (LUT == 2'b01) begin - MISTRAL_NOT _TECHMAP_REPLACE_( - .A(A[0]), .Q(Y) - ); - end - else if (LUT == 2'b10) begin - assign Y = A; - end - else if (LUT == 2'b11) begin - assign Y = 1'b1; - end - endgenerate - end else - if (WIDTH == 2) begin - MISTRAL_ALUT2 #(.LUT(LUT)) _TECHMAP_REPLACE_( - .A(A[0]), .B(A[1]), .Q(Y) - ); - end else - if (WIDTH == 3) begin - MISTRAL_ALUT3 #(.LUT(LUT)) _TECHMAP_REPLACE_( - .A(A[0]), .B(A[1]), .C(A[2]), .Q(Y) - ); - end else - if (WIDTH == 4) begin - MISTRAL_ALUT4 #(.LUT(LUT)) _TECHMAP_REPLACE_( - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .Q(Y) - ); - end else - if (WIDTH == 5) begin - MISTRAL_ALUT5 #(.LUT(LUT)) _TECHMAP_REPLACE_ ( - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .Q(Y) - ); - end else - if (WIDTH == 6) begin - MISTRAL_ALUT6 #(.LUT(LUT)) _TECHMAP_REPLACE_ ( - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .F(A[5]), .Q(Y) - ); - end else begin - wire _TECHMAP_FAIL_ = 1'b1; - end -endgenerate -endmodule diff --git a/techlibs/intel_alm/common/alm_sim.v b/techlibs/intel_alm/common/alm_sim.v deleted file mode 100644 index 979c511320f..00000000000 --- a/techlibs/intel_alm/common/alm_sim.v +++ /dev/null @@ -1,551 +0,0 @@ -// The core logic primitive of the Cyclone V/10GX is the Adaptive Logic Module -// (ALM). Each ALM is made up of an 8-input, 2-output look-up table, covered -// in this file, connected to combinational outputs, a carry chain, and four -// D flip-flops (which are covered as MISTRAL_FF in dff_sim.v). -// -// The ALM is vertically symmetric, so I find it helps to think in terms of -// half-ALMs, as that's predominantly the unit that synth_intel_alm uses. -// -// ALMs are quite flexible, having multiple modes. -// -// Normal (combinational) mode -// --------------------------- -// The ALM can implement: -// - a single 6-input function (with the other inputs usable for flip-flop access) -// - two 5-input functions that share two inputs -// - a 5-input and a 4-input function that share one input -// - a 5-input and a 3-or-less-input function that share no inputs -// - two 4-or-less-input functions that share no inputs -// -// Normal-mode functions are represented as MISTRAL_ALUTN cells with N inputs. -// It would be possible to represent a normal mode function as a single cell - -// the vendor cyclone{v,10gx}_lcell_comb cell does exactly that - but I felt -// it was more user-friendly to print out the specific function sizes -// separately. -// -// With the exception of MISTRAL_ALUT6, you can think of two normal-mode cells -// fitting inside a single ALM. -// -// Extended (7-input) mode -// ----------------------- -// The ALM can also fit a 7-input function made of two 5-input functions that -// share four inputs, multiplexed by another input. -// -// Because this can't accept arbitrary 7-input functions, Yosys can't handle -// it, so it doesn't have a cell, but I would likely call it MISTRAL_ALUT7(E?) -// if it did, and it would take up a full ALM. -// -// It might be possible to add an extraction pass to examine all ALUT5 cells -// that feed into ALUT3 cells to see if they can be combined into an extended -// ALM, but I don't think it will be worth it. -// -// Arithmetic mode -// --------------- -// In arithmetic mode, each half-ALM uses its carry chain to perform fast addition -// of two four-input functions that share three inputs. Oddly, the result of -// one of the functions is inverted before being added (you can see this as -// the dot on a full-adder input of Figure 1-8 in the Handbook). -// -// The cell for an arithmetic-mode half-ALM is MISTRAL_ALM_ARITH. One idea -// I've had (or rather was suggested by mwk) is that functions that feed into -// arithmetic-mode cells could be packed directly into the arithmetic-mode -// cell as a function, which reduces the number of ALMs needed. -// -// Shared arithmetic mode -// ---------------------- -// Shared arithmetic mode looks a lot like arithmetic mode, but here the -// output of every other four-input function goes to the input of the adder -// the next bit along. What this means is that adding three bits together can -// be done in an ALM, because functions can be used to implement addition that -// then feeds into the carry chain. This means that three bits can be added per -// ALM, as opposed to two in the arithmetic mode. -// -// Shared arithmetic mode doesn't currently have a cell, but I intend to add -// it as MISTRAL_ALM_SHARED, and have it occupy a full ALM. Because it adds -// three bits per cell, it makes addition shorter and use less ALMs, but -// I don't know enough to tell whether it's more efficient to use shared -// arithmetic mode to shorten the carry chain, or plain arithmetic mode with -// the functions packed in. - -`default_nettype none - -(* abc9_lut=2, lib_whitebox *) -module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); - -parameter [63:0] LUT = 64'h0000_0000_0000_0000; - -`ifdef cyclonev -specify - (A => Q) = 602; - (B => Q) = 584; - (C => Q) = 510; - (D => Q) = 510; - (E => Q) = 339; - (F => Q) = 94; -endspecify -`endif -`ifdef cyclone10gx -specify - (A => Q) = 275; - (B => Q) = 272; - (C => Q) = 175; - (D => Q) = 165; - (E => Q) = 162; - (F => Q) = 53; -endspecify -`endif - -assign Q = LUT >> {F, E, D, C, B, A}; - -endmodule - - -(* abc9_lut=1, lib_whitebox *) -module MISTRAL_ALUT5(input A, B, C, D, E, output Q); - -parameter [31:0] LUT = 32'h0000_0000; - -`ifdef cyclonev -specify - (A => Q) = 584; - (B => Q) = 510; - (C => Q) = 510; - (D => Q) = 339; - (E => Q) = 94; -endspecify -`endif -`ifdef cyclone10gx -specify - (A => Q) = 272; - (B => Q) = 175; - (C => Q) = 165; - (D => Q) = 162; - (E => Q) = 53; -endspecify -`endif - -assign Q = LUT >> {E, D, C, B, A}; - -endmodule - - -(* abc9_lut=1, lib_whitebox *) -module MISTRAL_ALUT4(input A, B, C, D, output Q); - -parameter [15:0] LUT = 16'h0000; - -`ifdef cyclonev -specify - (A => Q) = 510; - (B => Q) = 510; - (C => Q) = 339; - (D => Q) = 94; -endspecify -`endif -`ifdef cyclone10gx -specify - (A => Q) = 175; - (B => Q) = 165; - (C => Q) = 162; - (D => Q) = 53; -endspecify -`endif - -assign Q = LUT >> {D, C, B, A}; - -endmodule - - -(* abc9_lut=1, lib_whitebox *) -module MISTRAL_ALUT3(input A, B, C, output Q); - -parameter [7:0] LUT = 8'h00; - -`ifdef cyclonev -specify - (A => Q) = 510; - (B => Q) = 339; - (C => Q) = 94; -endspecify -`endif -`ifdef cyclone10gx -specify - (A => Q) = 165; - (B => Q) = 162; - (C => Q) = 53; -endspecify -`endif - -assign Q = LUT >> {C, B, A}; - -endmodule - - -(* abc9_lut=1, lib_whitebox *) -module MISTRAL_ALUT2(input A, B, output Q); - -parameter [3:0] LUT = 4'h0; - -`ifdef cyclonev -specify - (A => Q) = 339; - (B => Q) = 94; -endspecify -`endif -`ifdef cyclone10gx -specify - (A => Q) = 162; - (B => Q) = 53; -endspecify -`endif - -assign Q = LUT >> {B, A}; - -endmodule - - -(* abc9_lut=1, lib_whitebox *) -module MISTRAL_NOT(input A, output Q); - -`ifdef cyclonev -specify - (A => Q) = 94; -endspecify -`endif -`ifdef cyclone10gx -specify - (A => Q) = 53; -endspecify -`endif - -assign Q = ~A; - -endmodule - -(* abc9_box, lib_whitebox *) -module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO); - -parameter LUT0 = 16'h0000; -parameter LUT1 = 16'h0000; - -`ifdef cyclonev -specify - (A => SO) = 1283; - (B => SO) = 1167; - (C => SO) = 866; - (D0 => SO) = 756; - (D1 => SO) = 756; - (CI => SO) = 355; - (A => CO) = 950; - (B => CO) = 1039; - (C => CO) = 820; - (D0 => CO) = 1006; - (D1 => CO) = 1006; - (CI => CO) = 23; -endspecify -`endif -`ifdef cyclone10gx -specify - (A => SO) = 644; - (B => SO) = 477; - (C => SO) = 416; - (D0 => SO) = 380; - (D1 => SO) = 431; - (CI => SO) = 276; - (A => CO) = 525; - (B => CO) = 433; - (C => CO) = 712; - (D0 => CO) = 653; - (D1 => CO) = 593; - (CI => CO) = 16; -endspecify -`endif - -wire q0, q1; - -assign q0 = LUT0 >> {D0, C, B, A}; -assign q1 = LUT1 >> {D1, C, B, A}; - -assign {CO, SO} = q0 + !q1 + CI; - -endmodule - - -/* -// A, B, C0, C1, E0, E1, F0, F1: data inputs -// CARRYIN: carry input -// SHAREIN: shared-arithmetic input -// CLK0, CLK1, CLK2: clock inputs -// -// COMB0, COMB1: combinational outputs -// FF0, FF1, FF2, FF3: DFF outputs -// SUM0, SUM1: adder outputs -// CARRYOUT: carry output -// SHAREOUT: shared-arithmetic output -module MISTRAL_ALM( - input A, B, C0, C1, E0, E1, F0, F1, CARRYIN, SHAREIN, // LUT path - input CLK0, CLK1, CLK2, AC0, AC1, // FF path - output COMB0, COMB1, SUM0, SUM1, CARRYOUT, SHAREOUT, - output FF0, FF1, FF2, FF3 -); - -parameter LUT0 = 16'b0000; -parameter LUT1 = 16'b0000; -parameter LUT2 = 16'b0000; -parameter LUT3 = 16'b0000; - -parameter INIT0 = 1'b0; -parameter INIT1 = 1'b0; -parameter INIT2 = 1'b0; -parameter INIT3 = 1'b0; - -parameter C0_MUX = "C0"; -parameter C1_MUX = "C1"; - -parameter F0_MUX = "VCC"; -parameter F1_MUX = "GND"; - -parameter FEEDBACK0 = "FF0"; -parameter FEEDBACK1 = "FF2"; - -parameter ADD_MUX = "LUT"; - -parameter DFF01_DATA_MUX = "COMB"; -parameter DFF23_DATA_MUX = "COMB"; - -parameter DFF0_CLK = "CLK0"; -parameter DFF1_CLK = "CLK0"; -parameter DFF2_CLK = "CLK0"; -parameter DFF3_CLK = "CLK0"; - -parameter DFF0_AC = "AC0"; -parameter DFF1_AC = "AC0"; -parameter DFF2_AC = "AC0"; -parameter DFF3_AC = "AC0"; - -// Feedback muxes from the flip-flop outputs. -wire ff_feedback_mux0, ff_feedback_mux1; - -// C-input muxes which can be set to also use the F-input. -wire c0_input_mux, c1_input_mux; - -// F-input muxes which can be set to a constant to allow LUT5 use. -wire f0_input_mux, f1_input_mux; - -// Adder input muxes to select between shared-arithmetic mode and arithmetic mode. -wire add0_input_mux, add1_input_mux; - -// Combinational-output muxes for LUT #1 and LUT #3 -wire lut1_comb_mux, lut3_comb_mux; - -// Sum-output muxes for LUT #1 and LUT #3 -wire lut1_sum_mux, lut3_sum_mux; - -// DFF data-input muxes -wire dff01_data_mux, dff23_data_mux; - -// DFF clock selectors -wire dff0_clk, dff1_clk, dff2_clk, dff3_clk; - -// DFF asynchronous-clear selectors -wire dff0_ac, dff1_ac, dff2_ac, dff3_ac; - -// LUT, DFF and adder output wires for routing. -wire lut0_out, lut1a_out, lut1b_out, lut2_out, lut3a_out, lut3b_out; -wire dff0_out, dff1_out, dff2_out, dff3_out; -wire add0_sum, add1_sum, add0_carry, add1_carry; - -generate - if (FEEDBACK0 === "FF0") - assign ff_feedback_mux0 = dff0_out; - else if (FEEDBACK0 === "FF1") - assign ff_feedback_mux0 = dff1_out; - else - $error("Invalid FEEDBACK0 setting!"); - - if (FEEDBACK1 == "FF2") - assign ff_feedback_mux1 = dff2_out; - else if (FEEDBACK1 == "FF3") - assign ff_feedback_mux1 = dff3_out; - else - $error("Invalid FEEDBACK1 setting!"); - - if (C0_MUX === "C0") - assign c0_input_mux = C0; - else if (C0_MUX === "F1") - assign c0_input_mux = F1; - else if (C0_MUX === "FEEDBACK1") - assign c0_input_mux = ff_feedback_mux1; - else - $error("Invalid C0_MUX setting!"); - - if (C1_MUX === "C1") - assign c1_input_mux = C1; - else if (C1_MUX === "F0") - assign c1_input_mux = F0; - else if (C1_MUX === "FEEDBACK0") - assign c1_input_mux = ff_feedback_mux0; - else - $error("Invalid C1_MUX setting!"); - - // F0 == VCC is LUT5 - // F0 == F0 is LUT6 - // F0 == FEEDBACK is unknown - if (F0_MUX === "VCC") - assign f0_input_mux = 1'b1; - else if (F0_MUX === "F0") - assign f0_input_mux = F0; - else if (F0_MUX === "FEEDBACK0") - assign f0_input_mux = ff_feedback_mux0; - else - $error("Invalid F0_MUX setting!"); - - // F1 == GND is LUT5 - // F1 == F1 is LUT6 - // F1 == FEEDBACK is unknown - if (F1_MUX === "GND") - assign f1_input_mux = 1'b0; - else if (F1_MUX === "F1") - assign f1_input_mux = F1; - else if (F1_MUX === "FEEDBACK1") - assign f1_input_mux = ff_feedback_mux1; - else - $error("Invalid F1_MUX setting!"); - - if (ADD_MUX === "LUT") begin - assign add0_input_mux = ~lut1_sum_mux; - assign add1_input_mux = ~lut3_sum_mux; - end else if (ADD_MUX === "SHARE") begin - assign add0_input_mux = SHAREIN; - assign add1_input_mux = lut1_comb_mux; - end else - $error("Invalid ADD_MUX setting!"); - - if (DFF01_DATA_MUX === "COMB") - assign dff01_data_mux = COMB0; - else if (DFF01_DATA_MUX === "SUM") - assign dff01_data_mux = SUM0; - else - $error("Invalid DFF01_DATA_MUX setting!"); - - if (DFF23_DATA_MUX === "COMB") - assign dff23_data_mux = COMB0; - else if (DFF23_DATA_MUX === "SUM") - assign dff23_data_mux = SUM0; - else - $error("Invalid DFF23_DATA_MUX setting!"); - - if (DFF0_CLK === "CLK0") - assign dff0_clk = CLK0; - else if (DFF0_CLK === "CLK1") - assign dff0_clk = CLK1; - else if (DFF0_CLK === "CLK2") - assign dff0_clk = CLK2; - else - $error("Invalid DFF0_CLK setting!"); - - if (DFF1_CLK === "CLK0") - assign dff1_clk = CLK0; - else if (DFF1_CLK === "CLK1") - assign dff1_clk = CLK1; - else if (DFF1_CLK === "CLK2") - assign dff1_clk = CLK2; - else - $error("Invalid DFF1_CLK setting!"); - - if (DFF2_CLK === "CLK0") - assign dff2_clk = CLK0; - else if (DFF2_CLK === "CLK1") - assign dff2_clk = CLK1; - else if (DFF2_CLK === "CLK2") - assign dff2_clk = CLK2; - else - $error("Invalid DFF2_CLK setting!"); - - if (DFF3_CLK === "CLK0") - assign dff3_clk = CLK0; - else if (DFF3_CLK === "CLK1") - assign dff3_clk = CLK1; - else if (DFF3_CLK === "CLK2") - assign dff3_clk = CLK2; - else - $error("Invalid DFF3_CLK setting!"); - - if (DFF0_AC === "AC0") - assign dff0_ac = AC0; - else if (DFF0_AC === "AC1") - assign dff0_ac = AC1; - else - $error("Invalid DFF0_AC setting!"); - - if (DFF1_AC === "AC0") - assign dff1_ac = AC0; - else if (DFF1_AC === "AC1") - assign dff1_ac = AC1; - else - $error("Invalid DFF1_AC setting!"); - - if (DFF2_AC === "AC0") - assign dff2_ac = AC0; - else if (DFF2_AC === "AC1") - assign dff2_ac = AC1; - else - $error("Invalid DFF2_AC setting!"); - - if (DFF3_AC === "AC0") - assign dff3_ac = AC0; - else if (DFF3_AC === "AC1") - assign dff3_ac = AC1; - else - $error("Invalid DFF3_AC setting!"); - -endgenerate - -// F0 on the Quartus diagram -MISTRAL_ALUT4 #(.LUT(LUT0)) lut0 (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut0_out)); - -// F2 on the Quartus diagram -MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_comb (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut1_comb_mux)); -MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_sum (.A(A), .B(B), .C(C0), .D(E0), .Q(lut1_sum_mux)); - -// F1 on the Quartus diagram -MISTRAL_ALUT4 #(.LUT(LUT2)) lut2 (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut2_out)); - -// F3 on the Quartus diagram -MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_comb (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut3_comb_mux)); -MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_sum (.A(A), .B(B), .C(C1), .D(E1), .Q(lut3_sum_mux)); - -MISTRAL_FF #(.INIT(INIT0)) dff0 (.D(dff01_data_mux), .CLK(dff0_clk), .ACn(dff0_ac), .Q(dff0_out)); -MISTRAL_FF #(.INIT(INIT1)) dff1 (.D(dff01_data_mux), .CLK(dff1_clk), .ACn(dff1_ac), .Q(dff1_out)); -MISTRAL_FF #(.INIT(INIT2)) dff2 (.D(dff23_data_mux), .CLK(dff2_clk), .ACn(dff2_ac), .Q(dff2_out)); -MISTRAL_FF #(.INIT(INIT3)) dff3 (.D(dff23_data_mux), .CLK(dff3_clk), .ACn(dff3_ac), .Q(dff3_out)); - -// Adders -assign {add0_carry, add0_sum} = CARRYIN + lut0_out + lut1_sum_mux; -assign {add1_carry, add1_sum} = add0_carry + lut2_out + lut3_sum_mux; - -// COMBOUT outputs on the Quartus diagram -assign COMB0 = E0 ? (f0_input_mux ? lut3_comb_mux : lut1_comb_mux) - : (f0_input_mux ? lut2_out : lut0_out); - -assign COMB1 = E1 ? (f1_input_mux ? lut3_comb_mux : lut1_comb_mux) - : (f1_input_mux ? lut2_out : lut0_out); - -// SUMOUT output on the Quartus diagram -assign SUM0 = add0_sum; -assign SUM1 = add1_sum; - -// COUT output on the Quartus diagram -assign CARRYOUT = add1_carry; - -// SHAREOUT output on the Quartus diagram -assign SHAREOUT = lut3_comb_mux; - -// REGOUT outputs on the Quartus diagram -assign FF0 = dff0_out; -assign FF1 = dff1_out; -assign FF2 = dff2_out; -assign FF3 = dff3_out; - -endmodule -*/ diff --git a/techlibs/intel_alm/common/arith_alm_map.v b/techlibs/intel_alm/common/arith_alm_map.v deleted file mode 100644 index 8515eeb5625..00000000000 --- a/techlibs/intel_alm/common/arith_alm_map.v +++ /dev/null @@ -1,71 +0,0 @@ -`default_nettype none - -module \$alu (A, B, CI, BI, X, Y, CO); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -parameter _TECHMAP_CONSTMSK_CI_ = 0; -parameter _TECHMAP_CONSTVAL_CI_ = 0; - -(* force_downto *) -input [A_WIDTH-1:0] A; -(* force_downto *) -input [B_WIDTH-1:0] B; -input CI, BI; -(* force_downto *) -output [Y_WIDTH-1:0] X, Y, CO; - -(* force_downto *) -wire [Y_WIDTH-1:0] A_buf, B_buf; -\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - -(* force_downto *) -wire [Y_WIDTH-1:0] AA = A_buf; -(* force_downto *) -wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; -(* force_downto *) -wire [Y_WIDTH-1:0] BX = B_buf; -wire [Y_WIDTH:0] ALM_CARRY; - -// Start of carry chain -generate - if (_TECHMAP_CONSTMSK_CI_ == 1) begin - assign ALM_CARRY[0] = _TECHMAP_CONSTVAL_CI_; - end else begin - MISTRAL_ALUT_ARITH #( - .LUT0(16'b1010_1010_1010_1010), // Q = A - .LUT1(16'b0000_0000_0000_0000), // Q = 0 (LUT1's input to the adder is inverted) - ) alm_start ( - .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), - .CI(1'b0), - .CO(ALM_CARRY[0]) - ); - end -endgenerate - -// Carry chain -genvar i; -generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice - // TODO: mwk suggests that a pass could merge pre-adder logic into this. - MISTRAL_ALUT_ARITH #( - .LUT0(16'b1010_1010_1010_1010), // Q = A - .LUT1(16'b1100_0011_1100_0011), // Q = C ? B : ~B (LUT1's input to the adder is inverted) - ) alm_i ( - .A(AA[i]), .B(BX[i]), .C(BI), .D0(1'b1), .D1(1'b1), - .CI(ALM_CARRY[i]), - .SO(Y[i]), - .CO(ALM_CARRY[i+1]) - ); - - // ALM carry chain is not directly accessible, so calculate the carry through soft logic if really needed. - assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i])); -end endgenerate - -assign X = AA ^ BB; - -endmodule diff --git a/techlibs/intel_alm/common/bram_m10k.txt b/techlibs/intel_alm/common/bram_m10k.txt deleted file mode 100644 index 837e3a33032..00000000000 --- a/techlibs/intel_alm/common/bram_m10k.txt +++ /dev/null @@ -1,33 +0,0 @@ -bram __MISTRAL_M10K_SDP - init 0 # TODO: Re-enable when I figure out how BRAM init works - abits 13 @D8192x1 - dbits 1 @D8192x1 - abits 12 @D4096x2 - dbits 2 @D4096x2 - abits 11 @D2048x4 @D2048x5 - dbits 4 @D2048x4 - dbits 5 @D2048x5 - abits 10 @D1024x8 @D1024x10 - dbits 8 @D1024x8 - dbits 10 @D1024x10 - abits 9 @D512x16 @D512x20 - dbits 16 @D512x16 - dbits 20 @D512x20 - abits 8 @D256x32 @D256x40 - dbits 32 @D256x32 - dbits 40 @D256x40 - groups 2 - ports 1 1 - wrmode 1 0 - # read enable; write enable + byte enables (only for multiples of 8) - enable 1 1 - transp 0 0 - clocks 1 1 - clkpol 1 1 -endbram - - -match __MISTRAL_M10K_SDP - min efficiency 5 - make_transp -endmatch diff --git a/techlibs/intel_alm/common/bram_m10k_map.v b/techlibs/intel_alm/common/bram_m10k_map.v deleted file mode 100644 index 061463c3e1d..00000000000 --- a/techlibs/intel_alm/common/bram_m10k_map.v +++ /dev/null @@ -1,31 +0,0 @@ -module __MISTRAL_M10K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); - -parameter CFG_ABITS = 10; -parameter CFG_DBITS = 10; -parameter CFG_ENABLE_A = 1; -parameter CFG_ENABLE_B = 1; - -input CLK1; -input [CFG_ABITS-1:0] A1ADDR, B1ADDR; -input [CFG_DBITS-1:0] A1DATA; -output [CFG_DBITS-1:0] B1DATA; -input [CFG_ENABLE_A-1:0] A1EN, B1EN; - -altsyncram #( - .operation_mode("dual_port"), - .ram_block_type("m10k"), - .widthad_a(CFG_ABITS), - .width_a(CFG_DBITS), - .widthad_b(CFG_ABITS), - .width_b(CFG_DBITS), -) _TECHMAP_REPLACE_ ( - .address_a(A1ADDR), - .data_a(A1DATA), - .wren_a(A1EN), - .address_b(B1ADDR), - .q_b(B1DATA), - .clock0(CLK1), - .clock1(CLK1) -); - -endmodule diff --git a/techlibs/intel_alm/common/bram_m20k.txt b/techlibs/intel_alm/common/bram_m20k.txt deleted file mode 100644 index b4c5a537287..00000000000 --- a/techlibs/intel_alm/common/bram_m20k.txt +++ /dev/null @@ -1,33 +0,0 @@ -bram __MISTRAL_M20K_SDP - init 1 # TODO: Re-enable when I figure out how BRAM init works - abits 14 @D16384x1 - dbits 1 @D16384x1 - abits 13 @D8192x2 - dbits 2 @D8192x2 - abits 12 @D4096x4 @D4096x5 - dbits 4 @D4096x4 - dbits 5 @D4096x5 - abits 11 @D2048x8 @D2048x10 - dbits 8 @D2048x8 - dbits 10 @D2048x10 - abits 10 @D1024x16 @D1024x20 - dbits 16 @D1024x16 - dbits 20 @D1024x20 - abits 9 @D512x32 @D512x40 - dbits 32 @D512x32 - dbits 40 @D512x40 - groups 2 - ports 1 1 - wrmode 1 0 - # read enable; write enable + byte enables (only for multiples of 8) - enable 1 1 - transp 0 0 - clocks 1 1 - clkpol 1 1 -endbram - - -match __MISTRAL_M20K_SDP - min efficiency 5 - make_transp -endmatch diff --git a/techlibs/intel_alm/common/bram_m20k_map.v b/techlibs/intel_alm/common/bram_m20k_map.v deleted file mode 100644 index 92f41310f67..00000000000 --- a/techlibs/intel_alm/common/bram_m20k_map.v +++ /dev/null @@ -1,31 +0,0 @@ -module __MISTRAL_M20K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); - -parameter CFG_ABITS = 10; -parameter CFG_DBITS = 20; -parameter CFG_ENABLE_A = 1; -parameter CFG_ENABLE_B = 1; - -input CLK1; -input [CFG_ABITS-1:0] A1ADDR, B1ADDR; -input [CFG_DBITS-1:0] A1DATA; -output [CFG_DBITS-1:0] B1DATA; -input [CFG_ENABLE_A-1:0] A1EN, B1EN; - -altsyncram #( - .operation_mode("dual_port"), - .ram_block_type("m20k"), - .widthad_a(CFG_ABITS), - .width_a(CFG_DBITS), - .widthad_b(CFG_ABITS), - .width_b(CFG_DBITS), -) _TECHMAP_REPLACE_ ( - .address_a(A1ADDR), - .data_a(A1DATA), - .wren_a(A1EN), - .address_b(B1ADDR), - .q_b(B1DATA), - .clock0(CLK1), - .clock1(CLK1) -); - -endmodule diff --git a/techlibs/intel_alm/common/dff_map.v b/techlibs/intel_alm/common/dff_map.v deleted file mode 100644 index 962be670c65..00000000000 --- a/techlibs/intel_alm/common/dff_map.v +++ /dev/null @@ -1,124 +0,0 @@ -`default_nettype none - -// D flip-flops -module \$_DFF_P_ (input D, C, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop that initialises to one"); -endmodule - -module \$_DFF_N_ (input D, C, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop that initialises to one"); -endmodule - -// D flip-flops with reset -module \$_DFF_PP0_ (input D, C, R, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop with reset that initialises to one"); -endmodule - -module \$_DFF_PN0_ (input D, C, R, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop with reset that initialises to one"); -endmodule - -module \$_DFF_NP0_ (input D, C, R, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop with reset that initialises to one"); -endmodule - -module \$_DFF_NN0_ (input D, C, R, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop with reset that initialises to one"); -endmodule - -// D flip-flops with set -module \$_DFF_PP1_ (input D, C, R, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b1; -if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - wire Q_tmp; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp)); - assign Q = ~Q_tmp; -end else $error("Cannot implement a flip-flop with set that initialises to zero"); -endmodule - -module \$_DFF_PN1_ (input D, C, R, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b1; -if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - wire Q_tmp; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp)); -end else $error("Cannot implement a flip-flop with set that initialises to zero"); -endmodule - -module \$_DFF_NP1_ (input D, C, R, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b1; -if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - wire Q_tmp; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp)); - assign Q = ~Q_tmp; -end else $error("Cannot implement a flip-flop with set that initialises to zero"); -endmodule - -module \$_DFF_NN1_ (input D, C, R, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b1; -if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - wire Q_tmp; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp)); - assign Q = ~Q_tmp; -end else $error("Cannot implement a flip-flop with set that initialises to zero"); -endmodule - -// D flip-flops with clock enable -module \$_DFFE_PP_ (input D, C, E, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop with enable that initialises to one"); -endmodule - -module \$_DFFE_PN_ (input D, C, E, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop with enable that initialises to one"); -endmodule - -module \$_DFFE_NP_ (input D, C, E, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop with enable that initialises to one"); -endmodule - -module \$_DFFE_NN_ (input D, C, E, output Q); -parameter _TECHMAP_WIREINIT_Q_ = 1'b0; -if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); -end else $error("Cannot implement a flip-flop with enable that initialises to one"); -endmodule diff --git a/techlibs/intel_alm/common/dff_sim.v b/techlibs/intel_alm/common/dff_sim.v deleted file mode 100644 index 32444dd46e8..00000000000 --- a/techlibs/intel_alm/common/dff_sim.v +++ /dev/null @@ -1,92 +0,0 @@ -// The four D flip-flops (DFFs) in a Cyclone V/10GX Adaptive Logic Module (ALM) -// act as one-bit memory cells that can be placed very flexibly (wherever there's -// an ALM); each flop is represented by a MISTRAL_FF cell. -// -// The flops in these chips are rather flexible in some ways, but in practice -// quite crippled by FPGA standards. -// -// What the flops can do -// --------------------- -// The core flop acts as a single-bit memory that initialises to zero at chip -// reset. It takes in data on the rising edge of CLK if ENA is high, -// and outputs it to Q. The ENA (clock enable) pin can therefore be used to -// capture the input only if a condition is true. -// -// The data itself is zero if SCLR (synchronous clear) is high, else it comes -// from SDATA (synchronous data) if SLOAD (synchronous load) is high, or DATAIN -// if SLOAD is low. -// -// If ACLR (asynchronous clear) is low then Q is forced to zero, regardless of -// the synchronous inputs or CLK edge. This is most often used for an FPGA-wide -// power-on reset. -// -// An asynchronous set that sets Q to one can be emulated by inverting the input -// and output of the flop, resulting in ACLR forcing Q to zero, which then gets -// inverted to produce one. Likewise, logic can operate on the falling edge of -// CLK if CLK is inverted before being passed as an input. -// -// What the flops *can't* do -// ------------------------- -// The trickiest part of the above capabilities is the lack of configurable -// initialisation state. For example, it isn't possible to implement a flop with -// asynchronous clear that initialises to one, because the hardware initialises -// to zero. Likewise, you can't emulate a flop with asynchronous set that -// initialises to zero, because the inverters mean the flop initialises to one. -// -// If the input design requires one of these cells (which appears to be rare -// in practice) then synth_intel_alm will fail to synthesize the design where -// other Yosys synthesis scripts might succeed. -// -// This stands in notable contrast to e.g. Xilinx flip-flops, which have -// configurable initialisation state and native synchronous/asynchronous -// set/clear (although not at the same time), which means they can generally -// implement a much wider variety of logic. - -// DATAIN: synchronous data input -// CLK: clock input (positive edge) -// ACLR: asynchronous clear (negative-true) -// ENA: clock-enable -// SCLR: synchronous clear -// SLOAD: synchronous load -// SDATA: synchronous load data -// -// Q: data output -// -// Note: the DFFEAS primitive is mostly emulated; it does not reflect what the hardware implements. -module MISTRAL_FF( - input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, - output reg Q -); - -`ifdef cyclonev -specify - (posedge CLK => (Q : DATAIN)) = 262; - $setup(DATAIN, posedge CLK, 522); -endspecify -`endif -`ifdef cyclone10gx -specify - (posedge CLK => (Q : DATAIN)) = 219; - $setup(DATAIN, posedge CLK, 268); -endspecify -`endif - -initial begin - // Altera flops initialise to zero. - Q = 0; -end - -always @(posedge CLK, negedge ACLR) begin - // Asynchronous clear - if (!ACLR) Q <= 0; - // Clock-enable - else if (ENA) begin - // Synchronous clear - if (SCLR) Q <= 0; - // Synchronous load - else if (SLOAD) Q <= SDATA; - else Q <= DATAIN; - end -end - -endmodule diff --git a/techlibs/intel_alm/common/lutram_mlab.txt b/techlibs/intel_alm/common/lutram_mlab.txt deleted file mode 100644 index 3cc69399dbf..00000000000 --- a/techlibs/intel_alm/common/lutram_mlab.txt +++ /dev/null @@ -1,18 +0,0 @@ -bram MISTRAL_MLAB - init 0 # TODO: Re-enable when Yosys remembers the original filename. - abits 5 - dbits 1 - groups 2 - ports 1 1 - wrmode 1 0 - # write enable - enable 1 0 - transp 0 0 - clocks 1 0 - clkpol 1 1 -endbram - -match MISTRAL_MLAB - min efficiency 5 - make_outreg -endmatch \ No newline at end of file diff --git a/techlibs/intel_alm/common/megafunction_bb.v b/techlibs/intel_alm/common/megafunction_bb.v deleted file mode 100644 index c749fa70bd7..00000000000 --- a/techlibs/intel_alm/common/megafunction_bb.v +++ /dev/null @@ -1,131 +0,0 @@ -// Intel megafunction declarations, to avoid Yosys complaining. -`default_nettype none - -(* blackbox *) -module altera_std_synchronizer(clk, din, dout, reset_n); - -parameter depth = 2; - -input clk; -input reset_n; -input din; -output dout; - -endmodule - -(* blackbox *) -module altiobuf_in(datain, dataout); - -parameter enable_bus_hold = "FALSE"; -parameter use_differential_mode = "FALSE"; -parameter number_of_channels = 1; - -input [number_of_channels-1:0] datain; -output [number_of_channels-1:0] dataout; - -endmodule - -(* blackbox *) -module altiobuf_out(datain, dataout); - -parameter enable_bus_hold = "FALSE"; -parameter use_differential_mode = "FALSE"; -parameter use_oe = "FALSE"; -parameter number_of_channels = 1; - -input [number_of_channels-1:0] datain; -output [number_of_channels-1:0] dataout; - -endmodule - -(* blackbox *) -module altiobuf_bidir(dataio, oe, datain, dataout); - -parameter number_of_channels = 1; -parameter enable_bus_hold = "OFF"; - -inout [number_of_channels-1:0] dataio; -input [number_of_channels-1:0] datain; -output [number_of_channels-1:0] dataout; -input [number_of_channels-1:0] oe; - -endmodule - -(* blackbox *) -module altsyncram(clock0, clock1, address_a, data_a, rden_a, wren_a, byteena_a, q_a, addressstall_a, address_b, data_b, rden_b, wren_b, byteena_b, q_b, addressstall_b, clocken0, clocken1, clocken2, clocken3, aclr0, aclr1, eccstatus); - -parameter lpm_type = "altsyncram"; -parameter operation_mode = "dual_port"; -parameter ram_block_type = "auto"; -parameter intended_device_family = "auto"; -parameter power_up_uninitialized = "false"; -parameter read_during_write_mode_mixed_ports = "dontcare"; -parameter byte_size = 8; -parameter widthad_a = 1; -parameter width_a = 1; -parameter width_byteena_a = 1; -parameter numwords_a = 1; -parameter clock_enable_input_a = "clocken0"; -parameter widthad_b = 1; -parameter width_b = 1; -parameter numwords_b = 1; -parameter address_aclr_b = "aclr0"; -parameter address_reg_b = ""; -parameter outdata_aclr_b = "aclr0"; -parameter outdata_reg_b = ""; -parameter clock_enable_input_b = "clocken0"; -parameter clock_enable_output_b = "clocken0"; - -input clock0, clock1; -input [widthad_a-1:0] address_a; -input [width_a-1:0] data_a; -input rden_a; -input wren_a; -input [(width_a/8)-1:0] byteena_a; -input addressstall_a; - -output [width_a-1:0] q_a; - -input wren_b; -input rden_b; -input [widthad_b-1:0] address_b; -input [width_b-1:0] data_b; -input [(width_b/8)-1:0] byteena_b; -input addressstall_b; - -output [width_b-1:0] q_b; - -input clocken0; -input clocken1; -input clocken2; -input clocken3; - -input aclr0; -input aclr1; - -output eccstatus; - -endmodule - -(* blackbox *) -module cyclonev_mlab_cell(portaaddr, portadatain, portbaddr, portbdataout, ena0, clk0, clk1); - -parameter logical_ram_name = ""; -parameter logical_ram_depth = 32; -parameter logical_ram_width = 20; -parameter mixed_port_feed_through_mode = "new"; -parameter first_bit_number = 0; -parameter first_address = 0; -parameter last_address = 31; -parameter address_width = 5; -parameter data_width = 1; -parameter byte_enable_mask_width = 1; -parameter port_b_data_out_clock = "NONE"; -parameter [639:0] mem_init0 = 640'b0; - -input [address_width-1:0] portaaddr, portbaddr; -input [data_width-1:0] portadatain; -output [data_width-1:0] portbdataout; -input ena0, clk0, clk1; - -endmodule diff --git a/techlibs/intel_alm/common/mem_sim.v b/techlibs/intel_alm/common/mem_sim.v deleted file mode 100644 index ae79b19a42e..00000000000 --- a/techlibs/intel_alm/common/mem_sim.v +++ /dev/null @@ -1,60 +0,0 @@ -// The MLAB -// -------- -// In addition to Logic Array Blocks (LABs) that contain ten Adaptive Logic -// Modules (ALMs, see alm_sim.v), the Cyclone V/10GX also contain -// Memory/Logic Array Blocks (MLABs) that can act as either ten ALMs, or utilise -// the memory the ALM uses to store the look-up table data for general usage, -// producing a 32 address by 20-bit block of memory. MLABs are spread out -// around the chip, so they can be placed near where they are needed, rather than -// being comparatively limited in placement for a deep but narrow memory such as -// the M10K memory block. -// -// MLABs are used mainly for shallow but wide memories, such as CPU register -// files (which have perhaps 32 registers that are comparatively wide (16/32-bit)) -// or shift registers (by using the output of the Nth bit as input for the N+1th -// bit). -// -// Oddly, instead of providing a block 32 address by 20-bit cell, Quartus asks -// synthesis tools to build MLABs out of 32 address by 1-bit cells, and tries -// to put these cells in the same MLAB during cell placement. Because of this -// a MISTRAL_MLAB cell represents one of these 32 address by 1-bit cells, and -// 20 of them represent a physical MLAB. -// -// How the MLAB works -// ------------------ -// MLABs are poorly documented, so the following information is based mainly -// on the simulation model and my knowledge of how memories like these work. -// Additionally, note that the ports of MISTRAL_MLAB are the ones auto-generated -// by the Yosys `memory_bram` pass, and it doesn't make sense to me to use -// `techmap` just for the sake of renaming the cell ports. -// -// The MLAB can be initialised to any value, but unfortunately Quartus only -// allows memory initialisation from a file. Since Yosys doesn't preserve input -// file information, or write the contents of an `initial` block to a file, -// Yosys can't currently initialise the MLAB in a way Quartus will accept. -// -// The MLAB takes in data from A1DATA at the rising edge of CLK1, and if A1EN -// is high, writes it to the address in A1ADDR. A1EN can therefore be used to -// conditionally write data to the MLAB. -// -// Simultaneously, the MLAB reads data from B1ADDR, and outputs it to B1DATA, -// asynchronous to CLK1 and ignoring A1EN. If a synchronous read is needed -// then the output can be fed to embedded flops. Presently, Yosys assumes -// Quartus will pack external flops into the MLAB, but this is an assumption -// that needs testing. - -// The vendor sim model outputs 'x for a very short period (a few -// combinational delta cycles) after each write. This has been omitted from -// the following model because it's very difficult to trigger this in practice -// as clock cycles will be much longer than any potential blip of 'x, so the -// model can be treated as always returning a defined result. -module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA); - -reg [31:0] mem = 32'b0; - -always @(posedge CLK1) - if (A1EN) mem[A1ADDR] <= A1DATA; - -assign B1DATA = mem[B1ADDR]; - -endmodule diff --git a/techlibs/intel_alm/common/quartus_rename.v b/techlibs/intel_alm/common/quartus_rename.v deleted file mode 100644 index c40a4e02d1e..00000000000 --- a/techlibs/intel_alm/common/quartus_rename.v +++ /dev/null @@ -1,121 +0,0 @@ -`ifdef cyclonev -`define LCELL cyclonev_lcell_comb -`define MLAB cyclonev_mlab_cell -`endif -`ifdef cyclone10gx -`define LCELL cyclone10gx_lcell_comb -`define MLAB cyclone10gx_mlab_cell -`endif - -module __MISTRAL_VCC(output Q); - -MISTRAL_ALUT2 #(.LUT(4'b1111)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q)); - -endmodule - - -module __MISTRAL_GND(output Q); - -MISTRAL_ALUT2 #(.LUT(4'b0000)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q)); - -endmodule - - -module MISTRAL_FF(input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, output reg Q); - -dffeas #(.power_up("low"), .is_wysiwyg("true")) _TECHMAP_REPLACE_ (.d(DATAIN), .clk(CLK), .clrn(ACLR), .ena(ENA), .sclr(SCLR), .sload(SLOAD), .asdata(SDATA), .q(Q)); - -endmodule - - -module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); -parameter [63:0] LUT = 64'h0000_0000_0000_0000; - -`LCELL #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT5(input A, B, C, D, E, output Q); -parameter [31:0] LUT = 32'h0000_0000; - -`LCELL #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT4(input A, B, C, D, output Q); -parameter [15:0] LUT = 16'h0000; - -`LCELL #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT3(input A, B, C, output Q); -parameter [7:0] LUT = 8'h00; - -`LCELL #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT2(input A, B, output Q); -parameter [3:0] LUT = 4'h0; - -`LCELL #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); - -endmodule - - -module MISTRAL_NOT(input A, output Q); - -NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); - -endmodule - - -module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO); -parameter LUT0 = 16'h0000; -parameter LUT1 = 16'h0000; - -`LCELL #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO)); - -endmodule - - -module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA); - -// Here we get to an unfortunate situation. The cell has a mem_init0 parameter, -// which takes in a hexadecimal string that could be used to initialise RAM. -// In the vendor simulation models, this appears to work fine, but Quartus, -// either intentionally or not, forgets about this parameter and initialises the -// RAM to zero. -// -// Because of this, RAM initialisation is presently disabled, but the source -// used to generate mem_init0 is kept (commented out) in case this gets fixed -// or an undocumented way to get Quartus to initialise from mem_init0 is found. - -`MLAB #( - .logical_ram_name("MISTRAL_MLAB"), - .logical_ram_depth(32), - .logical_ram_width(1), - .mixed_port_feed_through_mode("Dont Care"), - .first_bit_number(0), - .first_address(0), - .last_address(31), - .address_width(5), - .data_width(1), - .byte_enable_mask_width(1), - .port_b_data_out_clock("NONE"), - // .mem_init0($sformatf("%08x", INIT)) -) _TECHMAP_REPLACE_ ( - .portaaddr(A1ADDR), - .portadatain(A1DATA), - .portbaddr(B1ADDR), - .portbdataout(B1DATA), - .ena0(A1EN), - .clk0(CLK1) -); - -endmodule diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc deleted file mode 100644 index fabfc9003e3..00000000000 --- a/techlibs/intel_alm/synth_intel_alm.cc +++ /dev/null @@ -1,249 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Claire Wolf - * Copyright (C) 2019 Dan Ravensloft - * - * 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/celltypes.h" -#include "kernel/log.h" -#include "kernel/register.h" -#include "kernel/rtlil.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct SynthIntelALMPass : public ScriptPass { - SynthIntelALMPass() : ScriptPass("synth_intel_alm", "synthesis for ALM-based Intel (Altera) FPGAs.") {} - - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" synth_intel_alm [options]\n"); - log("\n"); - log("This command runs synthesis for ALM-based Intel FPGAs.\n"); - log("\n"); - log(" -top \n"); - log(" use the specified module as top module (default='top')\n"); - log("\n"); - log(" -family \n"); - log(" target one of:\n"); - log(" \"cyclonev\" - Cyclone V (default)\n"); - log(" \"cyclone10gx\" - Cyclone 10GX\n"); - log("\n"); - log(" -quartus\n"); - log(" output a netlist using Quartus cells instead of MISTRAL_* cells\n"); - log("\n"); - log(" -vqm \n"); - log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n"); - log(" output file is omitted if this parameter is not specified. Implies -quartus.\n"); - log("\n"); - log(" -run :\n"); - log(" only run the commands between the labels (see below). an empty\n"); - log(" from label is synonymous to 'begin', and empty to label is\n"); - log(" synonymous to the end of the command list.\n"); - log("\n"); - log(" -nolutram\n"); - log(" do not use LUT RAM cells in output netlist\n"); - log("\n"); - log(" -nobram\n"); - log(" do not use block RAM cells in output netlist\n"); - log("\n"); - log(" -noflatten\n"); - log(" do not flatten design before synthesis\n"); - log("\n"); - log("The following commands are executed by this synthesis command:\n"); - help_script(); - log("\n"); - } - - string top_opt, family_opt, bram_type, vout_file; - bool flatten, quartus, nolutram, nobram; - - void clear_flags() override - { - top_opt = "-auto-top"; - family_opt = "cyclonev"; - bram_type = "m10k"; - vout_file = ""; - flatten = true; - quartus = false; - nolutram = false; - nobram = false; - } - - void execute(std::vector args, RTLIL::Design *design) override - { - string run_from, run_to; - clear_flags(); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-family" && argidx + 1 < args.size()) { - family_opt = args[++argidx]; - continue; - } - if (args[argidx] == "-top" && argidx + 1 < args.size()) { - top_opt = "-top " + args[++argidx]; - continue; - } - if (args[argidx] == "-vqm" && argidx + 1 < args.size()) { - quartus = true; - vout_file = args[++argidx]; - continue; - } - if (args[argidx] == "-run" && argidx + 1 < args.size()) { - size_t pos = args[argidx + 1].find(':'); - if (pos == std::string::npos) - break; - run_from = args[++argidx].substr(0, pos); - run_to = args[argidx].substr(pos + 1); - continue; - } - if (args[argidx] == "-quartus") { - quartus = true; - continue; - } - if (args[argidx] == "-nolutram") { - nolutram = true; - continue; - } - if (args[argidx] == "-nobram") { - nobram = true; - continue; - } - if (args[argidx] == "-noflatten") { - flatten = false; - continue; - } - break; - } - extra_args(args, argidx, design); - - if (!design->full_selection()) - log_cmd_error("This command only operates on fully selected designs!\n"); - - if (family_opt == "cyclonev") { - bram_type = "m10k"; - } else if (family_opt == "cyclone10gx") { - bram_type = "m20k"; - } else { - log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str()); - } - - log_header(design, "Executing SYNTH_INTEL_ALM pass.\n"); - log_push(); - - run_script(design, run_from, run_to); - - log_pop(); - } - - void script() override - { - if (help_mode) { - family_opt = ""; - bram_type = ""; - } - - if (check_label("begin")) { - run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str())); - run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str())); - run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str())); - run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt.c_str())); - - // Misc and common cells - run("read_verilog -lib +/intel/common/altpll_bb.v"); - run("read_verilog -lib +/intel_alm/common/megafunction_bb.v"); - run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); - } - - if (flatten && check_label("flatten", "(unless -noflatten)")) { - run("proc"); - run("flatten"); - run("tribuf -logic"); - run("deminout"); - } - - if (check_label("coarse")) { - run("synth -run coarse -lut 6"); - run("techmap -map +/intel_alm/common/arith_alm_map.v"); - } - - if (!nobram && check_label("map_bram", "(skip if -nobram)")) { - run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str())); - run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str())); - } - - if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { - run("memory_bram -rules +/intel_alm/common/lutram_mlab.txt", "(for Cyclone V / Cyclone 10GX)"); - } - - if (check_label("map_ffram")) { - run("memory_map"); - run("opt -full"); - } - - if (check_label("map_ffs")) { - run("dff2dffe"); - // As mentioned in common/dff_sim.v, Intel flops power up to zero, - // so use `zinit` to add inverters where needed. - run("zinit"); - run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v"); - run("opt -full -undriven -mux_undef"); - run("clean -purge"); - } - - if (check_label("map_luts")) { - run("abc9 -maxlut 6 -W 200"); - run("techmap -map +/intel_alm/common/alm_map.v"); - run("opt -fast"); - run("autoname"); - run("clean"); - } - - if (check_label("check")) { - run("hierarchy -check"); - run("stat"); - run("check"); - } - - if (check_label("quartus")) { - if (quartus || help_mode) { - // Quartus ICEs if you have a wire which has `[]` in its name, - // which Yosys produces when building memories out of flops. - run("rename -hide w:*[* w:*]*"); - // VQM mode does not support 'x, so replace those with zero. - run("setundef -zero"); - // VQM mode does not support multi-bit constant assignments - // (e.g. 2'b00 is an error), so as a workaround use references - // to constant driver cells, which Quartus accepts. - run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q"); - // Rename from Yosys-internal MISTRAL_* cells to Quartus cells. - run(stringf("techmap -D %s -map +/intel_alm/common/quartus_rename.v", family_opt.c_str())); - } - } - - if (check_label("vqm")) { - if (!vout_file.empty() || help_mode) { - run(stringf("write_verilog -attr2comment -defparam -nohex -decimal %s", help_mode ? "" : vout_file.c_str())); - } - } - } -} SynthIntelALMPass; - -PRIVATE_NAMESPACE_END diff --git a/techlibs/sf2/cells_map.v b/techlibs/sf2/cells_map.v index 70f3b3b16e0..6ad7807d224 100644 --- a/techlibs/sf2/cells_map.v +++ b/techlibs/sf2/cells_map.v @@ -44,22 +44,21 @@ endmodule // module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule // module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule // -// module \$_DFFE_NN0P_ (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule -// module \$_DFFE_NN1P_ (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule -// module \$_DFFE_PN0P_ (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule -// module \$_DFFE_PN1P_ (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule +// module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule +// module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule +// module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule +// module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule // -// module \$_DFFE_NP0P_ (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule -// module \$_DFFE_NP1P_ (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule -// module \$_DFFE_PP0P_ (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule -// module \$_DFFE_PP1P_ (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule +// module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule +// module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule +// module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule +// module \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule `ifndef NO_LUT module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc index 5fd719ce52f..3d43332e26d 100644 --- a/techlibs/sf2/sf2_iobs.cc +++ b/techlibs/sf2/sf2_iobs.cc @@ -34,14 +34,14 @@ static void handle_iobufs(Module *module, bool clkbuf_mode) for (auto cell : module->cells()) { - if (clkbuf_mode && cell->type == ID(SLE)) { - for (auto bit : sigmap(cell->getPort(ID::CLK))) + if (clkbuf_mode && cell->type == "\\SLE") { + for (auto bit : sigmap(cell->getPort("\\CLK"))) clk_bits.insert(bit); } - if (cell->type.in(ID(INBUF), ID(OUTBUF), ID(TRIBUFF), ID(BIBUF), ID(CLKBUF), ID(CLKBIBUF), - ID(INBUF_DIFF), ID(OUTBUF_DIFF), ID(BIBUFF_DIFF), ID(TRIBUFF_DIFF), ID(CLKBUF_DIFF), - ID(GCLKBUF), ID(GCLKBUF_DIFF), ID(GCLKBIBUF))) { - for (auto bit : sigmap(cell->getPort(ID(PAD)))) + if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUFF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF", + "\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUFF_DIFF", "\\CLKBUF_DIFF", + "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF")) { + for (auto bit : sigmap(cell->getPort("\\PAD"))) handled_io_bits.insert(bit); } } @@ -65,14 +65,14 @@ static void handle_iobufs(Module *module, bool clkbuf_mode) IdString buf_type, buf_port; if (wire->port_output) { - buf_type = ID(OUTBUF); - buf_port = ID::D; + buf_type = "\\OUTBUF"; + buf_port = "\\D"; } else if (clkbuf_mode && clk_bits.count(canonical_bit)) { - buf_type = ID(CLKBUF); - buf_port = ID::Y; + buf_type = "\\CLKBUF"; + buf_port = "\\Y"; } else { - buf_type = ID(INBUF); - buf_port = ID::Y; + buf_type = "\\INBUF"; + buf_port = "\\Y"; } Cell *c = module->addCell(NEW_ID, buf_type); @@ -96,7 +96,7 @@ static void handle_iobufs(Module *module, bool clkbuf_mode) module->rewrite_sigspecs(rewrite_function); for (auto &it : pad_bits) - it.first->setPort(ID(PAD), it.second); + it.first->setPort("\\PAD", it.second); } static void handle_clkint(Module *module) @@ -108,13 +108,13 @@ static void handle_clkint(Module *module) for (auto cell : module->cells()) { - if (cell->type == ID(SLE)) { - for (auto bit : sigmap(cell->getPort(ID::CLK))) + if (cell->type == "\\SLE") { + for (auto bit : sigmap(cell->getPort("\\CLK"))) clk_bits.insert(bit); } - if (cell->type.in(ID(CLKBUF), ID(CLKBIBUF), ID(CLKBUF_DIFF), ID(GCLKBUF), ID(GCLKBUF_DIFF), ID(GCLKBIBUF), - ID(CLKINT), ID(CLKINT_PRESERVE), ID(GCLKINT), ID(RCLKINT), ID(RGCLKINT))) { - for (auto bit : sigmap(cell->getPort(ID::Y))) + if (cell->type.in("\\CLKBUF", "\\CLKBIBUF", "\\CLKBUF_DIFF", "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF", + "\\CLKINT", "\\CLKINT_PRESERVE", "\\GCLKINT", "\\RCLKINT", "\\RGCLKINT")) { + for (auto bit : sigmap(cell->getPort("\\Y"))) handled_clk_bits.push_back(bit); } } @@ -134,10 +134,10 @@ static void handle_clkint(Module *module) for (auto &bit : sig) { SigBit canonical_bit = sigmap(bit); if (clk_bits.count(canonical_bit)) { - Cell *c = module->addCell(NEW_ID, ID(CLKINT)); + Cell *c = module->addCell(NEW_ID, "\\CLKINT"); SigBit new_bit = module->addWire(NEW_ID); - c->setPort(ID::A, new_bit); - c->setPort(ID::Y, bit); + c->setPort("\\A", new_bit); + c->setPort("\\Y", bit); log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit)); clk_bits.erase(canonical_bit); did_something = true; @@ -155,7 +155,7 @@ static void handle_clkint(Module *module) struct Sf2IobsPass : public Pass { Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -167,7 +167,7 @@ struct Sf2IobsPass : public Pass { log(" Insert PAD->global_net clock buffers\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool clkbuf_mode = false; diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index 6b2a3f9b830..0924df7a677 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -29,7 +29,7 @@ struct SynthSf2Pass : public ScriptPass { SynthSf2Pass() : ScriptPass("synth_sf2", "synthesis for SmartFusion2 and IGLOO2 FPGAs") { } - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -67,7 +67,7 @@ struct SynthSf2Pass : public ScriptPass log(" insert direct PAD->global_net buffers\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -78,7 +78,7 @@ struct SynthSf2Pass : public ScriptPass string top_opt, edif_file, vlog_file, json_file; bool flatten, retime, iobs, clkbuf; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; edif_file = ""; @@ -90,7 +90,7 @@ struct SynthSf2Pass : public ScriptPass clkbuf = false; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -153,7 +153,7 @@ struct SynthSf2Pass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { if (check_label("begin")) { @@ -180,13 +180,13 @@ struct SynthSf2Pass : public ScriptPass run("memory_map"); run("opt -undriven -fine"); run("techmap -map +/techmap.v -map +/sf2/arith_map.v"); - run("opt -fast"); if (retime || help_mode) - run("abc -dff -D 1", "(only if -retime)"); + run("abc -dff", "(only if -retime)"); } if (check_label("map_ffs")) { + run("dffsr2dff"); run("techmap -D NO_LUT -map +/sf2/cells_map.v"); run("opt_expr -mux_undef"); run("simplemap"); diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index d4d8638317a..3ebc72fe83e 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -1,6 +1,5 @@ OBJS += techlibs/xilinx/synth_xilinx.o -OBJS += techlibs/xilinx/xilinx_dffopt.o GENFILES += techlibs/xilinx/brams_init_36.vh GENFILES += techlibs/xilinx/brams_init_32.vh @@ -27,10 +26,6 @@ techlibs/xilinx/brams_init_8.vh: techlibs/xilinx/brams_init.mk $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_sim.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_xtra.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc2v_brams.txt)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc2v_brams_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc3sa_brams.txt)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc3sda_brams.txt)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams.txt)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_xcu_brams.txt)) @@ -38,8 +33,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_brams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcup_urams.txt)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcup_urams_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut4_lutrams.txt)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut6_lutrams.txt)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams.txt)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_ff_map.v)) @@ -54,7 +48,12 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc5v_dsp_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_unmap.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_model.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_xc7.box)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_xc7.lut)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_xc7_nowide.lut)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v new file mode 100644 index 00000000000..0eac08f3f65 --- /dev/null +++ b/techlibs/xilinx/abc9_map.v @@ -0,0 +1,447 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * 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. + * + */ + +// ============================================================================ + +module RAM32X1D ( + output DPO, SPO, + (* techmap_autopurge *) input D, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE, + (* techmap_autopurge *) input A0, A1, A2, A3, A4, + (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 +); + parameter INIT = 32'h0; + parameter IS_WCLK_INVERTED = 1'b0; + wire \$DPO , \$SPO ; + RAM32X1D #( + .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) + ) _TECHMAP_REPLACE_ ( + .DPO(\$DPO ), .SPO(\$SPO ), + .D(D), .WCLK(WCLK), .WE(WE), + .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), + .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4) + ); + \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(DPO)); + \$__ABC9_LUT6 spo (.A(\$SPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(SPO)); +endmodule + +module RAM64X1D ( + output DPO, SPO, + (* techmap_autopurge *) input D, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE, + (* techmap_autopurge *) input A0, A1, A2, A3, A4, A5, + (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 +); + parameter INIT = 64'h0; + parameter IS_WCLK_INVERTED = 1'b0; + wire \$DPO , \$SPO ; + RAM64X1D #( + .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) + ) _TECHMAP_REPLACE_ ( + .DPO(\$DPO ), .SPO(\$SPO ), + .D(D), .WCLK(WCLK), .WE(WE), + .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5), + .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5) + ); + \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(DPO)); + \$__ABC9_LUT6 spo (.A(\$SPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(SPO)); +endmodule + +module RAM128X1D ( + output DPO, SPO, + (* techmap_autopurge *) input D, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE, + (* techmap_autopurge *) input [6:0] A, DPRA +); + parameter INIT = 128'h0; + parameter IS_WCLK_INVERTED = 1'b0; + wire \$DPO , \$SPO ; + RAM128X1D #( + .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) + ) _TECHMAP_REPLACE_ ( + .DPO(\$DPO ), .SPO(\$SPO ), + .D(D), .WCLK(WCLK), .WE(WE), + .A(A), + .DPRA(DPRA) + ); + \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO)); + \$__ABC9_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO)); +endmodule + +module SRL16E ( + output Q, + (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D +); + parameter [15:0] INIT = 16'h0000; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + wire \$Q ; + SRL16E #( + .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) + ) _TECHMAP_REPLACE_ ( + .Q(\$Q ), + .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D) + ); + \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q)); +endmodule + +module SRLC32E ( + output Q, + output Q31, + (* techmap_autopurge *) input [4:0] A, + (* techmap_autopurge *) input CE, CLK, D +); + parameter [31:0] INIT = 32'h00000000; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + wire \$Q ; + SRLC32E #( + .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) + ) _TECHMAP_REPLACE_ ( + .Q(\$Q ), .Q31(Q31), + .A(A), .CE(CE), .CLK(CLK), .D(D) + ); + \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q)); +endmodule + +module DSP48E1 ( + (* techmap_autopurge *) output [29:0] ACOUT, + (* techmap_autopurge *) output [17:0] BCOUT, + (* techmap_autopurge *) output reg CARRYCASCOUT, + (* techmap_autopurge *) output reg [3:0] CARRYOUT, + (* techmap_autopurge *) output reg MULTSIGNOUT, + (* techmap_autopurge *) output OVERFLOW, + (* techmap_autopurge *) output reg signed [47:0] P, + (* techmap_autopurge *) output PATTERNBDETECT, + (* techmap_autopurge *) output PATTERNDETECT, + (* techmap_autopurge *) output [47:0] PCOUT, + (* techmap_autopurge *) output UNDERFLOW, + (* techmap_autopurge *) input signed [29:0] A, + (* techmap_autopurge *) input [29:0] ACIN, + (* techmap_autopurge *) input [3:0] ALUMODE, + (* techmap_autopurge *) input signed [17:0] B, + (* techmap_autopurge *) input [17:0] BCIN, + (* techmap_autopurge *) input [47:0] C, + (* techmap_autopurge *) input CARRYCASCIN, + (* techmap_autopurge *) input CARRYIN, + (* techmap_autopurge *) input [2:0] CARRYINSEL, + (* techmap_autopurge *) input CEA1, + (* techmap_autopurge *) input CEA2, + (* techmap_autopurge *) input CEAD, + (* techmap_autopurge *) input CEALUMODE, + (* techmap_autopurge *) input CEB1, + (* techmap_autopurge *) input CEB2, + (* techmap_autopurge *) input CEC, + (* techmap_autopurge *) input CECARRYIN, + (* techmap_autopurge *) input CECTRL, + (* techmap_autopurge *) input CED, + (* techmap_autopurge *) input CEINMODE, + (* techmap_autopurge *) input CEM, + (* techmap_autopurge *) input CEP, + (* techmap_autopurge *) input CLK, + (* techmap_autopurge *) input [24:0] D, + (* techmap_autopurge *) input [4:0] INMODE, + (* techmap_autopurge *) input MULTSIGNIN, + (* techmap_autopurge *) input [6:0] OPMODE, + (* techmap_autopurge *) input [47:0] PCIN, + (* techmap_autopurge *) input RSTA, + (* techmap_autopurge *) input RSTALLCARRYIN, + (* techmap_autopurge *) input RSTALUMODE, + (* techmap_autopurge *) input RSTB, + (* techmap_autopurge *) input RSTC, + (* techmap_autopurge *) input RSTCTRL, + (* techmap_autopurge *) input RSTD, + (* techmap_autopurge *) input RSTINMODE, + (* techmap_autopurge *) input RSTM, + (* techmap_autopurge *) input RSTP +); + parameter integer ACASCREG = 1; + parameter integer ADREG = 1; + parameter integer ALUMODEREG = 1; + parameter integer AREG = 1; + parameter AUTORESET_PATDET = "NO_RESET"; + parameter A_INPUT = "DIRECT"; + parameter integer BCASCREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer INMODEREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter SEL_MASK = "MASK"; + parameter SEL_PATTERN = "PATTERN"; + parameter USE_DPORT = "FALSE"; + parameter USE_MULT = "MULTIPLY"; + parameter USE_PATTERN_DETECT = "NO_PATDET"; + parameter USE_SIMD = "ONE48"; + parameter [47:0] MASK = 48'h3FFFFFFFFFFF; + parameter [47:0] PATTERN = 48'h000000000000; + parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; + parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + parameter [4:0] IS_INMODE_INVERTED = 5'b0; + parameter [6:0] IS_OPMODE_INVERTED = 7'b0; + + parameter _TECHMAP_CELLTYPE_ = ""; + localparam techmap_guard = (_TECHMAP_CELLTYPE_ != ""); + +`define DSP48E1_INST(__CELL__) """ +__CELL__ #( + .ACASCREG(ACASCREG), + .ADREG(ADREG), + .ALUMODEREG(ALUMODEREG), + .AREG(AREG), + .AUTORESET_PATDET(AUTORESET_PATDET), + .A_INPUT(A_INPUT), + .BCASCREG(BCASCREG), + .BREG(BREG), + .B_INPUT(B_INPUT), + .CARRYINREG(CARRYINREG), + .CARRYINSELREG(CARRYINSELREG), + .CREG(CREG), + .DREG(DREG), + .INMODEREG(INMODEREG), + .MREG(MREG), + .OPMODEREG(OPMODEREG), + .PREG(PREG), + .SEL_MASK(SEL_MASK), + .SEL_PATTERN(SEL_PATTERN), + .USE_DPORT(USE_DPORT), + .USE_MULT(USE_MULT), + .USE_PATTERN_DETECT(USE_PATTERN_DETECT), + .USE_SIMD(USE_SIMD), + .MASK(MASK), + .PATTERN(PATTERN), + .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), + .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), + .IS_CLK_INVERTED(IS_CLK_INVERTED), + .IS_INMODE_INVERTED(IS_INMODE_INVERTED), + .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) + ) _TECHMAP_REPLACE_ ( + .ACOUT(ACOUT), + .BCOUT(BCOUT), + .CARRYCASCOUT(CARRYCASCOUT), + .CARRYOUT(CARRYOUT), + .MULTSIGNOUT(MULTSIGNOUT), + .OVERFLOW(OVERFLOW), + .P(oP), + .PATTERNBDETECT(PATTERNBDETECT), + .PATTERNDETECT(PATTERNDETECT), + .PCOUT(oPCOUT), + .UNDERFLOW(UNDERFLOW), + .A(iA), + .ACIN(ACIN), + .ALUMODE(ALUMODE), + .B(iB), + .BCIN(BCIN), + .C(iC), + .CARRYCASCIN(CARRYCASCIN), + .CARRYIN(CARRYIN), + .CARRYINSEL(CARRYINSEL), + .CEA1(CEA1), + .CEA2(CEA2), + .CEAD(CEAD), + .CEALUMODE(CEALUMODE), + .CEB1(CEB1), + .CEB2(CEB2), + .CEC(CEC), + .CECARRYIN(CECARRYIN), + .CECTRL(CECTRL), + .CED(CED), + .CEINMODE(CEINMODE), + .CEM(CEM), + .CEP(CEP), + .CLK(CLK), + .D(iD), + .INMODE(INMODE), + .MULTSIGNIN(MULTSIGNIN), + .OPMODE(OPMODE), + .PCIN(PCIN), + .RSTA(RSTA), + .RSTALLCARRYIN(RSTALLCARRYIN), + .RSTALUMODE(RSTALUMODE), + .RSTB(RSTB), + .RSTC(RSTC), + .RSTCTRL(RSTCTRL), + .RSTD(RSTD), + .RSTINMODE(RSTINMODE), + .RSTM(RSTM), + .RSTP(RSTP) + ); +""" + + wire [29:0] iA; + wire [17:0] iB; + wire [47:0] iC; + wire [24:0] iD; + + wire pA, pB, pC, pD, pAD, pM, pP; + wire [47:0] oP, mP; + wire [47:0] oPCOUT, mPCOUT; + + generate + if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken + if (AREG == 0 && MREG == 0 && PREG == 0) + assign iA = A, pA = 1'bx; + else + \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); + if (BREG == 0 && MREG == 0 && PREG == 0) + assign iB = B, pB = 1'bx; + else + \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); + if (CREG == 0 && PREG == 0) + assign iC = C, pC = 1'bx; + else + \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); + if (DREG == 0) + assign iD = D; + else if (techmap_guard) + $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + assign pD = 1'bx; + if (ADREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); + assign pAD = 1'bx; + if (PREG == 0) begin + if (MREG == 1) + \$__ABC9_REG rM (.Q(pM)); + else + assign pM = 1'bx; + assign pP = 1'bx; + end else begin + assign pM = 1'bx; + \$__ABC9_REG rP (.Q(pP)); + end + + if (MREG == 0 && PREG == 0) + assign mP = oP, mPCOUT = oPCOUT; + else + assign mP = 1'bx, mPCOUT = 1'bx; + \$__ABC9_DSP48E1_MULT_P_MUX muxP ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P) + ); + \$__ABC9_DSP48E1_MULT_PCOUT_MUX muxPCOUT ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT) + ); + + `DSP48E1_INST(\$__ABC9_DSP48E1_MULT ) + end + else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken + if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) + assign iA = A, pA = 1'bx; + else + \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); + if (BREG == 0 && MREG == 0 && PREG == 0) + assign iB = B, pB = 1'bx; + else + \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); + if (CREG == 0 && PREG == 0) + assign iC = C, pC = 1'bx; + else + \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); + if (DREG == 0 && ADREG == 0) + assign iD = D, pD = 1'bx; + else + \$__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD)); + if (PREG == 0) begin + if (MREG == 1) begin + assign pAD = 1'bx; + \$__ABC9_REG rM (.Q(pM)); + end else begin + if (ADREG == 1) + \$__ABC9_REG rAD (.Q(pAD)); + else + assign pAD = 1'bx; + assign pM = 1'bx; + end + assign pP = 1'bx; + end else begin + assign pAD = 1'bx, pM = 1'bx; + \$__ABC9_REG rP (.Q(pP)); + end + + if (MREG == 0 && PREG == 0) + assign mP = oP, mPCOUT = oPCOUT; + else + assign mP = 1'bx, mPCOUT = 1'bx; + \$__ABC9_DSP48E1_MULT_DPORT_P_MUX muxP ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P) + ); + \$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT) + ); + + `DSP48E1_INST(\$__ABC9_DSP48E1_MULT_DPORT ) + end + else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken + if (AREG == 0 && PREG == 0) + assign iA = A, pA = 1'bx; + else + \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); + if (BREG == 0 && PREG == 0) + assign iB = B, pB = 1'bx; + else + \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); + if (CREG == 0 && PREG == 0) + assign iC = C, pC = 1'bx; + else + \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); + if (DREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + assign pD = 1'bx; + if (ADREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); + assign pAD = 1'bx; + if (MREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); + assign pM = 1'bx; + if (PREG == 1) + \$__ABC9_REG rP (.Q(pP)); + else + assign pP = 1'bx; + + if (MREG == 0 && PREG == 0) + assign mP = oP, mPCOUT = oPCOUT; + else + assign mP = 1'bx, mPCOUT = 1'bx; + \$__ABC9_DSP48E1_P_MUX muxP ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P) + ); + \$__ABC9_DSP48E1_PCOUT_MUX muxPCOUT ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT) + ); + + `DSP48E1_INST(\$__ABC9_DSP48E1 ) + end + else + $error("Invalid DSP48E1 configuration"); + endgenerate + `undef DSP48E1_INST +endmodule diff --git a/techlibs/xilinx/abc9_model.v b/techlibs/xilinx/abc9_model.v index db44ff00b81..8c8e1556c55 100644 --- a/techlibs/xilinx/abc9_model.v +++ b/techlibs/xilinx/abc9_model.v @@ -24,16 +24,167 @@ // Necessary to make these an atomic unit so that // ABC cannot optimise just one of the MUXF7 away // and expect to save on its delay -(* abc9_box, lib_whitebox *) +(* abc9_box_id = 3, lib_whitebox *) module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); assign O = S1 ? (S0 ? I3 : I2) : (S0 ? I1 : I0); - specify - (I0 => O) = 294; - (I1 => O) = 297; - (I2 => O) = 311; - (I3 => O) = 317; - (S0 => O) = 390; - (S1 => O) = 273; - endspecify endmodule + +// Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} +// Necessary since RAMD* and SRL* have both combinatorial (i.e. +// same-cycle read operation) and sequential (write operation +// is only committed on the next clock edge). +// To model the combinatorial path, such cells have to be split +// into comb and seq parts, with this box modelling only the former. +(* abc9_box_id=2000 *) +module \$__ABC9_LUT6 (input A, input [5:0] S, output Y); +endmodule +// Box to emulate comb/seq behaviour of RAMD128 +(* abc9_box_id=2001 *) +module \$__ABC9_LUT7 (input A, input [6:0] S, output Y); +endmodule + + +// Modules used to model the comb/seq behaviour of DSP48E1 +// With abc9_map.v responsible for splicing the below modules +// between the combinatorial DSP48E1 box (e.g. disconnecting +// A when AREG, MREG or PREG is enabled and splicing in the +// "$__ABC9_DSP48E1_REG" blackbox as "REG" in the diagram below) +// this acts to first disables the combinatorial path (as there +// is no connectivity through REG), and secondly, since this is +// blackbox a new PI will be introduced with an arrival time of +// zero. +// Note: Since these "$__ABC9_DSP48E1_REG" modules are of a +// sequential nature, they are not passed as a box to ABC and +// (desirably) represented as PO/PIs. +// +// At the DSP output, we place a blackbox mux ("M" in the diagram +// below) to capture the fact that the critical-path could come +// from any one of its inputs. +// In contrast to "REG", the "$__ABC9_DSP48E1_*_MUX" modules are +// combinatorial blackboxes that do get passed to ABC. +// The propagation delay through this box (specified in the box +// file) captures the arrival time of the register (i.e. +// propagation from AREG to P after clock edge), or zero delay +// for the combinatorial path from the DSP. +// +// Doing so should means that ABC is able to analyse the +// worst-case delay through to P, regardless of if it was +// through any combinatorial paths (e.g. B, below) or an +// internal register (A2REG). +// However, the true value of being as complete as this is +// questionable since if AREG=1 and BREG=0 (as below) +// then the worse-case path would very likely be through B +// and very unlikely to be through AREG.Q...? +// +// In graphical form: +// +// +-----+ +// +------>> REG >>----+ +// | +-----+ | +// | | +// | +---------+ | __ +// A >>-+X X-| | +--| \ +// | DSP48E1 |P | M |--->> P +// | AREG=1 |-------|__/ +// B >>------| | +// +---------+ +// +`define ABC9_DSP48E1_MUX(__NAME__) """ +module __NAME__ (input Aq, ADq, Bq, Cq, Dq, input [47:0] I, input Mq, input [47:0] P, input Pq, output [47:0] O); +endmodule +""" +(* abc9_box_id=2100 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_P_MUX ) +(* abc9_box_id=2101 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_PCOUT_MUX ) +(* abc9_box_id=2102 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_DPORT_P_MUX ) +(* abc9_box_id=2103 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX ) +(* abc9_box_id=2104 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_P_MUX ) +(* abc9_box_id=2105 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_PCOUT_MUX ) + +`define ABC9_DSP48E1(__NAME__) """ +module __NAME__ ( + output [29:0] ACOUT, + output [17:0] BCOUT, + output reg CARRYCASCOUT, + output reg [3:0] CARRYOUT, + output reg MULTSIGNOUT, + output OVERFLOW, + output reg signed [47:0] P, + output PATTERNBDETECT, + output PATTERNDETECT, + output [47:0] PCOUT, + output UNDERFLOW, + input signed [29:0] A, + input [29:0] ACIN, + input [3:0] ALUMODE, + input signed [17:0] B, + input [17:0] BCIN, + input [47:0] C, + input CARRYCASCIN, + input CARRYIN, + input [2:0] CARRYINSEL, + input CEA1, + input CEA2, + input CEAD, + input CEALUMODE, + input CEB1, + input CEB2, + input CEC, + input CECARRYIN, + input CECTRL, + input CED, + input CEINMODE, + input CEM, + input CEP, + input CLK, + input [24:0] D, + input [4:0] INMODE, + input MULTSIGNIN, + input [6:0] OPMODE, + input [47:0] PCIN, + input RSTA, + input RSTALLCARRYIN, + input RSTALUMODE, + input RSTB, + input RSTC, + input RSTCTRL, + input RSTD, + input RSTINMODE, + input RSTM, + input RSTP +); + parameter integer ACASCREG = 1; + parameter integer ADREG = 1; + parameter integer ALUMODEREG = 1; + parameter integer AREG = 1; + parameter AUTORESET_PATDET = "NO_RESET"; + parameter A_INPUT = "DIRECT"; + parameter integer BCASCREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer INMODEREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter SEL_MASK = "MASK"; + parameter SEL_PATTERN = "PATTERN"; + parameter USE_DPORT = "FALSE"; + parameter USE_MULT = "MULTIPLY"; + parameter USE_PATTERN_DETECT = "NO_PATDET"; + parameter USE_SIMD = "ONE48"; + parameter [47:0] MASK = 48'h3FFFFFFFFFFF; + parameter [47:0] PATTERN = 48'h000000000000; + parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; + parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + parameter [4:0] IS_INMODE_INVERTED = 5'b0; + parameter [6:0] IS_OPMODE_INVERTED = 7'b0; +endmodule +""" +(* abc9_box_id=3000 *) `ABC9_DSP48E1(\$__ABC9_DSP48E1_MULT ) +(* abc9_box_id=3001 *) `ABC9_DSP48E1(\$__ABC9_DSP48E1_MULT_DPORT ) +(* abc9_box_id=3002 *) `ABC9_DSP48E1(\$__ABC9_DSP48E1 ) diff --git a/techlibs/xilinx/abc9_unmap.v b/techlibs/xilinx/abc9_unmap.v new file mode 100644 index 00000000000..ad6469702ef --- /dev/null +++ b/techlibs/xilinx/abc9_unmap.v @@ -0,0 +1,211 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * 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. + * + */ + +// ============================================================================ + +module \$__ABC9_LUT6 (input A, input [5:0] S, output Y); + assign Y = A; +endmodule +module \$__ABC9_LUT7 (input A, input [6:0] S, output Y); + assign Y = A; +endmodule + +module \$__ABC9_REG (input [WIDTH-1:0] I, output [WIDTH-1:0] O, output Q); + parameter WIDTH = 1; + assign O = I; +endmodule +(* techmap_celltype = "$__ABC9_DSP48E1_MULT_P_MUX $__ABC9_DSP48E1_MULT_PCOUT_MUX $__ABC9_DSP48E1_MULT_DPORT_P_MUX $__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX $__ABC9_DSP48E1_P_MUX $__ABC9_DSP48E1_PCOUT_MUX" *) +module \$__ABC9_DSP48E1_MUX ( + input Aq, Bq, Cq, Dq, ADq, + input [47:0] I, + input Mq, + input [47:0] P, + input Pq, + output [47:0] O +); + assign O = I; +endmodule + +(* techmap_celltype = "$__ABC9_DSP48E1_MULT $__ABC9_DSP48E1_MULT_DPORT $__ABC9_DSP48E1" *) +module \$__ABC9_DSP48E1 ( + (* techmap_autopurge *) output [29:0] ACOUT, + (* techmap_autopurge *) output [17:0] BCOUT, + (* techmap_autopurge *) output reg CARRYCASCOUT, + (* techmap_autopurge *) output reg [3:0] CARRYOUT, + (* techmap_autopurge *) output reg MULTSIGNOUT, + (* techmap_autopurge *) output OVERFLOW, + (* techmap_autopurge *) output reg signed [47:0] P, + (* techmap_autopurge *) output PATTERNBDETECT, + (* techmap_autopurge *) output PATTERNDETECT, + (* techmap_autopurge *) output [47:0] PCOUT, + (* techmap_autopurge *) output UNDERFLOW, + (* techmap_autopurge *) input signed [29:0] A, + (* techmap_autopurge *) input [29:0] ACIN, + (* techmap_autopurge *) input [3:0] ALUMODE, + (* techmap_autopurge *) input signed [17:0] B, + (* techmap_autopurge *) input [17:0] BCIN, + (* techmap_autopurge *) input [47:0] C, + (* techmap_autopurge *) input CARRYCASCIN, + (* techmap_autopurge *) input CARRYIN, + (* techmap_autopurge *) input [2:0] CARRYINSEL, + (* techmap_autopurge *) input CEA1, + (* techmap_autopurge *) input CEA2, + (* techmap_autopurge *) input CEAD, + (* techmap_autopurge *) input CEALUMODE, + (* techmap_autopurge *) input CEB1, + (* techmap_autopurge *) input CEB2, + (* techmap_autopurge *) input CEC, + (* techmap_autopurge *) input CECARRYIN, + (* techmap_autopurge *) input CECTRL, + (* techmap_autopurge *) input CED, + (* techmap_autopurge *) input CEINMODE, + (* techmap_autopurge *) input CEM, + (* techmap_autopurge *) input CEP, + (* techmap_autopurge *) input CLK, + (* techmap_autopurge *) input [24:0] D, + (* techmap_autopurge *) input [4:0] INMODE, + (* techmap_autopurge *) input MULTSIGNIN, + (* techmap_autopurge *) input [6:0] OPMODE, + (* techmap_autopurge *) input [47:0] PCIN, + (* techmap_autopurge *) input RSTA, + (* techmap_autopurge *) input RSTALLCARRYIN, + (* techmap_autopurge *) input RSTALUMODE, + (* techmap_autopurge *) input RSTB, + (* techmap_autopurge *) input RSTC, + (* techmap_autopurge *) input RSTCTRL, + (* techmap_autopurge *) input RSTD, + (* techmap_autopurge *) input RSTINMODE, + (* techmap_autopurge *) input RSTM, + (* techmap_autopurge *) input RSTP +); + parameter integer ACASCREG = 1; + parameter integer ADREG = 1; + parameter integer ALUMODEREG = 1; + parameter integer AREG = 1; + parameter AUTORESET_PATDET = "NO_RESET"; + parameter A_INPUT = "DIRECT"; + parameter integer BCASCREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer INMODEREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter SEL_MASK = "MASK"; + parameter SEL_PATTERN = "PATTERN"; + parameter USE_DPORT = "FALSE"; + parameter USE_MULT = "MULTIPLY"; + parameter USE_PATTERN_DETECT = "NO_PATDET"; + parameter USE_SIMD = "ONE48"; + parameter [47:0] MASK = 48'h3FFFFFFFFFFF; + parameter [47:0] PATTERN = 48'h000000000000; + parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; + parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + parameter [4:0] IS_INMODE_INVERTED = 5'b0; + parameter [6:0] IS_OPMODE_INVERTED = 7'b0; + + DSP48E1 #( + .ACASCREG(ACASCREG), + .ADREG(ADREG), + .ALUMODEREG(ALUMODEREG), + .AREG(AREG), + .AUTORESET_PATDET(AUTORESET_PATDET), + .A_INPUT(A_INPUT), + .BCASCREG(BCASCREG), + .BREG(BREG), + .B_INPUT(B_INPUT), + .CARRYINREG(CARRYINREG), + .CARRYINSELREG(CARRYINSELREG), + .CREG(CREG), + .DREG(DREG), + .INMODEREG(INMODEREG), + .MREG(MREG), + .OPMODEREG(OPMODEREG), + .PREG(PREG), + .SEL_MASK(SEL_MASK), + .SEL_PATTERN(SEL_PATTERN), + .USE_DPORT(USE_DPORT), + .USE_MULT(USE_MULT), + .USE_PATTERN_DETECT(USE_PATTERN_DETECT), + .USE_SIMD(USE_SIMD), + .MASK(MASK), + .PATTERN(PATTERN), + .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), + .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), + .IS_CLK_INVERTED(IS_CLK_INVERTED), + .IS_INMODE_INVERTED(IS_INMODE_INVERTED), + .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) + ) _TECHMAP_REPLACE_ ( + .ACOUT(ACOUT), + .BCOUT(BCOUT), + .CARRYCASCOUT(CARRYCASCOUT), + .CARRYOUT(CARRYOUT), + .MULTSIGNOUT(MULTSIGNOUT), + .OVERFLOW(OVERFLOW), + .P(P), + .PATTERNBDETECT(PATTERNBDETECT), + .PATTERNDETECT(PATTERNDETECT), + .PCOUT(PCOUT), + .UNDERFLOW(UNDERFLOW), + .A(A), + .ACIN(ACIN), + .ALUMODE(ALUMODE), + .B(B), + .BCIN(BCIN), + .C(C), + .CARRYCASCIN(CARRYCASCIN), + .CARRYIN(CARRYIN), + .CARRYINSEL(CARRYINSEL), + .CEA1(CEA1), + .CEA2(CEA2), + .CEAD(CEAD), + .CEALUMODE(CEALUMODE), + .CEB1(CEB1), + .CEB2(CEB2), + .CEC(CEC), + .CECARRYIN(CECARRYIN), + .CECTRL(CECTRL), + .CED(CED), + .CEINMODE(CEINMODE), + .CEM(CEM), + .CEP(CEP), + .CLK(CLK), + .D(D), + .INMODE(INMODE), + .MULTSIGNIN(MULTSIGNIN), + .OPMODE(OPMODE), + .PCIN(PCIN), + .RSTA(RSTA), + .RSTALLCARRYIN(RSTALLCARRYIN), + .RSTALUMODE(RSTALUMODE), + .RSTB(RSTB), + .RSTC(RSTC), + .RSTCTRL(RSTCTRL), + .RSTD(RSTD), + .RSTINMODE(RSTINMODE), + .RSTM(RSTM), + .RSTP(RSTP) + ); +endmodule diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box new file mode 100644 index 00000000000..3a19b372070 --- /dev/null +++ b/techlibs/xilinx/abc9_xc7.box @@ -0,0 +1,1188 @@ +# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf +# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf + +# NB: Inputs/Outputs must be ordered alphabetically +# (with exceptions for carry in/out) + +# Average across F7[AB]MUX +# Inputs: I0 I1 S0 +# Outputs: O +MUXF7 1 1 3 1 +204 208 286 + +# Inputs: I0 I1 S0 +# Outputs: O +MUXF8 2 1 3 1 +104 94 273 + +# Box containing MUXF7.[AB] + MUXF8, +# Necessary to make these an atomic unit so that +# ABC cannot optimise just one of the MUXF7 away +# and expect to save on its delay +# Inputs: I0 I1 I2 I3 S0 S1 +# Outputs: O +$__MUXF78 3 1 6 1 +294 297 311 317 390 273 + +# CARRY4 + CARRY4_[ABCD]X +# Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI +# Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3 +# (NB: carry chain input/output must be last +# input/output and the entire bus has been +# moved there overriding the otherwise +# alphabetical ordering) +CARRY4 4 1 10 8 +482 - - - - 223 - - - 222 +598 407 - - - 400 205 - - 334 +584 556 537 - - 523 558 226 - 239 +642 615 596 438 - 582 618 330 227 313 +536 379 - - - 340 - - - 271 +494 465 445 - - 433 469 - - 157 +592 540 520 356 - 512 548 292 - 228 +580 526 507 398 385 508 528 378 380 114 + +# CARRY4_COUT + CARRY4_[ABCD]X +# Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI +# Outputs: O0 O1 O2 O3 COUT +# (NB: carry chain input/output must be last +# input/output and the entire bus has been +# moved there overriding the otherwise +# alphabetical ordering) +CARRY4_COUT 8 1 10 5 +482 - - - - 223 - - - 222 +598 407 - - - 400 205 - - 334 +584 556 537 - - 523 558 226 - 239 +642 615 596 438 - 582 618 330 227 313 +580 526 507 398 385 508 528 378 380 114 + +# CARRY_COUT_PLUG +# Inputs: CIN +# Outputs: COUT +# +# This blackbox is simply in place to prevent ABC from optimizating across it, +# as it uses dedicated routing and cannot be manipulated in general. +CARRY_COUT_PLUG 9 0 1 1 +0 + +# SLICEM/A6LUT +# Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} +# Necessary since RAMD* and SRL* have both combinatorial (i.e. +# same-cycle read operation) and sequential (write operation +# is only committed on the next clock edge). +# To model the combinatorial path, such cells have to be split +# into comb and seq parts, with this box modelling only the former. +# Inputs: A S0 S1 S2 S3 S4 S5 +# Outputs: Y +$__ABC9_LUT6 2000 0 7 1 +0 642 631 472 407 238 127 + +# SLICEM/A6LUT + F7BMUX +# Box to emulate comb/seq behaviour of RAMD128 +# Inputs: A S0 S1 S2 S3 S4 S5 S6 +# Outputs: DPO SPO +$__ABC9_LUT7 2001 0 8 1 +0 1047 1036 877 812 643 532 478 + +# Boxes used to represent the comb/seq behaviour of DSP48E1 +# With abc9_map.v responsible for disconnecting inputs to +# the combinatorial DSP48E1 model by a register (e.g. +# disconnecting A when AREG, MREG or PREG is enabled) +# this mux captures the existence of a replacement path +# between AREG/BREG/CREG/etc. and P/PCOUT. +# Since the Aq/ADq/Bq/etc. inputs are assumed to arrive at +# the mux at zero time, the combinatorial delay through +# these muxes thus represents the clock-to-q delay at +# P/PCOUT. +$__ABC9_DSP48E1_MULT_P_MUX 2100 0 103 48 +# A AD B C D I M P Pq +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC9_DSP48E1_MULT_PCOUT_MUX 2101 0 103 48 +# A AD B C D I M P Pq +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC9_DSP48E1_MULT_DPORT_P_MUX 2102 0 103 48 +# A AD B C D I M P Pq +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 103 48 +# A AD B C D I M P Pq +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC9_DSP48E1_P_MUX 2104 0 103 48 +# A AD B C D I M P Pq +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC9_DSP48E1_PCOUT_MUX 2105 0 103 48 +# A AD B C D I M P Pq +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 + +$__ABC9_DSP48E1_MULT 3000 0 263 154 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +$__ABC9_DSP48E1_MULT_DPORT 3001 0 263 154 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +$__ABC9_DSP48E1 3002 0 263 154 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/techlibs/xilinx/abc9_xc7.lut b/techlibs/xilinx/abc9_xc7.lut new file mode 100644 index 00000000000..bcbdec12778 --- /dev/null +++ b/techlibs/xilinx/abc9_xc7.lut @@ -0,0 +1,15 @@ +# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/timings/CLBLL_L.sdf +# and https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/tile_type_CLBLL_L.json + +# K area delay +1 1 127 +2 2 127 238 +3 3 127 238 407 +4 3 127 238 407 472 +5 3 127 238 407 472 631 +6 5 127 238 407 472 631 642 + # (F7[AB]MUX.S + [AC]OUTMUX) / 2 +7 10 464 513 624 793 858 1017 1028 + # F8MUX.S+BOUTMUX + # F8MUX.I0+F7MUX.S+BOUTMUX +8 20 468 585 634 745 914 979 1138 1149 diff --git a/techlibs/xilinx/abc9_xc7_nowide.lut b/techlibs/xilinx/abc9_xc7_nowide.lut new file mode 100644 index 00000000000..fab48c87930 --- /dev/null +++ b/techlibs/xilinx/abc9_xc7_nowide.lut @@ -0,0 +1,10 @@ +# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/timings/CLBLL_L.sdf +# and https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/tile_type_CLBLL_L.json + +# K area delay +1 1 127 +2 2 127 238 +3 3 127 238 407 +4 3 127 238 407 472 +5 3 127 238 407 472 631 +6 5 127 238 407 472 631 642 diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v index 83c238569b2..9b999bb41e4 100644 --- a/techlibs/xilinx/arith_map.v +++ b/techlibs/xilinx/arith_map.v @@ -24,28 +24,83 @@ module _80_xilinx_lcu (P, G, CI, CO); parameter WIDTH = 2; - (* force_downto *) input [WIDTH-1:0] P, G; input CI; - (* force_downto *) output [WIDTH-1:0] CO; wire _TECHMAP_FAIL_ = WIDTH <= 2; genvar i; -`ifdef _EXPLICIT_CARRY - localparam EXPLICIT_CARRY = 1'b1; -`else - localparam EXPLICIT_CARRY = 1'b0; -`endif +`ifdef _CLB_CARRY + + localparam CARRY4_COUNT = (WIDTH + 3) / 4; + localparam MAX_WIDTH = CARRY4_COUNT * 4; + localparam PAD_WIDTH = MAX_WIDTH - WIDTH; + + wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, P & ~G}; + wire [MAX_WIDTH-1:0] C = CO; + + generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice + + // Partially occupied CARRY4 + if ((i+1)*4 > WIDTH) begin + + // First one + if (i == 0) begin + CARRY4 carry4_1st_part + ( + .CYINIT(CI), + .CI (1'd0), + .DI (G [(Y_WIDTH - 1):i*4]), + .S (S [(Y_WIDTH - 1):i*4]), + .CO (CO[(Y_WIDTH - 1):i*4]), + ); + // Another one + end else begin + CARRY4 carry4_part + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (G [(Y_WIDTH - 1):i*4]), + .S (S [(Y_WIDTH - 1):i*4]), + .CO (CO[(Y_WIDTH - 1):i*4]), + ); + end + + // Fully occupied CARRY4 + end else begin + + // First one + if (i == 0) begin + CARRY4 carry4_1st_full + ( + .CYINIT(CI), + .CI (1'd0), + .DI (G [((i+1)*4 - 1):i*4]), + .S (S [((i+1)*4 - 1):i*4]), + .CO (CO[((i+1)*4 - 1):i*4]), + ); + // Another one + end else begin + CARRY4 carry4_full + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (G [((i+1)*4 - 1):i*4]), + .S (S [((i+1)*4 - 1):i*4]), + .CO (CO[((i+1)*4 - 1):i*4]), + ); + end + + end + + end endgenerate -generate if (`LUT_SIZE == 4) begin +`elsif _EXPLICIT_CARRY - (* force_downto *) wire [WIDTH-1:0] C = {CO, CI}; - (* force_downto *) wire [WIDTH-1:0] S = P & ~G; generate for (i = 0; i < WIDTH; i = i + 1) begin:slice @@ -57,89 +112,20 @@ generate if (`LUT_SIZE == 4) begin ); end endgenerate -end else if (EXPLICIT_CARRY) begin - - localparam CARRY4_COUNT = (WIDTH + 3) / 4; - localparam MAX_WIDTH = CARRY4_COUNT * 4; - localparam PAD_WIDTH = MAX_WIDTH - WIDTH; - - (* force_downto *) - wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, P & ~G}; - (* force_downto *) - wire [MAX_WIDTH-1:0] GG = {{PAD_WIDTH{1'b0}}, G}; - (* force_downto *) - wire [MAX_WIDTH-1:0] C; - (* force_downto *) - wire [CARRY4_COUNT-1:0] CO_CHAIN; - (* force_downto *) - wire [CARRY4_COUNT-1:0] CO_CHAIN_PLUG; - assign CO = C; +`else - generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice - if (i == 0) begin - CARRY4_CO_COUT carry4 - ( - .CYINIT(CI), - .CI (1'd0), - .DI (GG[i*4 +: 4]), - .S (S [i*4 +: 4]), - .CO (C [i*4 +: 4]), - .COUT (CO_CHAIN_PLUG [i]), - ); - end else begin - CARRY4_CO_COUT carry4 - ( - .CYINIT(1'd0), - .CI (CO_CHAIN[i-1]), - .DI (GG[i*4 +: 4]), - .S (S [i*4 +: 4]), - .CO (C [i*4 +: 4]), - .COUT (CO_CHAIN_PLUG [i]), - ); - end + wire [WIDTH-1:0] C = {CO, CI}; + wire [WIDTH-1:0] S = P & ~G; - CARRY_COUT_PLUG plug( - .CIN(CO_CHAIN_PLUG[i]), - .COUT(CO_CHAIN[i]) + generate for (i = 0; i < WIDTH; i = i + 1) begin:slice + MUXCY muxcy ( + .CI(C[i]), + .DI(G[i]), + .S(S[i]), + .O(CO[i]) ); end endgenerate - -end else begin - - localparam CARRY4_COUNT = (WIDTH + 3) / 4; - localparam MAX_WIDTH = CARRY4_COUNT * 4; - localparam PAD_WIDTH = MAX_WIDTH - WIDTH; - - (* force_downto *) - wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, P & ~G}; - (* force_downto *) - wire [MAX_WIDTH-1:0] GG = {{PAD_WIDTH{1'b0}}, G}; - (* force_downto *) - wire [MAX_WIDTH-1:0] C; - assign CO = C; - - generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice - if (i == 0) begin - CARRY4 carry4 - ( - .CYINIT(CI), - .CI (1'd0), - .DI (GG[i*4 +: 4]), - .S (S [i*4 +: 4]), - .CO (C [i*4 +: 4]), - ); - end else begin - CARRY4 carry4 - ( - .CYINIT(1'd0), - .CI (C [i*4 - 1]), - .DI (GG[i*4 +: 4]), - .S (S [i*4 +: 4]), - .CO (C [i*4 +: 4]), - ); - end - end endgenerate -end endgenerate +`endif endmodule @@ -157,60 +143,97 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); parameter _TECHMAP_CONSTVAL_CI_ = 0; parameter _TECHMAP_CONSTMSK_CI_ = 0; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] X, Y; input CI, BI; - (* force_downto *) output [Y_WIDTH-1:0] CO; wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; - (* force_downto *) wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - (* force_downto *) wire [Y_WIDTH-1:0] AA = A_buf; - (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; genvar i; -`ifdef _EXPLICIT_CARRY - localparam EXPLICIT_CARRY = 1'b1; -`else - localparam EXPLICIT_CARRY = 1'b0; -`endif +`ifdef _CLB_CARRY -generate if (`LUT_SIZE == 4) begin + localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4; + localparam MAX_WIDTH = CARRY4_COUNT * 4; + localparam PAD_WIDTH = MAX_WIDTH - Y_WIDTH; - (* force_downto *) - wire [Y_WIDTH-1:0] C = {CO, CI}; - (* force_downto *) - wire [Y_WIDTH-1:0] S = {AA ^ BB}; + wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, AA ^ BB}; + wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB}; + + wire [MAX_WIDTH-1:0] C = CO; genvar i; - generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice - MUXCY muxcy ( - .CI(C[i]), - .DI(AA[i]), - .S(S[i]), - .O(CO[i]) - ); - XORCY xorcy ( - .CI(C[i]), - .LI(S[i]), - .O(Y[i]) - ); + generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice + + // Partially occupied CARRY4 + if ((i+1)*4 > Y_WIDTH) begin + + // First one + if (i == 0) begin + CARRY4 carry4_1st_part + ( + .CYINIT(CI), + .CI (1'd0), + .DI (DI[(Y_WIDTH - 1):i*4]), + .S (S [(Y_WIDTH - 1):i*4]), + .O (Y [(Y_WIDTH - 1):i*4]), + .CO (CO[(Y_WIDTH - 1):i*4]) + ); + // Another one + end else begin + CARRY4 carry4_part + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (DI[(Y_WIDTH - 1):i*4]), + .S (S [(Y_WIDTH - 1):i*4]), + .O (Y [(Y_WIDTH - 1):i*4]), + .CO (CO[(Y_WIDTH - 1):i*4]) + ); + end + + // Fully occupied CARRY4 + end else begin + + // First one + if (i == 0) begin + CARRY4 carry4_1st_full + ( + .CYINIT(CI), + .CI (1'd0), + .DI (DI[((i+1)*4 - 1):i*4]), + .S (S [((i+1)*4 - 1):i*4]), + .O (Y [((i+1)*4 - 1):i*4]), + .CO (CO[((i+1)*4 - 1):i*4]) + ); + // Another one + end else begin + CARRY4 carry4_full + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (DI[((i+1)*4 - 1):i*4]), + .S (S [((i+1)*4 - 1):i*4]), + .O (Y [((i+1)*4 - 1):i*4]), + .CO (CO[((i+1)*4 - 1):i*4]) + ); + end + + end + end endgenerate -end else if (EXPLICIT_CARRY) begin +`elsif _EXPLICIT_CARRY // Turns out CO and O both use [ABCD]MUX, so provide a non-congested path // to carry chain by using O outputs. @@ -224,11 +247,8 @@ end else if (EXPLICIT_CARRY) begin localparam MAX_WIDTH = CARRY4_COUNT * 4; localparam PAD_WIDTH = MAX_WIDTH - Y_WIDTH; - (* force_downto *) wire [Y_PAD_WIDTH-1:0] O; - (* force_downto *) wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, AA ^ BB}; - (* force_downto *) wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB}; // Carry chain between CARRY4 blocks. @@ -240,9 +260,7 @@ end else if (EXPLICIT_CARRY) begin // So we maintain two wire sets, CO_CHAIN is the carry that is for VPR, // e.g. off fabric dedicated chain. CO is the carry outputs that are // available to the fabric. - (* force_downto *) wire [CARRY4_COUNT-1:0] CO_CHAIN; - (* force_downto *) wire [CARRY4_COUNT-1:0] CO_CHAIN_PLUG; assign Y[Y_WIDTH-1:0] = O[Y_WIDTH-1:0]; @@ -320,49 +338,28 @@ end else if (EXPLICIT_CARRY) begin end endgenerate -end else begin +`else - localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4; - localparam MAX_WIDTH = CARRY4_COUNT * 4; - localparam PAD_WIDTH = MAX_WIDTH - Y_WIDTH; + wire [Y_WIDTH-1:0] S = AA ^ BB; + wire [Y_WIDTH-1:0] DI = AA & BB; - (* force_downto *) - wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, AA ^ BB}; - (* force_downto *) - wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA}; - - (* force_downto *) - wire [MAX_WIDTH-1:0] O; - (* force_downto *) - wire [MAX_WIDTH-1:0] C; - assign Y = O, CO = C; + wire [Y_WIDTH-1:0] C = {CO, CI}; - genvar i; - generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice - if (i == 0) begin - CARRY4 carry4 - ( - .CYINIT(CI), - .CI (1'd0), - .DI (DI[i*4 +: 4]), - .S (S [i*4 +: 4]), - .O (O [i*4 +: 4]), - .CO (C [i*4 +: 4]) - ); - end else begin - CARRY4 carry4 - ( - .CYINIT(1'd0), - .CI (C [i*4 - 1]), - .DI (DI[i*4 +: 4]), - .S (S [i*4 +: 4]), - .O (O [i*4 +: 4]), - .CO (C [i*4 +: 4]) - ); - end + generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice + MUXCY muxcy ( + .CI(C[i]), + .DI(DI[i]), + .S(S[i]), + .O(CO[i]) + ); + XORCY xorcy ( + .CI(C[i]), + .LI(S[i]), + .O(Y[i]) + ); end endgenerate -end endgenerate +`endif assign X = S; endmodule diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index a6cd129213a..3a71ed32ae3 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -28,33 +28,6 @@ module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1_ _TECHMAP_REPL (* techmap_celltype = "$_DFF_PN1_" *) module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -(* techmap_celltype = "$_DFFE_NN0P_" *) -module _90_dffe_nn0_to_np0 (input D, C, R, E, output Q); \$_DFFE_NP0P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule -(* techmap_celltype = "$_DFFE_PN0P_" *) -module _90_dffe_pn0_to_pp0 (input D, C, R, E, output Q); \$_DFFE_PP0P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule -(* techmap_celltype = "$_DFFE_NN1P_" *) -module _90_dffe_nn1_to_np1 (input D, C, R, E, output Q); \$_DFFE_NP1P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule -(* techmap_celltype = "$_DFFE_PN1P_" *) -module _90_dffe_pn1_to_pp1 (input D, C, R, E, output Q); \$_DFFE_PP1P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule - -(* techmap_celltype = "$_SDFF_NN0_" *) -module _90_dffs_nn0_to_np0 (input D, C, R, output Q); \$_SDFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -(* techmap_celltype = "$_SDFF_PN0_" *) -module _90_dffs_pn0_to_pp0 (input D, C, R, output Q); \$_SDFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -(* techmap_celltype = "$_SDFF_NN1_" *) -module _90_dffs_nn1_to_np1 (input D, C, R, output Q); \$_SDFF_NP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -(* techmap_celltype = "$_SDFF_PN1_" *) -module _90_dffs_pn1_to_pp1 (input D, C, R, output Q); \$_SDFF_PP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule - -(* techmap_celltype = "$_SDFFE_NN0P_" *) -module _90_dffse_nn0_to_np0 (input D, C, R, E, output Q); \$_SDFFE_NP0P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule -(* techmap_celltype = "$_SDFFE_PN0P_" *) -module _90_dffse_pn0_to_pp0 (input D, C, R, E, output Q); \$_SDFFE_PP0P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule -(* techmap_celltype = "$_SDFFE_NN1P_" *) -module _90_dffse_nn1_to_np1 (input D, C, R, E, output Q); \$_SDFFE_NP1P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule -(* techmap_celltype = "$_SDFFE_PN1P_" *) -module _90_dffse_pn1_to_pp1 (input D, C, R, E, output Q); \$_SDFFE_PP1P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule - module \$__SHREG_ (input C, input D, input E, output Q); parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; @@ -181,11 +154,8 @@ module \$__XILINX_SHIFTX (A, B, Y); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; @@ -321,11 +291,8 @@ module _90__XILINX_SHIFTX (A, B, Y); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index c2c2bf91dbf..981f35326ba 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -36,9 +36,6 @@ module IBUF( parameter IOSTANDARD = "default"; parameter IBUF_LOW_PWR = 0; assign O = I; - specify - (I => O) = 0; - endspecify endmodule module IBUFG( @@ -60,9 +57,6 @@ module OBUF( parameter DRIVE = 12; parameter SLEW = "SLOW"; assign O = I; - specify - (I => O) = 0; - endspecify endmodule module IOBUF ( @@ -78,10 +72,6 @@ module IOBUF ( parameter SLEW = "SLOW"; assign IO = T ? 1'bz : I; assign O = IO; - specify - (I => IO) = 0; - (IO => O) = 0; - endspecify endmodule module OBUFT ( @@ -95,20 +85,14 @@ module OBUFT ( parameter IOSTANDARD = "DEFAULT"; parameter SLEW = "SLOW"; assign O = T ? 1'bz : I; - specify - (I => O) = 0; - endspecify endmodule module BUFG( (* clkbuf_driver *) output O, input I); + assign O = I; - specify - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/CLK_BUFG_TOP_R.sdf#L11 - (I => O) = 96; - endspecify endmodule module BUFGCTRL( @@ -176,60 +160,34 @@ module INV( input I ); assign O = !I; - specify - (I => O) = 127; - endspecify endmodule -(* abc9_lut=1 *) module LUT1(output O, input I0); parameter [1:0] INIT = 0; assign O = I0 ? INIT[1] : INIT[0]; - specify - (I0 => O) = 127; - endspecify endmodule -(* abc9_lut=2 *) module LUT2(output O, input I0, I1); parameter [3:0] INIT = 0; wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0]; assign O = I0 ? s1[1] : s1[0]; - specify - (I0 => O) = 238; - (I1 => O) = 127; - endspecify endmodule -(* abc9_lut=3 *) module LUT3(output O, input I0, I1, I2); parameter [7:0] INIT = 0; wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0]; wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; assign O = I0 ? s1[1] : s1[0]; - specify - (I0 => O) = 407; - (I1 => O) = 238; - (I2 => O) = 127; - endspecify endmodule -(* abc9_lut=3 *) module LUT4(output O, input I0, I1, I2, I3); parameter [15:0] INIT = 0; wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0]; wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; assign O = I0 ? s1[1] : s1[0]; - specify - (I0 => O) = 472; - (I1 => O) = 407; - (I2 => O) = 238; - (I3 => O) = 127; - endspecify endmodule -(* abc9_lut=3 *) module LUT5(output O, input I0, I1, I2, I3, I4); parameter [31:0] INIT = 0; wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0]; @@ -237,19 +195,8 @@ module LUT5(output O, input I0, I1, I2, I3, I4); wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; assign O = I0 ? s1[1] : s1[0]; - specify - (I0 => O) = 631; - (I1 => O) = 472; - (I2 => O) = 407; - (I3 => O) = 238; - (I4 => O) = 127; - endspecify endmodule -// This is a placeholder for ABC9 to extract the area/delay -// cost of 3-input LUTs and is not intended to be instantiated - -(* abc9_lut=5 *) module LUT6(output O, input I0, I1, I2, I3, I4, I5); parameter [63:0] INIT = 0; wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0]; @@ -258,14 +205,6 @@ module LUT6(output O, input I0, I1, I2, I3, I4, I5); wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; assign O = I0 ? s1[1] : s1[0]; - specify - (I0 => O) = 642; - (I1 => O) = 631; - (I2 => O) = 472; - (I3 => O) = 407; - (I4 => O) = 238; - (I5 => O) = 127; - endspecify endmodule module LUT6_2(output O6, output O5, input I0, I1, I2, I3, I4, I5); @@ -284,86 +223,25 @@ module LUT6_2(output O6, output O5, input I0, I1, I2, I3, I4, I5); assign O5 = I0 ? s5_1[1] : s5_1[0]; endmodule -// This is a placeholder for ABC9 to extract the area/delay -// cost of 3-input LUTs and is not intended to be instantiated -(* abc9_lut=10 *) -module \$__ABC9_LUT7 (output O, input I0, I1, I2, I3, I4, I5, I6); -`ifndef __ICARUS__ - specify - // https://github.com/SymbiFlow/prjxray-db/blob/1c85daf1b115da4d27ca83c6b89f53a94de39748/artix7/timings/slicel.sdf#L867 - (I0 => O) = 642 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (I1 => O) = 631 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (I2 => O) = 472 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (I3 => O) = 407 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (I4 => O) = 238 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (I5 => O) = 127 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (I6 => O) = 0 + 296 /* to select F7BMUX */ + 174 /* CMUX */; - endspecify -`endif -endmodule - -// This is a placeholder for ABC9 to extract the area/delay -// cost of 3-input LUTs and is not intended to be instantiated -(* abc9_lut=20 *) -module \$__ABC9_LUT8 (output O, input I0, I1, I2, I3, I4, I5, I6, I7); -`ifndef __ICARUS__ - specify - // https://github.com/SymbiFlow/prjxray-db/blob/1c85daf1b115da4d27ca83c6b89f53a94de39748/artix7/timings/slicel.sdf#L716 - (I0 => O) = 642 + 223 /* to cross F7BMUX */ + 104 /* to cross F8MUX */ + 192 /* BMUX */; - (I1 => O) = 631 + 223 /* to cross F7BMUX */ + 104 /* to cross F8MUX */ + 192 /* BMUX */; - (I2 => O) = 472 + 223 /* to cross F7BMUX */ + 104 /* to cross F8MUX */ + 192 /* BMUX */; - (I3 => O) = 407 + 223 /* to cross F7BMUX */ + 104 /* to cross F8MUX */ + 192 /* BMUX */; - (I4 => O) = 238 + 223 /* to cross F7BMUX */ + 104 /* to cross F8MUX */ + 192 /* BMUX */; - (I5 => O) = 127 + 223 /* to cross F7BMUX */ + 104 /* to cross F8MUX */ + 192 /* BMUX */; - (I6 => O) = 0 + 296 /* to select F7BMUX */ + 104 /* to cross F8MUX */ + 192 /* BMUX */; - (I7 => O) = 0 + 0 + 273 /* to select F8MUX */ + 192 /* BMUX */; - endspecify -`endif -endmodule - module MUXCY(output O, input CI, DI, S); assign O = S ? CI : DI; endmodule -module MUXF5(output O, input I0, I1, S); - assign O = S ? I1 : I0; -endmodule - -module MUXF6(output O, input I0, I1, S); - assign O = S ? I1 : I0; -endmodule - -(* abc9_box, lib_whitebox *) +(* abc9_box_id = 1, lib_whitebox *) module MUXF7(output O, input I0, I1, S); assign O = S ? I1 : I0; - specify - // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L451-L453 - (I0 => O) = 217; - (I1 => O) = 223; - (S => O) = 296; - endspecify endmodule -(* abc9_box, lib_whitebox *) +(* abc9_box_id = 2, lib_whitebox *) module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; - specify - // Max delays from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L462-L464 - (I0 => O) = 104; - (I1 => O) = 94; - (S => O) = 273; - endspecify -endmodule - -module MUXF9(output O, input I0, I1, S); - assign O = S ? I1 : I0; endmodule module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc9_box, lib_whitebox *) +(* abc9_box_id = 4, lib_whitebox *) module CARRY4( (* abc9_carry *) output [3:0] CO, @@ -378,96 +256,18 @@ module CARRY4( assign CO[1] = S[1] ? CO[0] : DI[1]; assign CO[2] = S[2] ? CO[1] : DI[2]; assign CO[3] = S[3] ? CO[2] : DI[3]; - specify - // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L11-L46 - (CYINIT => O[0]) = 482; - (S[0] => O[0]) = 223; - (CI => O[0]) = 222; - (CYINIT => O[1]) = 598; - (DI[0] => O[1]) = 407; - (S[0] => O[1]) = 400; - (S[1] => O[1]) = 205; - (CI => O[1]) = 334; - (CYINIT => O[2]) = 584; - (DI[0] => O[2]) = 556; - (DI[1] => O[2]) = 537; - (S[0] => O[2]) = 523; - (S[1] => O[2]) = 558; - (S[2] => O[2]) = 226; - (CI => O[2]) = 239; - (CYINIT => O[3]) = 642; - (DI[0] => O[3]) = 615; - (DI[1] => O[3]) = 596; - (DI[2] => O[3]) = 438; - (S[0] => O[3]) = 582; - (S[1] => O[3]) = 618; - (S[2] => O[3]) = 330; - (S[3] => O[3]) = 227; - (CI => O[3]) = 313; - (CYINIT => CO[0]) = 536; - (DI[0] => CO[0]) = 379; - (S[0] => CO[0]) = 340; - (CI => CO[0]) = 271; - (CYINIT => CO[1]) = 494; - (DI[0] => CO[1]) = 465; - (DI[1] => CO[1]) = 445; - (S[0] => CO[1]) = 433; - (S[1] => CO[1]) = 469; - (CI => CO[1]) = 157; - (CYINIT => CO[2]) = 592; - (DI[0] => CO[2]) = 540; - (DI[1] => CO[2]) = 520; - (DI[2] => CO[2]) = 356; - (S[0] => CO[2]) = 512; - (S[1] => CO[2]) = 548; - (S[2] => CO[2]) = 292; - (CI => CO[2]) = 228; - (CYINIT => CO[3]) = 580; - (DI[0] => CO[3]) = 526; - (DI[1] => CO[3]) = 507; - (DI[2] => CO[3]) = 398; - (DI[3] => CO[3]) = 385; - (S[0] => CO[3]) = 508; - (S[1] => CO[3]) = 528; - (S[2] => CO[3]) = 378; - (S[3] => CO[3]) = 380; - (CI => CO[3]) = 114; - endspecify -endmodule - -module CARRY8( - output [7:0] CO, - output [7:0] O, - input CI, - input CI_TOP, - input [7:0] DI, S -); - parameter CARRY_TYPE = "SINGLE_CY8"; - wire CI4 = (CARRY_TYPE == "DUAL_CY4" ? CI_TOP : CO[3]); - assign O = S ^ {CO[6:4], CI4, CO[2:0], CI}; - assign CO[0] = S[0] ? CI : DI[0]; - assign CO[1] = S[1] ? CO[0] : DI[1]; - assign CO[2] = S[2] ? CO[1] : DI[2]; - assign CO[3] = S[3] ? CO[2] : DI[3]; - assign CO[4] = S[4] ? CI4 : DI[4]; - assign CO[5] = S[5] ? CO[4] : DI[5]; - assign CO[6] = S[6] ? CO[5] : DI[6]; - assign CO[7] = S[7] ? CO[6] : DI[7]; endmodule `ifdef _EXPLICIT_CARRY -(* abc9_box, blackbox *) +(* abc9_box_id = 9, blackbox *) module CARRY_COUT_PLUG(input CIN, output COUT); - assign COUT = CIN; - specify - (CIN => COUT) = 0; - endspecify +assign COUT = CIN; endmodule -(* abc9_box, lib_whitebox *) +(* abc9_box_id = 8, lib_whitebox *) module CARRY4_COUT( output [3:0] O, (* abc9_carry *) @@ -476,144 +276,31 @@ module CARRY4_COUT( input CI, input CYINIT, input [3:0] DI, S); -`ifdef __ICARUS__ - wire CI0 = (CI === 1'bz) ? CYINIT : - (CYINIT === 1'bz) ? CI : - (CI | CYINIT); -`else +`ifdef _ABC wire CI0 = CYINIT | CI; -`endif - - wire [3:0] CO; - - assign O = S ^ {CO[2:0], CI0}; - assign CO[0] = S[0] ? CI0 : DI[0]; - assign CO[1] = S[1] ? CO[0] : DI[1]; - assign CO[2] = S[2] ? CO[1] : DI[2]; - wire CO_TOP = S[3] ? CO[2] : DI[3]; - assign CO[3] = CO_TOP; - assign COUT = CO_TOP; - specify - (CYINIT => O[0]) = 482; - (S[0] => O[0]) = 223; - (CI => O[0]) = 222; - (CYINIT => O[1]) = 598; - (DI[0] => O[1]) = 407; - (S[0] => O[1]) = 400; - (S[1] => O[1]) = 205; - (CI => O[1]) = 334; - (CYINIT => O[2]) = 584; - (DI[0] => O[2]) = 556; - (DI[1] => O[2]) = 537; - (S[0] => O[2]) = 523; - (S[1] => O[2]) = 558; - (S[2] => O[2]) = 226; - (CI => O[2]) = 239; - (CYINIT => O[3]) = 642; - (DI[0] => O[3]) = 615; - (DI[1] => O[3]) = 596; - (DI[2] => O[3]) = 438; - (S[0] => O[3]) = 582; - (S[1] => O[3]) = 618; - (S[2] => O[3]) = 330; - (S[3] => O[3]) = 227; - (CI => O[3]) = 313; - (CYINIT => COUT) = 580; - (DI[0] => COUT) = 526; - (DI[1] => COUT) = 507; - (DI[2] => COUT) = 398; - (DI[3] => COUT) = 385; - (S[0] => COUT) = 508; - (S[1] => COUT) = 528; - (S[2] => COUT) = 378; - (S[3] => COUT) = 380; - (CI => COUT) = 114; - endspecify -endmodule - -(* abc9_box, lib_whitebox *) -module CARRY4_CO_COUT( - output [3:0] CO, - (* abc9_carry *) - output COUT, - (* abc9_carry *) - input CI, - input CYINIT, - input [3:0] DI, S); -`ifdef __ICARUS__ +`else wire CI0 = (CI === 1'bz) ? CYINIT : (CYINIT === 1'bz) ? CI : (CI | CYINIT); -`else - wire CI0 = CYINIT | CI; `endif wire [3:0] CO; + assign O = S ^ {CO[2:0], CI0}; assign CO[0] = S[0] ? CI0 : DI[0]; assign CO[1] = S[1] ? CO[0] : DI[1]; assign CO[2] = S[2] ? CO[1] : DI[2]; wire CO_TOP = S[3] ? CO[2] : DI[3]; assign CO[3] = CO_TOP; assign COUT = CO_TOP; - specify - (CYINIT => CO[0]) = 536; - (DI[0] => CO[0]) = 379; - (S[0] => CO[0]) = 340; - (CI => CO[0]) = 271; - (CYINIT => CO[1]) = 494; - (DI[0] => CO[1]) = 465; - (DI[1] => CO[1]) = 445; - (S[0] => CO[1]) = 433; - (S[1] => CO[1]) = 469; - (CI => CO[1]) = 157; - (CYINIT => CO[2]) = 592; - (DI[0] => CO[2]) = 540; - (DI[1] => CO[2]) = 520; - (DI[2] => CO[2]) = 356; - (S[0] => CO[2]) = 512; - (S[1] => CO[2]) = 548; - (S[2] => CO[2]) = 292; - (CI => CO[2]) = 228; - (CYINIT => CO[3]) = 580; - (DI[0] => CO[3]) = 526; - (DI[1] => CO[3]) = 507; - (DI[2] => CO[3]) = 398; - (DI[3] => CO[3]) = 385; - (S[0] => CO[3]) = 508; - (S[1] => CO[3]) = 528; - (S[2] => CO[3]) = 378; - (S[3] => CO[3]) = 380; - (CI => CO[3]) = 114; - (CYINIT => COUT) = 580; - (DI[0] => COUT) = 526; - (DI[1] => COUT) = 507; - (DI[2] => COUT) = 398; - (DI[3] => COUT) = 385; - (S[0] => COUT) = 508; - (S[1] => COUT) = 528; - (S[2] => COUT) = 378; - (S[3] => COUT) = 380; - (CI => COUT) = 114; - endspecify endmodule `endif -module ORCY (output O, input CI, I); - assign O = CI | I; -endmodule - -module MULT_AND (output LO, input I0, I1); - assign LO = I0 & I1; -endmodule - -// Flip-flops and latches. - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250 -(* abc9_flop, lib_whitebox *) module FDRE ( + (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) (* invertible_pin = "IS_C_INVERTED" *) @@ -629,56 +316,14 @@ module FDRE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; initial Q <= INIT; - generate - case (|IS_C_INVERTED) + generate case (|IS_C_INVERTED) 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase - endgenerate - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - $setup(D , posedge C &&& CE && !IS_C_INVERTED , /*-46*/ 0); // Negative times not currently supported - $setup(D , negedge C &&& CE && IS_C_INVERTED , /*-46*/ 0); // Negative times not currently supported - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE, posedge C &&& !IS_C_INVERTED, 109); - $setup(CE, negedge C &&& IS_C_INVERTED, 109); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 - $setup(R , posedge C &&& !IS_C_INVERTED, 404); - $setup(R , negedge C &&& IS_C_INVERTED, 404); - // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 - if (!IS_C_INVERTED && R != IS_R_INVERTED) (posedge C => (Q : 1'b0)) = 303; - if ( IS_C_INVERTED && R != IS_R_INVERTED) (negedge C => (Q : 1'b0)) = 303; - if (!IS_C_INVERTED && R == IS_R_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; - if ( IS_C_INVERTED && R == IS_R_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; - endspecify + endcase endgenerate endmodule -(* abc9_flop, lib_whitebox *) -module FDRE_1 ( - output reg Q, - (* clkbuf_sink *) - input C, - input CE, - input D, - input R -); - parameter [0:0] INIT = 1'b0; - initial Q <= INIT; - always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE, negedge C, 109); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 - $setup(R , negedge C, 404); // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 - if (R) (negedge C => (Q : 1'b0)) = 303; - if (!R && CE) (negedge C => (Q : D)) = 303; - endspecify -endmodule - -(* abc9_flop, lib_whitebox *) module FDSE ( + (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) (* invertible_pin = "IS_C_INVERTED" *) @@ -694,172 +339,39 @@ module FDSE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; initial Q <= INIT; - generate - case (|IS_C_INVERTED) + generate case (|IS_C_INVERTED) 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase - endgenerate - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - $setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported - $setup(D , negedge C &&& IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE, posedge C &&& !IS_C_INVERTED, 109); - $setup(CE, negedge C &&& IS_C_INVERTED, 109); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 - $setup(S , posedge C &&& !IS_C_INVERTED, 404); - $setup(S , negedge C &&& IS_C_INVERTED, 404); - // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 - if (!IS_C_INVERTED && S != IS_S_INVERTED) (posedge C => (Q : 1'b1)) = 303; - if ( IS_C_INVERTED && S != IS_S_INVERTED) (negedge C => (Q : 1'b1)) = 303; - if (!IS_C_INVERTED && S == IS_S_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; - if ( IS_C_INVERTED && S == IS_S_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; - endspecify + endcase endgenerate endmodule -(* abc9_flop, lib_whitebox *) -module FDSE_1 ( - output reg Q, - (* clkbuf_sink *) - input C, - input CE, - input D, - input S -); - parameter [0:0] INIT = 1'b1; - initial Q <= INIT; - always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE, negedge C, 109); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 - $setup(S , negedge C, 404); - // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 - if (S) (negedge C => (Q : 1'b1)) = 303; - if (!S && CE) (negedge C => (Q : D)) = 303; - endspecify -endmodule - -module FDRSE ( +module FDCE ( + (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) (* invertible_pin = "IS_C_INVERTED" *) input C, - (* invertible_pin = "IS_CE_INVERTED" *) input CE, (* invertible_pin = "IS_D_INVERTED" *) input D, - (* invertible_pin = "IS_R_INVERTED" *) - input R, - (* invertible_pin = "IS_S_INVERTED" *) - input S -); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_CE_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_R_INVERTED = 1'b0; - parameter [0:0] IS_S_INVERTED = 1'b0; - initial Q <= INIT; - wire c = C ^ IS_C_INVERTED; - wire ce = CE ^ IS_CE_INVERTED; - wire d = D ^ IS_D_INVERTED; - wire r = R ^ IS_R_INVERTED; - wire s = S ^ IS_S_INVERTED; - always @(posedge c) - if (r) - Q <= 0; - else if (s) - Q <= 1; - else if (ce) - Q <= d; -endmodule - -(* abc9_box, lib_whitebox *) -module FDCE ( - output reg Q, - (* clkbuf_sink *) - (* invertible_pin = "IS_C_INVERTED" *) - input C, - input CE, (* invertible_pin = "IS_CLR_INVERTED" *) - input CLR, - (* invertible_pin = "IS_D_INVERTED" *) - input D + input CLR ); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; - generate - case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) + generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase - endgenerate - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - $setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported - $setup(D , negedge C &&& IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE , posedge C &&& !IS_C_INVERTED, 109); - $setup(CE , negedge C &&& IS_C_INVERTED, 109); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 - $setup(CLR, posedge C &&& !IS_C_INVERTED, 404); - $setup(CLR, negedge C &&& IS_C_INVERTED, 404); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 -`ifndef YOSYS - if (!IS_CLR_INVERTED) (posedge CLR => (Q : 1'b0)) = 764; - if ( IS_CLR_INVERTED) (negedge CLR => (Q : 1'b0)) = 764; -`else - if (IS_CLR_INVERTED != CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - if (!IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; - if ( IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; - endspecify + endcase endgenerate endmodule -(* abc9_box, lib_whitebox *) -module FDCE_1 ( - output reg Q, - (* clkbuf_sink *) - input C, - input CE, - input CLR, - input D -); - parameter [0:0] INIT = 1'b0; - initial Q <= INIT; - always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE , negedge C, 109); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 - $setup(CLR, negedge C, 404); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 -`ifndef YOSYS - (posedge CLR => (Q : 1'b0)) = 764; -`else - if (CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - if (!CLR && CE) (negedge C => (Q : D)) = 303; - endspecify -endmodule - -(* abc9_box, lib_whitebox *) module FDPE ( + (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) (* invertible_pin = "IS_C_INVERTED" *) @@ -880,106 +392,55 @@ module FDPE ( 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase - endgenerate - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - $setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported - $setup(D , negedge C &&& IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE , posedge C &&& !IS_C_INVERTED, 109); - $setup(CE , negedge C &&& IS_C_INVERTED, 109); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 - $setup(PRE, posedge C &&& !IS_C_INVERTED, 404); - $setup(PRE, negedge C &&& IS_C_INVERTED, 404); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 -`ifndef YOSYS - if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; - if ( IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; -`else - if (IS_PRE_INVERTED != PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - if (!IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; - if ( IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; - endspecify + endcase endgenerate endmodule -(* abc9_box, lib_whitebox *) -module FDPE_1 ( +module FDRE_1 ( + (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) input C, - input CE, - input D, - input PRE + input CE, D, R +); + parameter [0:0] INIT = 1'b0; + initial Q <= INIT; + always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; +endmodule + +module FDSE_1 ( + (* abc9_arrival=303 *) + output reg Q, + (* clkbuf_sink *) + input C, + input CE, D, S ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE , negedge C, 109); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 - $setup(PRE, negedge C, 404); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 -`ifndef YOSYS - (posedge PRE => (Q : 1'b1)) = 764; -`else - if (PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path -`endif - if (!PRE && CE) (negedge C => (Q : D)) = 303; - endspecify + always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; endmodule -module FDCPE ( - output wire Q, +module FDCE_1 ( + (* abc9_arrival=303 *) + output reg Q, (* clkbuf_sink *) - (* invertible_pin = "IS_C_INVERTED" *) input C, - input CE, - (* invertible_pin = "IS_CLR_INVERTED" *) - input CLR, - input D, - (* invertible_pin = "IS_PRE_INVERTED" *) - input PRE + input CE, D, CLR ); parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_CLR_INVERTED = 1'b0; - parameter [0:0] IS_PRE_INVERTED = 1'b0; - wire c = C ^ IS_C_INVERTED; - wire clr = CLR ^ IS_CLR_INVERTED; - wire pre = PRE ^ IS_PRE_INVERTED; - // Hacky model to avoid simulation-synthesis mismatches. - reg qc, qp, qs; - initial qc = INIT; - initial qp = INIT; - initial qs = 0; - always @(posedge c, posedge clr) begin - if (clr) - qc <= 0; - else if (CE) - qc <= D; - end - always @(posedge c, posedge pre) begin - if (pre) - qp <= 1; - else if (CE) - qp <= D; - end - always @* begin - if (clr) - qs <= 0; - else if (pre) - qs <= 1; - end - assign Q = qs ? qp : qc; + initial Q <= INIT; + always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; +endmodule + +module FDPE_1 ( + (* abc9_arrival=303 *) + output reg Q, + (* clkbuf_sink *) + input C, + input CE, D, PRE +); + parameter [0:0] INIT = 1'b1; + initial Q <= INIT; + always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule module LDCE ( @@ -1000,8 +461,8 @@ module LDCE ( wire clr = CLR ^ IS_CLR_INVERTED; wire g = G ^ IS_G_INVERTED; always @* - if (clr) Q <= 1'b0; - else if (GE && g) Q <= D; + if (clr) Q = 1'b0; + else if (GE && g) Q = D; endmodule module LDPE ( @@ -1022,59 +483,8 @@ module LDPE ( wire g = G ^ IS_G_INVERTED; wire pre = PRE ^ IS_PRE_INVERTED; always @* - if (pre) Q <= 1'b1; - else if (GE && g) Q <= D; -endmodule - -module LDCPE ( - output reg Q, - (* invertible_pin = "IS_CLR_INVERTED" *) - input CLR, - (* invertible_pin = "IS_D_INVERTED" *) - input D, - (* invertible_pin = "IS_G_INVERTED" *) - input G, - (* invertible_pin = "IS_GE_INVERTED" *) - input GE, - (* invertible_pin = "IS_PRE_INVERTED" *) - input PRE -); - parameter [0:0] INIT = 1'b1; - parameter [0:0] IS_CLR_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_G_INVERTED = 1'b0; - parameter [0:0] IS_GE_INVERTED = 1'b0; - parameter [0:0] IS_PRE_INVERTED = 1'b0; - initial Q = INIT; - wire d = D ^ IS_D_INVERTED; - wire g = G ^ IS_G_INVERTED; - wire ge = GE ^ IS_GE_INVERTED; - wire clr = CLR ^ IS_CLR_INVERTED; - wire pre = PRE ^ IS_PRE_INVERTED; - always @* - if (clr) Q <= 1'b0; - else if (pre) Q <= 1'b1; - else if (ge && g) Q <= d; -endmodule - -module AND2B1L ( - output O, - input DI, - (* invertible_pin = "IS_SRI_INVERTED" *) - input SRI -); - parameter [0:0] IS_SRI_INVERTED = 1'b0; - assign O = DI & ~(SRI ^ IS_SRI_INVERTED); -endmodule - -module OR2L ( - output O, - input DI, - (* invertible_pin = "IS_SRI_INVERTED" *) - input SRI -); - parameter [0:0] IS_SRI_INVERTED = 1'b0; - assign O = DI | (SRI ^ IS_SRI_INVERTED); + if (pre) Q = 1'b1; + else if (GE && g) Q = D; endmodule // LUTRAM. @@ -1544,8 +954,9 @@ module RAM16X1D_1 ( always @(negedge clk) if (WE) mem[a] <= D; endmodule -(* abc9_box, lib_whitebox *) module RAM32X1D ( + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + (* abc9_arrival=1153 *) output DPO, SPO, input D, (* clkbuf_sink *) @@ -1564,54 +975,18 @@ module RAM32X1D ( assign DPO = mem[dpra]; wire clk = WCLK ^ IS_WCLK_INVERTED; always @(posedge clk) if (WE) mem[a] <= D; - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 - $setup(D , posedge WCLK &&& !IS_WCLK_INVERTED && WE, 453); - $setup(D , negedge WCLK &&& IS_WCLK_INVERTED && WE, 453); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 - $setup(WE, posedge WCLK &&& !IS_WCLK_INVERTED, 654); - $setup(WE, negedge WCLK &&& IS_WCLK_INVERTED, 654); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L800 - $setup(A0, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 245); - $setup(A0, negedge WCLK &&& IS_WCLK_INVERTED && WE, 245); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L798 - $setup(A1, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 208); - $setup(A1, negedge WCLK &&& IS_WCLK_INVERTED && WE, 208); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L796 - $setup(A2, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 147); - $setup(A2, negedge WCLK &&& IS_WCLK_INVERTED && WE, 147); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L794 - $setup(A3, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 68); - $setup(A3, negedge WCLK &&& IS_WCLK_INVERTED && WE, 68); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L792 - $setup(A4, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 66); - $setup(A4, posedge WCLK &&& IS_WCLK_INVERTED && WE, 66); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 - if (!IS_WCLK_INVERTED) (posedge WCLK => (SPO : D)) = 1153; - if (!IS_WCLK_INVERTED) (posedge WCLK => (DPO : 1'bx)) = 1153; - if ( IS_WCLK_INVERTED) (posedge WCLK => (SPO : D)) = 1153; - if ( IS_WCLK_INVERTED) (negedge WCLK => (DPO : 1'bx)) = 1153; - (A0 => SPO) = 642; (DPRA0 => DPO) = 642; - (A1 => SPO) = 632; (DPRA1 => DPO) = 631; - (A2 => SPO) = 472; (DPRA2 => DPO) = 472; - (A3 => SPO) = 407; (DPRA3 => DPO) = 407; - (A4 => SPO) = 238; (DPRA4 => DPO) = 238; - endspecify endmodule -(* abc9_box, lib_whitebox *) module RAM32X1D_1 ( + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + (* abc9_arrival=1153 *) output DPO, SPO, input D, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) input WCLK, input WE, - input A0, - input A1, - input A2, - input A3, - input A4, + input A0, A1, A2, A3, A4, input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 ); parameter INIT = 32'h0; @@ -1623,34 +998,11 @@ module RAM32X1D_1 ( assign DPO = mem[dpra]; wire clk = WCLK ^ IS_WCLK_INVERTED; always @(negedge clk) if (WE) mem[a] <= D; - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 - $setup(D , negedge WCLK &&& WE, 453); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 - $setup(WE, negedge WCLK, 654); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L800 - $setup(A0, negedge WCLK &&& WE, 245); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L798 - $setup(A1, negedge WCLK &&& WE, 208); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L796 - $setup(A2, negedge WCLK &&& WE, 147); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L794 - $setup(A3, negedge WCLK &&& WE, 68); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L792 - $setup(A4, negedge WCLK &&& WE, 66); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 - if (WE) (negedge WCLK => (SPO : D)) = 1153; - if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153; - (A0 => SPO) = 642; (DPRA0 => DPO) = 642; - (A1 => SPO) = 632; (DPRA1 => DPO) = 631; - (A2 => SPO) = 472; (DPRA2 => DPO) = 472; - (A3 => SPO) = 407; (DPRA3 => DPO) = 407; - (A4 => SPO) = 238; (DPRA4 => DPO) = 238; - endspecify endmodule -(* abc9_box, lib_whitebox *) module RAM64X1D ( + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + (* abc9_arrival=1153 *) output DPO, SPO, input D, (* clkbuf_sink *) @@ -1669,46 +1021,11 @@ module RAM64X1D ( assign DPO = mem[dpra]; wire clk = WCLK ^ IS_WCLK_INVERTED; always @(posedge clk) if (WE) mem[a] <= D; - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 - $setup(D , posedge WCLK &&& !IS_WCLK_INVERTED && WE, 453); - $setup(D , negedge WCLK &&& IS_WCLK_INVERTED && WE, 453); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 - $setup(WE, posedge WCLK &&& !IS_WCLK_INVERTED, 654); - $setup(WE, negedge WCLK &&& IS_WCLK_INVERTED, 654); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L828 - $setup(A0, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 362); - $setup(A0, negedge WCLK &&& IS_WCLK_INVERTED && WE, 362); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L826 - $setup(A1, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 245); - $setup(A1, negedge WCLK &&& IS_WCLK_INVERTED && WE, 245); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L824 - $setup(A2, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 208); - $setup(A2, negedge WCLK &&& IS_WCLK_INVERTED && WE, 208); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L822 - $setup(A3, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 147); - $setup(A3, negedge WCLK &&& IS_WCLK_INVERTED && WE, 147); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L820 - $setup(A4, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 68); - $setup(A4, negedge WCLK &&& IS_WCLK_INVERTED && WE, 68); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L818 - $setup(A5, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 66); - $setup(A5, negedge WCLK &&& IS_WCLK_INVERTED && WE, 66); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (SPO : D)) = 1153; - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DPO : 1'bx)) = 1153; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (SPO : D)) = 1153; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153; - (A0 => SPO) = 642; (DPRA0 => DPO) = 642; - (A1 => SPO) = 632; (DPRA1 => DPO) = 631; - (A2 => SPO) = 472; (DPRA2 => DPO) = 472; - (A3 => SPO) = 407; (DPRA3 => DPO) = 407; - (A4 => SPO) = 238; (DPRA4 => DPO) = 238; - (A5 => SPO) = 127; (DPRA5 => DPO) = 127; - endspecify endmodule module RAM64X1D_1 ( + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + (* abc9_arrival=1153 *) output DPO, SPO, input D, (* clkbuf_sink *) @@ -1727,45 +1044,18 @@ module RAM64X1D_1 ( assign DPO = mem[dpra]; wire clk = WCLK ^ IS_WCLK_INVERTED; always @(negedge clk) if (WE) mem[a] <= D; - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 - $setup(D , negedge WCLK &&& WE, 453); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 - $setup(WE, negedge WCLK, 654); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L828 - $setup(A0, negedge WCLK &&& WE, 362); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L826 - $setup(A1, negedge WCLK &&& WE, 245); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L824 - $setup(A2, negedge WCLK &&& WE, 208); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L822 - $setup(A3, negedge WCLK &&& WE, 147); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L820 - $setup(A4, negedge WCLK &&& WE, 68); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L818 - $setup(A5, negedge WCLK &&& WE, 66); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 - if (WE) (negedge WCLK => (SPO : D)) = 1153; - if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153; - (A0 => SPO) = 642; (DPRA0 => DPO) = 642; - (A1 => SPO) = 632; (DPRA1 => DPO) = 631; - (A2 => SPO) = 472; (DPRA2 => DPO) = 472; - (A3 => SPO) = 407; (DPRA3 => DPO) = 407; - (A4 => SPO) = 238; (DPRA4 => DPO) = 238; - (A5 => SPO) = 127; (DPRA5 => DPO) = 127; - endspecify endmodule -(* abc9_box, lib_whitebox *) module RAM128X1D ( - output DPO, SPO, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + (* abc9_arrival=1153 *) + output DPO, SPO, input D, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) input WCLK, input WE, - input [6:0] A, - input [6:0] DPRA + input [6:0] A, DPRA ); parameter INIT = 128'h0; parameter IS_WCLK_INVERTED = 1'b0; @@ -1774,48 +1064,6 @@ module RAM128X1D ( assign DPO = mem[DPRA]; wire clk = WCLK ^ IS_WCLK_INVERTED; always @(posedge clk) if (WE) mem[A] <= D; - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 - $setup(D , posedge WCLK &&& !IS_WCLK_INVERTED && WE, 453); - $setup(D , negedge WCLK &&& IS_WCLK_INVERTED && WE, 453); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 - $setup(WE, posedge WCLK &&& !IS_WCLK_INVERTED, 654); - $setup(WE, negedge WCLK &&& IS_WCLK_INVERTED, 654); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L818-830 - $setup(A[0], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 616); - $setup(A[0], negedge WCLK &&& IS_WCLK_INVERTED && WE, 616); - $setup(A[1], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 362); - $setup(A[1], negedge WCLK &&& IS_WCLK_INVERTED && WE, 362); - $setup(A[2], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 245); - $setup(A[2], negedge WCLK &&& IS_WCLK_INVERTED && WE, 245); - $setup(A[3], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 208); - $setup(A[3], negedge WCLK &&& IS_WCLK_INVERTED && WE, 208); - $setup(A[4], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 147); - $setup(A[4], negedge WCLK &&& IS_WCLK_INVERTED && WE, 147); - $setup(A[5], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 68); - $setup(A[5], negedge WCLK &&& IS_WCLK_INVERTED && WE, 68); - $setup(A[6], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 66); - $setup(A[6], negedge WCLK &&& IS_WCLK_INVERTED && WE, 66); -`ifndef __ICARUS__ - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (SPO : D)) = 1153 + 217 /* to cross F7AMUX */ + 175 /* AMUX */; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (A[0] => SPO) = 642 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - (A[1] => SPO) = 631 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - (A[2] => SPO) = 472 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - (A[3] => SPO) = 407 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - (A[4] => SPO) = 238 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - (A[5] => SPO) = 127 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - (A[6] => SPO) = 0 + 276 /* to select F7AMUX */ + 175 /* AMUX */; - (DPRA[0] => DPO) = 642 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - (DPRA[1] => DPO) = 631 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - (DPRA[2] => DPO) = 472 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - (DPRA[3] => DPO) = 407 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - (DPRA[4] => DPO) = 238 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - (DPRA[5] => DPO) = 127 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - (DPRA[6] => DPO) = 0 + 296 /* to select MUXF7 */ + 174 /* CMUX */; -`endif - endspecify endmodule module RAM256X1D ( @@ -1838,22 +1086,23 @@ endmodule // Multi port. -(* abc9_box, lib_whitebox *) module RAM32M ( output [1:0] DOA, output [1:0] DOB, output [1:0] DOC, output [1:0] DOD, - input [4:0] ADDRA, ADDRB, ADDRC, - input [4:0] ADDRD, - input [1:0] DIA, - input [1:0] DIB, - input [1:0] DIC, - input [1:0] DID, + input [4:0] ADDRA, + input [4:0] ADDRB, + input [4:0] ADDRC, + input [4:0] ADDRD, + input [1:0] DIA, + input [1:0] DIB, + input [1:0] DIC, + input [1:0] DID, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) - input WCLK, - input WE + input WCLK, + input WE ); parameter [63:0] INIT_A = 64'h0000000000000000; parameter [63:0] INIT_B = 64'h0000000000000000; @@ -1876,71 +1125,6 @@ module RAM32M ( mem_c[2*ADDRD+:2] <= DIC; mem_d[2*ADDRD+:2] <= DID; end - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 - $setup(ADDRD[0], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 245); - $setup(ADDRD[0], negedge WCLK &&& IS_WCLK_INVERTED && WE, 245); - $setup(ADDRD[1], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 208); - $setup(ADDRD[1], negedge WCLK &&& IS_WCLK_INVERTED && WE, 208); - $setup(ADDRD[2], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 147); - $setup(ADDRD[2], negedge WCLK &&& IS_WCLK_INVERTED && WE, 147); - $setup(ADDRD[3], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 68); - $setup(ADDRD[3], negedge WCLK &&& IS_WCLK_INVERTED && WE, 68); - $setup(ADDRD[4], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 66); - $setup(ADDRD[4], negedge WCLK &&& IS_WCLK_INVERTED && WE, 66); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986-L988 - $setup(DIA[0], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 453); - $setup(DIA[0], negedge WCLK &&& IS_WCLK_INVERTED && WE, 453); - $setup(DIA[1], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 384); - $setup(DIA[1], negedge WCLK &&& IS_WCLK_INVERTED && WE, 384); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1054-L1056 - $setup(DIB[0], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 461); - $setup(DIB[0], negedge WCLK &&& IS_WCLK_INVERTED && WE, 461); - $setup(DIB[1], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 354); - $setup(DIB[1], negedge WCLK &&& IS_WCLK_INVERTED && WE, 354); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1122-L1124 - $setup(DIC[0], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 457); - $setup(DIC[0], negedge WCLK &&& IS_WCLK_INVERTED && WE, 457); - $setup(DIC[1], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 375); - $setup(DIC[1], negedge WCLK &&& IS_WCLK_INVERTED && WE, 375); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1190-L1192 - $setup(DID[0], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 310); - $setup(DID[0], negedge WCLK &&& IS_WCLK_INVERTED && WE, 310); - $setup(DID[1], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 334); - $setup(DID[1], negedge WCLK &&& IS_WCLK_INVERTED && WE, 334); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 - $setup(WE, posedge WCLK &&& !IS_WCLK_INVERTED, 654); - $setup(WE, negedge WCLK &&& IS_WCLK_INVERTED, 654); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L889 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOA[0] : DIA[0])) = 1153; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOA[0] : DIA[0])) = 1153; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L857 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOA[1] : DIA[1])) = 1188; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOA[1] : DIA[1])) = 1188; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOB[0] : DIB[0])) = 1161; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOB[0] : DIB[0])) = 1161; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L925 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOB[1] : DIB[1])) = 1187; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOB[1] : DIB[1])) = 1187; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L993 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOC[0] : DIC[0])) = 1158; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOC[0] : DIC[0])) = 1158; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1025 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOC[1] : DIC[1])) = 1180; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOC[1] : DIC[1])) = 1180; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1093 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD[0] : DID[0])) = 1163; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD[0] : DID[0])) = 1163; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1061 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD[1] : DID[1])) = 1190; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD[1] : DID[1])) = 1190; - (ADDRA[0] *> DOA) = 642; (ADDRB[0] *> DOB) = 642; (ADDRC[0] *> DOC) = 642; (ADDRD[0] *> DOD) = 642; - (ADDRA[1] *> DOA) = 631; (ADDRB[1] *> DOB) = 631; (ADDRC[1] *> DOC) = 631; (ADDRD[1] *> DOD) = 631; - (ADDRA[2] *> DOA) = 472; (ADDRB[2] *> DOB) = 472; (ADDRC[2] *> DOC) = 472; (ADDRD[2] *> DOD) = 472; - (ADDRA[3] *> DOA) = 407; (ADDRB[3] *> DOB) = 407; (ADDRC[3] *> DOC) = 407; (ADDRD[3] *> DOD) = 407; - (ADDRA[4] *> DOA) = 238; (ADDRB[4] *> DOB) = 238; (ADDRC[4] *> DOC) = 238; (ADDRD[4] *> DOD) = 238; - endspecify endmodule module RAM32M16 ( @@ -2012,22 +1196,23 @@ module RAM32M16 ( end endmodule -(* abc9_box, lib_whitebox *) module RAM64M ( - output DOA, - output DOB, - output DOC, - output DOD, - input [5:0] ADDRA, ADDRB, ADDRC, - input [5:0] ADDRD, - input DIA, - input DIB, - input DIC, - input DID, + output DOA, + output DOB, + output DOC, + output DOD, + input [4:0] ADDRA, + input [4:0] ADDRB, + input [4:0] ADDRC, + input [4:0] ADDRD, + input DIA, + input DIB, + input DIC, + input DID, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) - input WCLK, - input WE + input WCLK, + input WE ); parameter [63:0] INIT_A = 64'h0000000000000000; parameter [63:0] INIT_B = 64'h0000000000000000; @@ -2050,53 +1235,6 @@ module RAM64M ( mem_c[ADDRD] <= DIC; mem_d[ADDRD] <= DID; end - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L818-L830 - $setup(ADDRD[0], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 362); - $setup(ADDRD[0], negedge WCLK &&& IS_WCLK_INVERTED && WE, 362); - $setup(ADDRD[1], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 245); - $setup(ADDRD[1], negedge WCLK &&& IS_WCLK_INVERTED && WE, 245); - $setup(ADDRD[2], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 208); - $setup(ADDRD[2], negedge WCLK &&& IS_WCLK_INVERTED && WE, 208); - $setup(ADDRD[3], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 147); - $setup(ADDRD[3], negedge WCLK &&& IS_WCLK_INVERTED && WE, 147); - $setup(ADDRD[4], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 68); - $setup(ADDRD[4], negedge WCLK &&& IS_WCLK_INVERTED && WE, 68); - $setup(ADDRD[5], posedge WCLK &&& !IS_WCLK_INVERTED && WE, 66); - $setup(ADDRD[5], negedge WCLK &&& IS_WCLK_INVERTED && WE, 66); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986-L988 - $setup(DIA, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 384); - $setup(DIA, negedge WCLK &&& IS_WCLK_INVERTED && WE, 384); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1054-L1056 - $setup(DIB, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 354); - $setup(DIB, negedge WCLK &&& IS_WCLK_INVERTED && WE, 354); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1122-L1124 - $setup(DIC, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 375); - $setup(DIC, negedge WCLK &&& IS_WCLK_INVERTED && WE, 375); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1190-L1192 - $setup(DID, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 310); - $setup(DID, negedge WCLK &&& IS_WCLK_INVERTED && WE, 310); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 - $setup(WE, posedge WCLK &&& !IS_WCLK_INVERTED && WE, 654); - $setup(WE, negedge WCLK &&& IS_WCLK_INVERTED && WE, 654); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L889 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOA : DIA)) = 1153; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOA : DIA)) = 1153; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOB : DIB)) = 1161; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOB : DIB)) = 1161; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1025 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOC : DIC)) = 1158; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOC : DIC)) = 1158; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1093 - if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD : DID)) = 1163; - if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD : DID)) = 1163; - (ADDRA[0] => DOA) = 642; (ADDRB[0] => DOB) = 642; (ADDRC[0] => DOC) = 642; (ADDRD[0] => DOD) = 642; - (ADDRA[1] => DOA) = 631; (ADDRB[1] => DOB) = 631; (ADDRC[1] => DOC) = 631; (ADDRD[1] => DOD) = 631; - (ADDRA[2] => DOA) = 472; (ADDRB[2] => DOB) = 472; (ADDRC[2] => DOC) = 472; (ADDRD[2] => DOD) = 472; - (ADDRA[3] => DOA) = 407; (ADDRB[3] => DOB) = 407; (ADDRC[3] => DOC) = 407; (ADDRD[3] => DOD) = 407; - (ADDRA[4] => DOA) = 238; (ADDRB[4] => DOB) = 238; (ADDRC[4] => DOC) = 238; (ADDRD[4] => DOD) = 238; - endspecify endmodule module RAM64M8 ( @@ -2108,14 +1246,14 @@ module RAM64M8 ( output DOF, output DOG, output DOH, - input [5:0] ADDRA, - input [5:0] ADDRB, - input [5:0] ADDRC, - input [5:0] ADDRD, - input [5:0] ADDRE, - input [5:0] ADDRF, - input [5:0] ADDRG, - input [5:0] ADDRH, + input [4:0] ADDRA, + input [4:0] ADDRB, + input [4:0] ADDRC, + input [4:0] ADDRD, + input [4:0] ADDRE, + input [4:0] ADDRF, + input [4:0] ADDRG, + input [4:0] ADDRH, input DIA, input DIB, input DIC, @@ -2212,34 +1350,9 @@ endmodule // Shift registers. -(* abc9_box, lib_whitebox *) -module SRL16 ( - output Q, - input A0, A1, A2, A3, - (* clkbuf_sink *) - input CLK, - input D -); - parameter [15:0] INIT = 16'h0000; - - reg [15:0] r = INIT; - assign Q = r[{A3,A2,A1,A0}]; - always @(posedge CLK) r <= { r[14:0], D }; - - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 - (posedge CLK => (Q : 1'bx)) = 1472; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 - $setup(D , posedge CLK, 173); - (A0 => Q) = 631; - (A1 => Q) = 472; - (A2 => Q) = 407; - (A3 => Q) = 238; - endspecify -endmodule - -(* abc9_box, lib_whitebox *) module SRL16E ( + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905 + (* abc9_arrival=1472 *) output Q, input A0, A1, A2, A3, CE, (* clkbuf_sink *) @@ -2259,54 +1372,8 @@ module SRL16E ( else always @(posedge CLK) if (CE) r <= { r[14:0], D }; endgenerate - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 - $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); - $setup(D , negedge CLK &&& IS_CLK_INVERTED, 173); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 - if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472; - if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 - if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472; - if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472; - (A0 => Q) = 631; - (A1 => Q) = 472; - (A2 => Q) = 407; - (A3 => Q) = 238; - endspecify endmodule -(* abc9_box, lib_whitebox *) -module SRLC16 ( - output Q, - output Q15, - input A0, A1, A2, A3, - (* clkbuf_sink *) - input CLK, - input D -); - parameter [15:0] INIT = 16'h0000; - - reg [15:0] r = INIT; - assign Q15 = r[15]; - assign Q = r[{A3,A2,A1,A0}]; - always @(posedge CLK) r <= { r[14:0], D }; - - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 - $setup(D , posedge CLK, 173); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 - (posedge CLK => (Q : 1'bx)) = 1472; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 - (posedge CLK => (Q15 : 1'bx)) = 1114; - (A0 => Q) = 631; - (A1 => Q) = 472; - (A2 => Q) = 407; - (A3 => Q) = 238; - endspecify -endmodule - -(* abc9_box, lib_whitebox *) module SRLC16E ( output Q, output Q15, @@ -2329,29 +1396,13 @@ module SRLC16E ( else always @(posedge CLK) if (CE) r <= { r[14:0], D }; endgenerate - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 - $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); - $setup(D , negedge CLK &&& IS_CLK_INVERTED, 173); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE, posedge CLK &&& !IS_CLK_INVERTED, 109); - $setup(CE, negedge CLK &&& IS_CLK_INVERTED, 109); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 - if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472; - if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 - if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q15 : 1'bx)) = 1114; - if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q15 : 1'bx)) = 1114; - (A0 => Q) = 631; - (A1 => Q) = 472; - (A2 => Q) = 407; - (A3 => Q) = 238; - endspecify endmodule -(* abc9_box, lib_whitebox *) module SRLC32E ( + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905 + (* abc9_arrival=1472 *) output Q, + (* abc9_arrival=1114 *) output Q31, input [4:0] A, input CE, @@ -2373,50 +1424,6 @@ module SRLC32E ( else always @(posedge CLK) if (CE) r <= { r[30:0], D }; endgenerate - specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 - $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); - $setup(D , negedge CLK &&& IS_CLK_INVERTED, 173); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 - $setup(CE, posedge CLK &&& !IS_CLK_INVERTED, 109); - $setup(CE, negedge CLK &&& IS_CLK_INVERTED, 109); - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 - if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472; - if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472; - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 - if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q31 : 1'bx)) = 1114; - if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q31 : 1'bx)) = 1114; - (A[0] => Q) = 642; - (A[1] => Q) = 631; - (A[2] => Q) = 472; - (A[3] => Q) = 407; - (A[4] => Q) = 238; - endspecify -endmodule - -module CFGLUT5 ( - output CDO, - output O5, - output O6, - input I4, - input I3, - input I2, - input I1, - input I0, - input CDI, - input CE, - (* clkbuf_sink *) - (* invertible_pin = "IS_CLK_INVERTED" *) - input CLK -); - parameter [31:0] INIT = 32'h00000000; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - wire clk = CLK ^ IS_CLK_INVERTED; - reg [31:0] r = INIT; - assign CDO = r[31]; - assign O5 = r[{1'b0, I3, I2, I1, I0}]; - assign O6 = r[{I4, I3, I2, I1, I0}]; - always @(posedge clk) if (CE) r <= {r[30:0], CDI}; endmodule // DSP @@ -2575,7 +1582,6 @@ parameter RSTTYPE = "SYNC"; // This is a strict subset of Spartan 6 -- reuse its model. -/* verilator lint_off PINMISSING */ DSP48A1 #( .A0REG(A0REG), .A1REG(A1REG), @@ -2622,7 +1628,6 @@ DSP48A1 #( .RSTOPMODE(RSTOPMODE), .RSTP(RSTP) ); -/* verilator lint_on PINMISSING */ endmodule @@ -2896,7 +1901,7 @@ always @* begin 2'b00: XMUX <= 0; 2'b01: XMUX <= M; 2'b10: XMUX <= P; - 2'b11: XMUX <= {D_OUT[11:0], A1_OUT, B1_OUT}; + 2'b11: XMUX <= {D_OUT[11:0], B1_OUT, A1_OUT}; default: XMUX <= 48'hxxxxxxxxxxxx; endcase end @@ -2914,8 +1919,8 @@ end // The post-adder. wire signed [48:0] X_EXT; wire signed [48:0] Z_EXT; -assign X_EXT = {1'b0, XMUX}; -assign Z_EXT = {1'b0, ZMUX}; +assign X_EXT = XMUX; +assign Z_EXT = ZMUX; assign {CARRYOUT_IN, P_IN} = OPMODE_OUT[7] ? (Z_EXT - (X_EXT + CARRYIN_OUT)) : (Z_EXT + X_EXT + CARRYIN_OUT); // Cascade outputs. @@ -2924,244 +1929,12 @@ assign PCOUT = P; endmodule -module DSP48 ( - input signed [17:0] A, - input signed [17:0] B, - input signed [47:0] C, - input signed [17:0] BCIN, - input signed [47:0] PCIN, - input CARRYIN, - input [6:0] OPMODE, - input SUBTRACT, - input [1:0] CARRYINSEL, - output signed [47:0] P, - output signed [17:0] BCOUT, - output signed [47:0] PCOUT, - (* clkbuf_sink *) - input CLK, - input CEA, - input CEB, - input CEC, - input CEM, - input CECARRYIN, - input CECINSUB, - input CECTRL, - input CEP, - input RSTA, - input RSTB, - input RSTC, - input RSTM, - input RSTCARRYIN, - input RSTCTRL, - input RSTP -); - -parameter integer AREG = 1; -parameter integer BREG = 1; -parameter integer CREG = 1; -parameter integer MREG = 1; -parameter integer PREG = 1; -parameter integer CARRYINREG = 1; -parameter integer CARRYINSELREG = 1; -parameter integer OPMODEREG = 1; -parameter integer SUBTRACTREG = 1; -parameter B_INPUT = "DIRECT"; -parameter LEGACY_MODE = "MULT18X18S"; - -wire signed [17:0] A_OUT; -wire signed [17:0] B_OUT; -wire signed [47:0] C_OUT; -wire signed [35:0] M_MULT; -wire signed [35:0] M_OUT; -wire signed [47:0] P_IN; -wire [6:0] OPMODE_OUT; -wire [1:0] CARRYINSEL_OUT; -wire CARRYIN_OUT; -wire SUBTRACT_OUT; -reg INT_CARRYIN_XY; -reg INT_CARRYIN_Z; -reg signed [47:0] XMUX; -reg signed [47:0] YMUX; -wire signed [47:0] XYMUX; -reg signed [47:0] ZMUX; -reg CIN; - -// The B input multiplexer. -wire signed [17:0] B_MUX; -assign B_MUX = (B_INPUT == "DIRECT") ? B : BCIN; - -// The cascade output. -assign BCOUT = B_OUT; -assign PCOUT = P; - -// The registers. -reg signed [17:0] A0_REG; -reg signed [17:0] A1_REG; -reg signed [17:0] B0_REG; -reg signed [17:0] B1_REG; -reg signed [47:0] C_REG; -reg signed [35:0] M_REG; -reg signed [47:0] P_REG; -reg [6:0] OPMODE_REG; -reg [1:0] CARRYINSEL_REG; -reg SUBTRACT_REG; -reg CARRYIN_REG; -reg INT_CARRYIN_XY_REG; - -initial begin - A0_REG = 0; - A1_REG = 0; - B0_REG = 0; - B1_REG = 0; - C_REG = 0; - M_REG = 0; - P_REG = 0; - OPMODE_REG = 0; - CARRYINSEL_REG = 0; - SUBTRACT_REG = 0; - CARRYIN_REG = 0; - INT_CARRYIN_XY_REG = 0; -end - -always @(posedge CLK) begin - if (RSTA) begin - A0_REG <= 0; - A1_REG <= 0; - end else if (CEA) begin - A0_REG <= A; - A1_REG <= A0_REG; - end - if (RSTB) begin - B0_REG <= 0; - B1_REG <= 0; - end else if (CEB) begin - B0_REG <= B_MUX; - B1_REG <= B0_REG; - end - if (RSTC) begin - C_REG <= 0; - end else if (CEC) begin - C_REG <= C; - end - if (RSTM) begin - M_REG <= 0; - end else if (CEM) begin - M_REG <= M_MULT; - end - if (RSTP) begin - P_REG <= 0; - end else if (CEP) begin - P_REG <= P_IN; - end - if (RSTCTRL) begin - OPMODE_REG <= 0; - CARRYINSEL_REG <= 0; - SUBTRACT_REG <= 0; - end else begin - if (CECTRL) begin - OPMODE_REG <= OPMODE; - CARRYINSEL_REG <= CARRYINSEL; - end - if (CECINSUB) - SUBTRACT_REG <= SUBTRACT; - end - if (RSTCARRYIN) begin - CARRYIN_REG <= 0; - INT_CARRYIN_XY_REG <= 0; - end else begin - if (CECINSUB) - CARRYIN_REG <= CARRYIN; - if (CECARRYIN) - INT_CARRYIN_XY_REG <= INT_CARRYIN_XY; - end -end - -// The register enables. -assign A_OUT = (AREG == 2) ? A1_REG : (AREG == 1) ? A0_REG : A; -assign B_OUT = (BREG == 2) ? B1_REG : (BREG == 1) ? B0_REG : B_MUX; -assign C_OUT = (CREG == 1) ? C_REG : C; -assign M_OUT = (MREG == 1) ? M_REG : M_MULT; -assign P = (PREG == 1) ? P_REG : P_IN; -assign OPMODE_OUT = (OPMODEREG == 1) ? OPMODE_REG : OPMODE; -assign SUBTRACT_OUT = (SUBTRACTREG == 1) ? SUBTRACT_REG : SUBTRACT; -assign CARRYINSEL_OUT = (CARRYINSELREG == 1) ? CARRYINSEL_REG : CARRYINSEL; -assign CARRYIN_OUT = (CARRYINREG == 1) ? CARRYIN_REG : CARRYIN; - -// The multiplier. -assign M_MULT = A_OUT * B_OUT; - -// The post-adder inputs. -always @* begin - case (OPMODE_OUT[1:0]) - 2'b00: XMUX <= 0; - 2'b10: XMUX <= P; - 2'b11: XMUX <= {{12{A_OUT[17]}}, A_OUT, B_OUT}; - default: XMUX <= 48'hxxxxxxxxxxxx; - endcase - case (OPMODE_OUT[1:0]) - 2'b01: INT_CARRYIN_XY <= A_OUT[17] ~^ B_OUT[17]; - 2'b11: INT_CARRYIN_XY <= ~A_OUT[17]; - // TODO: not tested in hardware. - default: INT_CARRYIN_XY <= A_OUT[17] ~^ B_OUT[17]; - endcase -end - -always @* begin - case (OPMODE_OUT[3:2]) - 2'b00: YMUX <= 0; - 2'b11: YMUX <= C_OUT; - default: YMUX <= 48'hxxxxxxxxxxxx; - endcase -end - -assign XYMUX = (OPMODE_OUT[3:0] == 4'b0101) ? M_OUT : (XMUX + YMUX); - -always @* begin - case (OPMODE_OUT[6:4]) - 3'b000: ZMUX <= 0; - 3'b001: ZMUX <= PCIN; - 3'b010: ZMUX <= P; - 3'b011: ZMUX <= C_OUT; - 3'b101: ZMUX <= {{17{PCIN[47]}}, PCIN[47:17]}; - 3'b110: ZMUX <= {{17{P[47]}}, P[47:17]}; - default: ZMUX <= 48'hxxxxxxxxxxxx; - endcase - // TODO: check how all this works on actual hw. - if (OPMODE_OUT[1:0] == 2'b10) - INT_CARRYIN_Z <= ~P[47]; - else - case (OPMODE_OUT[6:4]) - 3'b001: INT_CARRYIN_Z <= ~PCIN[47]; - 3'b010: INT_CARRYIN_Z <= ~P[47]; - 3'b101: INT_CARRYIN_Z <= ~PCIN[47]; - 3'b110: INT_CARRYIN_Z <= ~P[47]; - default: INT_CARRYIN_Z <= 1'bx; - endcase -end - -always @* begin - case (CARRYINSEL_OUT) - 2'b00: CIN <= CARRYIN_OUT; - 2'b01: CIN <= INT_CARRYIN_Z; - 2'b10: CIN <= INT_CARRYIN_XY; - 2'b11: CIN <= INT_CARRYIN_XY_REG; - default: CIN <= 1'bx; - endcase -end - -// The post-adder. -assign P_IN = SUBTRACT_OUT ? (ZMUX - (XYMUX + CIN)) : (ZMUX + XYMUX + CIN); - -endmodule +// TODO: DSP48 (Virtex 4). // TODO: DSP48E (Virtex 5). // Virtex 6, Series 7. -`ifdef YOSYS -(* abc9_box=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG), - lib_whitebox=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG) *) -`endif module DSP48E1 ( output [29:0] ACOUT, output [17:0] BCOUT, @@ -3244,244 +2017,8 @@ module DSP48E1 ( parameter [4:0] IS_INMODE_INVERTED = 5'b0; parameter [6:0] IS_OPMODE_INVERTED = 7'b0; -`ifdef YOSYS - function integer \A.required ; - begin - if (AREG != 0) \A.required = 254; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin - if (MREG != 0) \A.required = 1416; - else if (PREG != 0) \A.required = (USE_PATTERN_DETECT != "NO_PATDET" ? 3030 : 2739) ; - end - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin - // Worst-case from ADREG and MREG - if (MREG != 0) \A.required = 2400; - else if (ADREG != 0) \A.required = 1283; - else if (PREG != 0) \A.required = 3723; - else if (PREG != 0) \A.required = (USE_PATTERN_DETECT != "NO_PATDET" ? 4014 : 3723) ; - end - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin - if (PREG != 0) \A.required = (USE_PATTERN_DETECT != "NO_PATDET" ? 1730 : 1441) ; - end - end - endfunction - function integer \B.required ; - begin - if (BREG != 0) \B.required = 324; - else if (MREG != 0) \B.required = 1285; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin - if (PREG != 0) \B.required = (USE_PATTERN_DETECT != "NO_PATDET" ? 2898 : 2608) ; - end - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin - if (PREG != 0) \B.required = (USE_PATTERN_DETECT != "NO_PATDET" ? 2898 : 2608) ; - end - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin - if (PREG != 0) \B.required = (USE_PATTERN_DETECT != "NO_PATDET" ? 1718 : 1428) ; - end - end - endfunction - function integer \C.required ; - begin - if (CREG != 0) \C.required = 168; - else if (PREG != 0) \C.required = (USE_PATTERN_DETECT != "NO_PATDET" ? 1534 : 1244) ; - end - endfunction - function integer \D.required ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin - end - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin - if (DREG != 0) \D.required = 248; - else if (ADREG != 0) \D.required = 1195; - else if (MREG != 0) \D.required = 2310; - else if (PREG != 0) \D.required = (USE_PATTERN_DETECT != "NO_PATDET" ? 3925 : 3635) ; - end - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin - end - end - endfunction - function integer \P.arrival ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin - if (PREG != 0) \P.arrival = 329; - // Worst-case from CREG and MREG - else if (CREG != 0) \P.arrival = 1687; - else if (MREG != 0) \P.arrival = 1671; - // Worst-case from AREG and BREG - else if (AREG != 0) \P.arrival = 2952; - else if (BREG != 0) \P.arrival = 2813; - end - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin - if (PREG != 0) \P.arrival = 329; - // Worst-case from CREG and MREG - else if (CREG != 0) \P.arrival = 1687; - else if (MREG != 0) \P.arrival = 1671; - // Worst-case from AREG, ADREG, BREG, DREG - else if (AREG != 0) \P.arrival = 3935; - else if (DREG != 0) \P.arrival = 3908; - else if (ADREG != 0) \P.arrival = 2958; - else if (BREG != 0) \P.arrival = 2813; - end - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin - if (PREG != 0) \P.arrival = 329; - // Worst-case from AREG, BREG, CREG - else if (CREG != 0) \P.arrival = 1687; - else if (AREG != 0) \P.arrival = 1632; - else if (BREG != 0) \P.arrival = 1616; - end - end - endfunction - function integer \PCOUT.arrival ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin - if (PREG != 0) \PCOUT.arrival = 435; - // Worst-case from CREG and MREG - else if (CREG != 0) \PCOUT.arrival = 1835; - else if (MREG != 0) \PCOUT.arrival = 1819; - // Worst-case from AREG and BREG - else if (AREG != 0) \PCOUT.arrival = 3098; - else if (BREG != 0) \PCOUT.arrival = 2960; - end - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin - if (PREG != 0) \PCOUT.arrival = 435; - // Worst-case from CREG and MREG - else if (CREG != 0) \PCOUT.arrival = 1835; - else if (MREG != 0) \PCOUT.arrival = 1819; - // Worst-case from AREG, ADREG, BREG, DREG - else if (AREG != 0) \PCOUT.arrival = 4083; - else if (DREG != 0) \PCOUT.arrival = 4056; - else if (BREG != 0) \PCOUT.arrival = 2960; - else if (ADREG != 0) \PCOUT.arrival = 2859; - end - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin - if (PREG != 0) \PCOUT.arrival = 435; - // Worst-case from AREG, BREG, CREG - else if (CREG != 0) \PCOUT.arrival = 1835; - else if (AREG != 0) \PCOUT.arrival = 1780; - else if (BREG != 0) \PCOUT.arrival = 1765; - end - end - endfunction - function integer \A.P.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \A.P.comb = 2823; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \A.P.comb = 3806; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \A.P.comb = 1523; - end - endfunction - function integer \A.PCOUT.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \A.PCOUT.comb = 2970; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \A.PCOUT.comb = 3954; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \A.PCOUT.comb = 1671; - end - endfunction - function integer \B.P.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \B.P.comb = 2690; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \B.P.comb = 2690; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \B.P.comb = 1509; - end - endfunction - function integer \B.PCOUT.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \B.PCOUT.comb = 2838; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \B.PCOUT.comb = 2838; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \B.PCOUT.comb = 1658; - end - endfunction - function integer \C.P.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \C.P.comb = 1325; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \C.P.comb = 1325; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \C.P.comb = 1325; - end - endfunction - function integer \C.PCOUT.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \C.PCOUT.comb = 1474; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \C.PCOUT.comb = 1474; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \C.PCOUT.comb = 1474; - end - endfunction - function integer \D.P.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \D.P.comb = 3717; - end - endfunction - function integer \D.PCOUT.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \D.PCOUT.comb = 3700; - end - endfunction - - generate - if (PREG == 0 && MREG == 0 && AREG == 0 && ADREG == 0) - specify - (A *> P) = \A.P.comb (); - (A *> PCOUT) = \A.PCOUT.comb (); - endspecify - else - specify - $setup(A, posedge CLK &&& !IS_CLK_INVERTED, \A.required () ); - $setup(A, negedge CLK &&& IS_CLK_INVERTED, \A.required () ); - endspecify - - if (PREG == 0 && MREG == 0 && BREG == 0) - specify - (B *> P) = \B.P.comb (); - (B *> PCOUT) = \B.PCOUT.comb (); - endspecify - else - specify - $setup(B, posedge CLK &&& !IS_CLK_INVERTED, \B.required () ); - $setup(B, negedge CLK &&& IS_CLK_INVERTED, \B.required () ); - endspecify - - if (PREG == 0 && CREG == 0) - specify - (C *> P) = \C.P.comb (); - (C *> PCOUT) = \C.PCOUT.comb (); - endspecify - else - specify - $setup(C, posedge CLK &&& !IS_CLK_INVERTED, \C.required () ); - $setup(C, negedge CLK &&& IS_CLK_INVERTED, \C.required () ); - endspecify - - if (PREG == 0 && MREG == 0 && ADREG == 0 && DREG == 0) - specify - (D *> P) = \D.P.comb (); - (D *> PCOUT) = \D.PCOUT.comb (); - endspecify - else - specify - $setup(D, posedge CLK &&& !IS_CLK_INVERTED, \D.required () ); - $setup(D, negedge CLK &&& IS_CLK_INVERTED, \D.required () ); - endspecify - - if (PREG == 0) - specify - (PCIN *> P) = 1107; - (PCIN *> PCOUT) = 1255; - endspecify - else - specify - $setup(PCIN, posedge CLK &&& !IS_CLK_INVERTED, USE_PATTERN_DETECT != "NO_PATDET" ? 1315 : 1025); - $setup(PCIN, negedge CLK &&& IS_CLK_INVERTED, USE_PATTERN_DETECT != "NO_PATDET" ? 1315 : 1025); - endspecify - - if (PREG || AREG || ADREG || BREG || CREG || DREG || MREG) - specify - if (!IS_CLK_INVERTED && CEP) (posedge CLK => (P : 48'bx)) = \P.arrival () ; - if ( IS_CLK_INVERTED && CEP) (negedge CLK => (P : 48'bx)) = \P.arrival () ; - if (!IS_CLK_INVERTED && CEP) (posedge CLK => (PCOUT : 48'bx)) = \PCOUT.arrival () ; - if ( IS_CLK_INVERTED && CEP) (negedge CLK => (PCOUT : 48'bx)) = \PCOUT.arrival () ; - endspecify - endgenerate -`endif - initial begin -`ifndef YOSYS +`ifdef __ICARUS__ if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value"); if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value"); if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value"); @@ -3509,10 +2046,10 @@ module DSP48E1 ( reg signed [24:0] Dr; reg signed [17:0] Br1, Br2; reg signed [47:0] Cr; - reg [4:0] INMODEr; - reg [6:0] OPMODEr; - reg [3:0] ALUMODEr; - reg [2:0] CARRYINSELr; + reg [4:0] INMODEr = 5'b0; + reg [6:0] OPMODEr = 7'b0; + reg [3:0] ALUMODEr = 4'b0; + reg [2:0] CARRYINSELr = 3'b0; generate // Configurable A register @@ -3556,8 +2093,8 @@ module DSP48E1 ( if (CEB2) Br2 <= Br1; end end else if (BREG == 1) begin - //initial Br1 = 18'b0; - initial Br2 = 18'b0; + //initial Br1 = 25'b0; + initial Br2 = 25'b0; always @(posedge CLK) if (RSTB) begin Br1 <= 18'b0; @@ -3604,7 +2141,7 @@ module DSP48E1 ( endgenerate // A/D input selection and pre-adder - wire signed [24:0] Ar12_muxed = INMODEr[0] ? Ar1 : Ar2; + wire signed [29:0] Ar12_muxed = INMODEr[0] ? Ar1 : Ar2; wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed; wire signed [24:0] Dr_gated = INMODEr[2] ? Dr : 25'b0; wire signed [24:0] AD_result = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated); @@ -3644,12 +2181,12 @@ module DSP48E1 ( case (OPMODEr[1:0]) 2'b00: X = 48'b0; 2'b01: begin X = $signed(Mrx); -`ifndef YOSYS +`ifdef __ICARUS__ if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01"); `endif end 2'b10: begin X = P; -`ifndef YOSYS +`ifdef __ICARUS__ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10"); `endif end @@ -3661,7 +2198,7 @@ module DSP48E1 ( case (OPMODEr[3:2]) 2'b00: Y = 48'b0; 2'b01: begin Y = 48'b0; // FIXME: more accurate partial product modelling? -`ifndef YOSYS +`ifdef __ICARUS__ if (OPMODEr[1:0] != 2'b01) $fatal(1, "OPMODEr[1:0] must be 2'b01 when OPMODEr[3:2] is 2'b01"); `endif end @@ -3675,13 +2212,13 @@ module DSP48E1 ( 3'b000: Z = 48'b0; 3'b001: Z = PCIN; 3'b010: begin Z = P; -`ifndef YOSYS +`ifdef __ICARUS__ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010"); `endif end 3'b011: Z = Cr; 3'b100: begin Z = P; -`ifndef YOSYS +`ifdef __ICARUS__ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100"); if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100"); `endif @@ -3694,13 +2231,11 @@ module DSP48E1 ( // Carry in wire A24_xnor_B17d = A_MULT[24] ~^ B_MULT[17]; - reg CARRYINr, A24_xnor_B17; + reg CARRYINr = 1'b0, A24_xnor_B17 = 1'b0; generate - if (CARRYINREG == 1) initial CARRYINr = 1'b0; if (CARRYINREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) CARRYINr <= 1'b0; else if (CECARRYIN) CARRYINr <= CARRYIN; end else always @* CARRYINr = CARRYIN; - if (MREG == 1) initial A24_xnor_B17 = 1'b0; if (MREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) A24_xnor_B17 <= 1'b0; else if (CEM) A24_xnor_B17 <= A24_xnor_B17d; end else always @* A24_xnor_B17 = A24_xnor_B17d; endgenerate @@ -3864,448 +2399,3 @@ module DSP48E1 ( endmodule // TODO: DSP48E2 (Ultrascale). - -// Block RAM - -module RAMB18E1 ( - (* clkbuf_sink *) - (* invertible_pin = "IS_CLKARDCLK_INVERTED" *) - input CLKARDCLK, - (* clkbuf_sink *) - (* invertible_pin = "IS_CLKBWRCLK_INVERTED" *) - input CLKBWRCLK, - (* invertible_pin = "IS_ENARDEN_INVERTED" *) - input ENARDEN, - (* invertible_pin = "IS_ENBWREN_INVERTED" *) - input ENBWREN, - input REGCEAREGCE, - input REGCEB, - (* invertible_pin = "IS_RSTRAMARSTRAM_INVERTED" *) - input RSTRAMARSTRAM, - (* invertible_pin = "IS_RSTRAMB_INVERTED" *) - input RSTRAMB, - (* invertible_pin = "IS_RSTREGARSTREG_INVERTED" *) - input RSTREGARSTREG, - (* invertible_pin = "IS_RSTREGB_INVERTED" *) - input RSTREGB, - input [13:0] ADDRARDADDR, - input [13:0] ADDRBWRADDR, - input [15:0] DIADI, - input [15:0] DIBDI, - input [1:0] DIPADIP, - input [1:0] DIPBDIP, - input [1:0] WEA, - input [3:0] WEBWE, - output [15:0] DOADO, - output [15:0] DOBDO, - output [1:0] DOPADOP, - output [1:0] DOPBDOP -); - parameter integer DOA_REG = 0; - parameter integer DOB_REG = 0; - parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_A = 18'h0; - parameter INIT_B = 18'h0; - parameter INIT_FILE = "NONE"; - parameter RAM_MODE = "TDP"; - parameter RDADDR_COLLISION_HWCONFIG = "DELAYED_WRITE"; - parameter integer READ_WIDTH_A = 0; - parameter integer READ_WIDTH_B = 0; - parameter RSTREG_PRIORITY_A = "RSTREG"; - parameter RSTREG_PRIORITY_B = "RSTREG"; - parameter SIM_COLLISION_CHECK = "ALL"; - parameter SIM_DEVICE = "VIRTEX6"; - parameter SRVAL_A = 18'h0; - parameter SRVAL_B = 18'h0; - parameter WRITE_MODE_A = "WRITE_FIRST"; - parameter WRITE_MODE_B = "WRITE_FIRST"; - parameter integer WRITE_WIDTH_A = 0; - parameter integer WRITE_WIDTH_B = 0; - parameter IS_CLKARDCLK_INVERTED = 1'b0; - parameter IS_CLKBWRCLK_INVERTED = 1'b0; - parameter IS_ENARDEN_INVERTED = 1'b0; - parameter IS_ENBWREN_INVERTED = 1'b0; - parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0; - parameter IS_RSTRAMB_INVERTED = 1'b0; - parameter IS_RSTREGARSTREG_INVERTED = 1'b0; - parameter IS_RSTREGB_INVERTED = 1'b0; - - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L13 - $setup(ADDRARDADDR, posedge CLKARDCLK, 566); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L17 - $setup(ADDRBWRADDR, posedge CLKBWRCLK, 566); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L19 - $setup(WEA, posedge CLKARDCLK, 532); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L21 - $setup(WEBWE, posedge CLKBWRCLK, 532); - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L29 - $setup(REGCEAREGCE, posedge CLKARDCLK, 360); - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L31 - $setup(RSTREGARSTREG, posedge CLKARDCLK, 342); - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L49 - $setup(REGCEB, posedge CLKBWRCLK, 360); - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L59 - $setup(RSTREGB, posedge CLKBWRCLK, 342); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L123 - $setup(DIADI, posedge CLKARDCLK, 737); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L133 - $setup(DIBDI, posedge CLKBWRCLK, 737); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L125 - $setup(DIPADIP, posedge CLKARDCLK, 737); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L135 - $setup(DIPBDIP, posedge CLKBWRCLK, 737); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L143 - if (&DOA_REG) (posedge CLKARDCLK => (DOADO : 16'bx)) = 2454; - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L144 - if (&DOA_REG) (posedge CLKARDCLK => (DOPADOP : 2'bx)) = 2454; - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L153 - if (|DOA_REG) (posedge CLKARDCLK => (DOADO : 16'bx)) = 882; - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L154 - if (|DOA_REG) (posedge CLKARDCLK => (DOPADOP : 2'bx)) = 882; - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L163 - if (&DOB_REG) (posedge CLKBWRCLK => (DOBDO : 16'bx)) = 2454; - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L164 - if (&DOB_REG) (posedge CLKBWRCLK => (DOPBDOP : 2'bx)) = 2454; - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L173 - if (|DOB_REG) (posedge CLKBWRCLK => (DOBDO : 16'bx)) = 882; - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L174 - if (|DOB_REG) (posedge CLKBWRCLK => (DOPBDOP : 2'bx)) = 882; - endspecify -endmodule - -module RAMB36E1 ( - output CASCADEOUTA, - output CASCADEOUTB, - output [31:0] DOADO, - output [31:0] DOBDO, - output [3:0] DOPADOP, - output [3:0] DOPBDOP, - output [7:0] ECCPARITY, - output [8:0] RDADDRECC, - output SBITERR, - output DBITERR, - (* invertible_pin = "IS_ENARDEN_INVERTED" *) - input ENARDEN, - (* clkbuf_sink *) - (* invertible_pin = "IS_CLKARDCLK_INVERTED" *) - input CLKARDCLK, - (* invertible_pin = "IS_RSTRAMARSTRAM_INVERTED" *) - input RSTRAMARSTRAM, - (* invertible_pin = "IS_RSTREGARSTREG_INVERTED" *) - input RSTREGARSTREG, - input CASCADEINA, - input REGCEAREGCE, - (* invertible_pin = "IS_ENBWREN_INVERTED" *) - input ENBWREN, - (* clkbuf_sink *) - (* invertible_pin = "IS_CLKBWRCLK_INVERTED" *) - input CLKBWRCLK, - (* invertible_pin = "IS_RSTRAMB_INVERTED" *) - input RSTRAMB, - (* invertible_pin = "IS_RSTREGB_INVERTED" *) - input RSTREGB, - input CASCADEINB, - input REGCEB, - input INJECTDBITERR, - input INJECTSBITERR, - input [15:0] ADDRARDADDR, - input [15:0] ADDRBWRADDR, - input [31:0] DIADI, - input [31:0] DIBDI, - input [3:0] DIPADIP, - input [3:0] DIPBDIP, - input [3:0] WEA, - input [7:0] WEBWE -); - parameter integer DOA_REG = 0; - parameter integer DOB_REG = 0; - parameter EN_ECC_READ = "FALSE"; - parameter EN_ECC_WRITE = "FALSE"; - parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_40 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_41 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_42 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_43 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_44 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_45 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_46 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_47 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_48 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_49 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_50 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_51 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_52 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_53 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_54 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_55 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_56 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_57 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_58 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_59 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_60 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_61 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_62 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_63 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_64 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_65 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_66 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_67 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_68 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_69 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_70 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_71 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_72 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_73 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_74 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_75 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_76 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_77 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_78 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_79 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_A = 36'h0; - parameter INIT_B = 36'h0; - parameter INIT_FILE = "NONE"; - parameter RAM_EXTENSION_A = "NONE"; - parameter RAM_EXTENSION_B = "NONE"; - parameter RAM_MODE = "TDP"; - parameter RDADDR_COLLISION_HWCONFIG = "DELAYED_WRITE"; - parameter integer READ_WIDTH_A = 0; - parameter integer READ_WIDTH_B = 0; - parameter RSTREG_PRIORITY_A = "RSTREG"; - parameter RSTREG_PRIORITY_B = "RSTREG"; - parameter SIM_COLLISION_CHECK = "ALL"; - parameter SIM_DEVICE = "VIRTEX6"; - parameter SRVAL_A = 36'h0; - parameter SRVAL_B = 36'h0; - parameter WRITE_MODE_A = "WRITE_FIRST"; - parameter WRITE_MODE_B = "WRITE_FIRST"; - parameter integer WRITE_WIDTH_A = 0; - parameter integer WRITE_WIDTH_B = 0; - parameter IS_CLKARDCLK_INVERTED = 1'b0; - parameter IS_CLKBWRCLK_INVERTED = 1'b0; - parameter IS_ENARDEN_INVERTED = 1'b0; - parameter IS_ENBWREN_INVERTED = 1'b0; - parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0; - parameter IS_RSTRAMB_INVERTED = 1'b0; - parameter IS_RSTREGARSTREG_INVERTED = 1'b0; - parameter IS_RSTREGB_INVERTED = 1'b0; - - specify - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L13 - $setup(ADDRARDADDR, posedge CLKARDCLK, 566); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L17 - $setup(ADDRBWRADDR, posedge CLKBWRCLK, 566); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L19 - $setup(WEA, posedge CLKARDCLK, 532); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L21 - $setup(WEBWE, posedge CLKBWRCLK, 532); - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L29 - $setup(REGCEAREGCE, posedge CLKARDCLK, 360); - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L31 - $setup(RSTREGARSTREG, posedge CLKARDCLK, 342); - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L49 - $setup(REGCEB, posedge CLKBWRCLK, 360); - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L59 - $setup(RSTREGB, posedge CLKBWRCLK, 342); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L123 - $setup(DIADI, posedge CLKARDCLK, 737); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L133 - $setup(DIBDI, posedge CLKBWRCLK, 737); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L125 - $setup(DIPADIP, posedge CLKARDCLK, 737); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L135 - $setup(DIPBDIP, posedge CLKBWRCLK, 737); - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L143 - if (&DOA_REG) (posedge CLKARDCLK => (DOADO : 32'bx)) = 2454; - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L144 - if (&DOA_REG) (posedge CLKARDCLK => (DOPADOP : 4'bx)) = 2454; - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L153 - if (|DOA_REG) (posedge CLKARDCLK => (DOADO : 32'bx)) = 882; - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L154 - if (|DOA_REG) (posedge CLKARDCLK => (DOPADOP : 4'bx)) = 882; - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L163 - if (&DOB_REG) (posedge CLKBWRCLK => (DOBDO : 32'bx)) = 2454; - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L164 - if (&DOB_REG) (posedge CLKBWRCLK => (DOPBDOP : 4'bx)) = 2454; - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L173 - if (|DOB_REG) (posedge CLKBWRCLK => (DOBDO : 32'bx)) = 882; - // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/BRAM_L.sdf#L174 - if (|DOB_REG) (posedge CLKBWRCLK => (DOPBDOP : 4'bx)) = 882; - endspecify -endmodule - diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py index f086291ab2d..e4c580b9d8b 100644 --- a/techlibs/xilinx/cells_xtra.py +++ b/techlibs/xilinx/cells_xtra.py @@ -65,9 +65,9 @@ def __init__(self, name, keep=False, port_attrs={}): # CLB -- registers/latches. # Virtex 1/2/4/5, Spartan 3. - # Cell('FDCPE', port_attrs={'C': ['clkbuf_sink']}), - # Cell('FDRSE', port_attrs={'C': ['clkbuf_sink']}), - # Cell('LDCPE', port_attrs={'C': ['clkbuf_sink']}), + Cell('FDCPE', port_attrs={'C': ['clkbuf_sink']}), + Cell('FDRSE', port_attrs={'C': ['clkbuf_sink']}), + Cell('LDCPE', port_attrs={'C': ['clkbuf_sink']}), # Virtex 6, Spartan 6, Series 7, Ultrascale. # Cell('FDCE'), # Cell('FDPE'), @@ -75,8 +75,8 @@ def __init__(self, name, keep=False, port_attrs={}): # Cell('FDSE'), # Cell('LDCE'), # Cell('LDPE'), - # Cell('AND2B1L'), - # Cell('OR2L'), + Cell('AND2B1L'), + Cell('OR2L'), # CLB -- other. # Cell('LUT1'), @@ -86,23 +86,23 @@ def __init__(self, name, keep=False, port_attrs={}): # Cell('LUT5'), # Cell('LUT6'), # Cell('LUT6_2'), - # Cell('MUXF5'), - # Cell('MUXF6'), + Cell('MUXF5'), + Cell('MUXF6'), # Cell('MUXF7'), # Cell('MUXF8'), - # Cell('MUXF9'), + Cell('MUXF9'), # Cell('CARRY4'), - # Cell('CARRY8'), + Cell('CARRY8'), # Cell('MUXCY'), # Cell('XORCY'), - # Cell('ORCY'), - # Cell('MULT_AND'), - # Cell('SRL16', port_attrs={'CLK': ['clkbuf_sink']}), + Cell('ORCY'), + Cell('MULT_AND'), + Cell('SRL16', port_attrs={'CLK': ['clkbuf_sink']}), # Cell('SRL16E', port_attrs={'CLK': ['clkbuf_sink']}), - # Cell('SRLC16', port_attrs={'CLK': ['clkbuf_sink']}), + Cell('SRLC16', port_attrs={'CLK': ['clkbuf_sink']}), # Cell('SRLC16E', port_attrs={'CLK': ['clkbuf_sink']}), # Cell('SRLC32E', port_attrs={'CLK': ['clkbuf_sink']}), - # Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}), + Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}), # Block RAM. # Virtex. @@ -144,9 +144,23 @@ def __init__(self, name, keep=False, port_attrs={}): Cell('RAMB16BWE_S36_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16BWE_S36_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), # Spartan 3A DSP. - Cell('RAMB16BWER', port_attrs={ 'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), + Cell('RAMB16BWER', port_attrs={ + 'CLKA': ['clkbuf_sink'], + 'CLKB': ['clkbuf_sink'], + #'DOA': ['abc9_arrival='], + #'DOB': ['abc9_arrival='], + #'DOPA': ['abc9_arrival='], + #'DOPB': ['abc9_arrival='], + }), # Spartan 6 (in addition to above). - Cell('RAMB8BWER', port_attrs={ 'CLKAWRCLK': ['clkbuf_sink'], 'CLKBRDCLK': ['clkbuf_sink']}), + Cell('RAMB8BWER', port_attrs={ + 'CLKAWRCLK': ['clkbuf_sink'], + 'CLKBRDCLK': ['clkbuf_sink'], + #'DOADO': ['abc9_arrival='], + #'DOBDO': ['abc9_arrival='], + #'DOPADOP': ['abc9_arrival='], + #'DOPBDOP': ['abc9_arrival='], + }), # Virtex 4. Cell('FIFO16', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('RAMB16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), @@ -163,8 +177,22 @@ def __init__(self, name, keep=False, port_attrs={}): # Virtex 6 / Series 7. Cell('FIFO18E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('FIFO36E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), - #Cell('RAMB18E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']]}), - #Cell('RAMB36E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']]}), + Cell('RAMB18E1', port_attrs={ + 'CLKARDCLK': ['clkbuf_sink'], + 'CLKBWRCLK': ['clkbuf_sink'], + 'DOADO': ['abc9_arrival=2454'], + 'DOBDO': ['abc9_arrival=2454'], + 'DOPADOP': ['abc9_arrival=2454'], + 'DOPBDOP': ['abc9_arrival=2454'], + }), + Cell('RAMB36E1', port_attrs={ + 'CLKARDCLK': ['clkbuf_sink'], + 'CLKBWRCLK': ['clkbuf_sink'], + 'DOADO': ['abc9_arrival=2454'], + 'DOBDO': ['abc9_arrival=2454'], + 'DOPADOP': ['abc9_arrival=2454'], + 'DOPBDOP': ['abc9_arrival=2454'], + }), # Ultrascale. Cell('FIFO18E2', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('FIFO36E2', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), @@ -181,7 +209,7 @@ def __init__(self, name, keep=False, port_attrs={}): # Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E # Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP # Cell('DSP48A1', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 6 - # Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4 + Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4 Cell('DSP48E', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 5 #Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 6 / Series 7 Cell('DSP48E2', port_attrs={'CLK': ['clkbuf_sink']}), # Ultrascale @@ -302,13 +330,13 @@ def __init__(self, name, keep=False, port_attrs={}): Cell('IOBUF_DCIEN', port_attrs={'IO': ['iopad_external_pin']}), Cell('IOBUF_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin']}), Cell('IOBUFE3', port_attrs={'IO': ['iopad_external_pin']}), - Cell('IOBUFDS', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), + Cell('IOBUFDS', port_attrs={'IO': ['iopad_external_pin']}), Cell('IOBUFDS_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDS_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDS_DIFF_OUT', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDS_DIFF_OUT_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), - Cell('IOBUFDSE3', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), + Cell('IOBUFDSE3', port_attrs={'IO': ['iopad_external_pin']}), # Output. # Cell('OBUF', port_attrs={'O': ['iopad_external_pin']}), Cell('OBUFDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index 3021f6b5a0a..8ac596459c1 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -1,5 +1,165 @@ // Created by cells_xtra.py from Xilinx models +module FDCPE (...); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_CLR_INVERTED = 1'b0; + parameter [0:0] IS_PRE_INVERTED = 1'b0; + output Q; + (* clkbuf_sink *) + (* invertible_pin = "IS_C_INVERTED" *) + input C; + input CE; + (* invertible_pin = "IS_CLR_INVERTED" *) + input CLR; + input D; + (* invertible_pin = "IS_PRE_INVERTED" *) + input PRE; +endmodule + +module FDRSE (...); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_CE_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_R_INVERTED = 1'b0; + parameter [0:0] IS_S_INVERTED = 1'b0; + output Q; + (* clkbuf_sink *) + (* invertible_pin = "IS_C_INVERTED" *) + input C; + (* invertible_pin = "IS_CE_INVERTED" *) + input CE; + (* invertible_pin = "IS_D_INVERTED" *) + input D; + (* invertible_pin = "IS_R_INVERTED" *) + input R; + (* invertible_pin = "IS_S_INVERTED" *) + input S; +endmodule + +module LDCPE (...); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_CLR_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_G_INVERTED = 1'b0; + parameter [0:0] IS_GE_INVERTED = 1'b0; + parameter [0:0] IS_PRE_INVERTED = 1'b0; + output Q; + (* invertible_pin = "IS_CLR_INVERTED" *) + input CLR; + (* invertible_pin = "IS_D_INVERTED" *) + input D; + (* invertible_pin = "IS_G_INVERTED" *) + input G; + (* invertible_pin = "IS_GE_INVERTED" *) + input GE; + (* invertible_pin = "IS_PRE_INVERTED" *) + input PRE; +endmodule + +module AND2B1L (...); + parameter [0:0] IS_SRI_INVERTED = 1'b0; + output O; + input DI; + (* invertible_pin = "IS_SRI_INVERTED" *) + input SRI; +endmodule + +module OR2L (...); + parameter [0:0] IS_SRI_INVERTED = 1'b0; + output O; + input DI; + (* invertible_pin = "IS_SRI_INVERTED" *) + input SRI; +endmodule + +module MUXF5 (...); + output O; + input I0; + input I1; + input S; +endmodule + +module MUXF6 (...); + output O; + input I0; + input I1; + input S; +endmodule + +module MUXF9 (...); + output O; + input I0; + input I1; + input S; +endmodule + +module CARRY8 (...); + parameter CARRY_TYPE = "SINGLE_CY8"; + output [7:0] CO; + output [7:0] O; + input CI; + input CI_TOP; + input [7:0] DI; + input [7:0] S; +endmodule + +module ORCY (...); + output O; + input CI; + input I; +endmodule + +module MULT_AND (...); + output LO; + input I0; + input I1; +endmodule + +module SRL16 (...); + parameter [15:0] INIT = 16'h0000; + output Q; + input A0; + input A1; + input A2; + input A3; + (* clkbuf_sink *) + input CLK; + input D; +endmodule + +module SRLC16 (...); + parameter [15:0] INIT = 16'h0000; + output Q; + output Q15; + input A0; + input A1; + input A2; + input A3; + (* clkbuf_sink *) + input CLK; + input D; +endmodule + +module CFGLUT5 (...); + parameter [31:0] INIT = 32'h00000000; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + output CDO; + output O5; + output O6; + input I4; + input I3; + input I2; + input I1; + input I0; + input CDI; + input CE; + (* clkbuf_sink *) + (* invertible_pin = "IS_CLK_INVERTED" *) + input CLK; +endmodule + module RAMB16_S1 (...); parameter [0:0] INIT = 1'h0; parameter [0:0] SRVAL = 1'h0; @@ -4390,6 +4550,368 @@ module FIFO36E1 (...); input WREN; endmodule +module RAMB18E1 (...); + parameter integer DOA_REG = 0; + parameter integer DOB_REG = 0; + parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_A = 18'h0; + parameter INIT_B = 18'h0; + parameter INIT_FILE = "NONE"; + parameter RAM_MODE = "TDP"; + parameter RDADDR_COLLISION_HWCONFIG = "DELAYED_WRITE"; + parameter integer READ_WIDTH_A = 0; + parameter integer READ_WIDTH_B = 0; + parameter RSTREG_PRIORITY_A = "RSTREG"; + parameter RSTREG_PRIORITY_B = "RSTREG"; + parameter SIM_COLLISION_CHECK = "ALL"; + parameter SIM_DEVICE = "VIRTEX6"; + parameter SRVAL_A = 18'h0; + parameter SRVAL_B = 18'h0; + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + parameter integer WRITE_WIDTH_A = 0; + parameter integer WRITE_WIDTH_B = 0; + parameter IS_CLKARDCLK_INVERTED = 1'b0; + parameter IS_CLKBWRCLK_INVERTED = 1'b0; + parameter IS_ENARDEN_INVERTED = 1'b0; + parameter IS_ENBWREN_INVERTED = 1'b0; + parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0; + parameter IS_RSTRAMB_INVERTED = 1'b0; + parameter IS_RSTREGARSTREG_INVERTED = 1'b0; + parameter IS_RSTREGB_INVERTED = 1'b0; + (* abc9_arrival=2454 *) + output [15:0] DOADO; + (* abc9_arrival=2454 *) + output [15:0] DOBDO; + (* abc9_arrival=2454 *) + output [1:0] DOPADOP; + (* abc9_arrival=2454 *) + output [1:0] DOPBDOP; + (* clkbuf_sink *) + (* invertible_pin = "IS_CLKARDCLK_INVERTED" *) + input CLKARDCLK; + (* clkbuf_sink *) + (* invertible_pin = "IS_CLKBWRCLK_INVERTED" *) + input CLKBWRCLK; + (* invertible_pin = "IS_ENARDEN_INVERTED" *) + input ENARDEN; + (* invertible_pin = "IS_ENBWREN_INVERTED" *) + input ENBWREN; + input REGCEAREGCE; + input REGCEB; + (* invertible_pin = "IS_RSTRAMARSTRAM_INVERTED" *) + input RSTRAMARSTRAM; + (* invertible_pin = "IS_RSTRAMB_INVERTED" *) + input RSTRAMB; + (* invertible_pin = "IS_RSTREGARSTREG_INVERTED" *) + input RSTREGARSTREG; + (* invertible_pin = "IS_RSTREGB_INVERTED" *) + input RSTREGB; + input [13:0] ADDRARDADDR; + input [13:0] ADDRBWRADDR; + input [15:0] DIADI; + input [15:0] DIBDI; + input [1:0] DIPADIP; + input [1:0] DIPBDIP; + input [1:0] WEA; + input [3:0] WEBWE; +endmodule + +module RAMB36E1 (...); + parameter integer DOA_REG = 0; + parameter integer DOB_REG = 0; + parameter EN_ECC_READ = "FALSE"; + parameter EN_ECC_WRITE = "FALSE"; + parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_40 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_41 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_42 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_43 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_44 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_45 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_46 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_47 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_48 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_49 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_4A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_4B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_4C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_4D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_4E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_4F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_50 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_51 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_52 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_53 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_54 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_55 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_56 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_57 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_58 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_59 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_5A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_5B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_5C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_5D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_5E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_5F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_60 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_61 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_62 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_63 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_64 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_65 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_66 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_67 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_68 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_69 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_6A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_6B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_6C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_6D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_6E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_6F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_70 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_71 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_72 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_73 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_74 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_75 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_76 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_77 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_78 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_79 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_7A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_7B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_7C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_7D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_7E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_7F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_A = 36'h0; + parameter INIT_B = 36'h0; + parameter INIT_FILE = "NONE"; + parameter RAM_EXTENSION_A = "NONE"; + parameter RAM_EXTENSION_B = "NONE"; + parameter RAM_MODE = "TDP"; + parameter RDADDR_COLLISION_HWCONFIG = "DELAYED_WRITE"; + parameter integer READ_WIDTH_A = 0; + parameter integer READ_WIDTH_B = 0; + parameter RSTREG_PRIORITY_A = "RSTREG"; + parameter RSTREG_PRIORITY_B = "RSTREG"; + parameter SIM_COLLISION_CHECK = "ALL"; + parameter SIM_DEVICE = "VIRTEX6"; + parameter SRVAL_A = 36'h0; + parameter SRVAL_B = 36'h0; + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + parameter integer WRITE_WIDTH_A = 0; + parameter integer WRITE_WIDTH_B = 0; + parameter IS_CLKARDCLK_INVERTED = 1'b0; + parameter IS_CLKBWRCLK_INVERTED = 1'b0; + parameter IS_ENARDEN_INVERTED = 1'b0; + parameter IS_ENBWREN_INVERTED = 1'b0; + parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0; + parameter IS_RSTRAMB_INVERTED = 1'b0; + parameter IS_RSTREGARSTREG_INVERTED = 1'b0; + parameter IS_RSTREGB_INVERTED = 1'b0; + output CASCADEOUTA; + output CASCADEOUTB; + (* abc9_arrival=2454 *) + output [31:0] DOADO; + (* abc9_arrival=2454 *) + output [31:0] DOBDO; + (* abc9_arrival=2454 *) + output [3:0] DOPADOP; + (* abc9_arrival=2454 *) + output [3:0] DOPBDOP; + output [7:0] ECCPARITY; + output [8:0] RDADDRECC; + output SBITERR; + output DBITERR; + (* invertible_pin = "IS_ENARDEN_INVERTED" *) + input ENARDEN; + (* clkbuf_sink *) + (* invertible_pin = "IS_CLKARDCLK_INVERTED" *) + input CLKARDCLK; + (* invertible_pin = "IS_RSTRAMARSTRAM_INVERTED" *) + input RSTRAMARSTRAM; + (* invertible_pin = "IS_RSTREGARSTREG_INVERTED" *) + input RSTREGARSTREG; + input CASCADEINA; + input REGCEAREGCE; + (* invertible_pin = "IS_ENBWREN_INVERTED" *) + input ENBWREN; + (* clkbuf_sink *) + (* invertible_pin = "IS_CLKBWRCLK_INVERTED" *) + input CLKBWRCLK; + (* invertible_pin = "IS_RSTRAMB_INVERTED" *) + input RSTRAMB; + (* invertible_pin = "IS_RSTREGB_INVERTED" *) + input RSTREGB; + input CASCADEINB; + input REGCEB; + input INJECTDBITERR; + input INJECTSBITERR; + input [15:0] ADDRARDADDR; + input [15:0] ADDRBWRADDR; + input [31:0] DIADI; + input [31:0] DIBDI; + input [3:0] DIPADIP; + input [3:0] DIPBDIP; + input [3:0] WEA; + input [7:0] WEBWE; +endmodule + module FIFO18E2 (...); parameter CASCADE_ORDER = "NONE"; parameter CLOCK_DOMAINS = "INDEPENDENT"; @@ -5114,6 +5636,49 @@ module URAM288_BASE (...); input SLEEP; endmodule +module DSP48 (...); + parameter integer AREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter LEGACY_MODE = "MULT18X18S"; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter integer SUBTRACTREG = 1; + output [17:0] BCOUT; + output [47:0] P; + output [47:0] PCOUT; + input [17:0] A; + input [17:0] B; + input [17:0] BCIN; + input [47:0] C; + input CARRYIN; + input [1:0] CARRYINSEL; + input CEA; + input CEB; + input CEC; + input CECARRYIN; + input CECINSUB; + input CECTRL; + input CEM; + input CEP; + (* clkbuf_sink *) + input CLK; + input [6:0] OPMODE; + input [47:0] PCIN; + input RSTA; + input RSTB; + input RSTC; + input RSTCARRYIN; + input RSTCTRL; + input RSTM; + input RSTP; + input SUBTRACT; +endmodule + module DSP48E (...); parameter SIM_MODE = "SAFE"; parameter integer ACASCREG = 1; @@ -7072,7 +7637,6 @@ module IOBUFDS (...); output O; (* iopad_external_pin *) inout IO; - (* iopad_external_pin *) inout IOB; input I; input T; @@ -7182,7 +7746,6 @@ module IOBUFDSE3 (...); output O; (* iopad_external_pin *) inout IO; - (* iopad_external_pin *) inout IOB; input DCITERMDISABLE; input I; diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v index 2ab6075f150..62d501632c9 100644 --- a/techlibs/xilinx/lut_map.v +++ b/techlibs/xilinx/lut_map.v @@ -26,71 +26,93 @@ module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; - (* force_downto *) input [WIDTH-1:0] A; output Y; + // Need to swap input ordering, and fix init accordingly, + // to match ABC's expectation of LUT inputs in non-decreasing + // delay order + function [WIDTH-1:0] permute_index; + input [WIDTH-1:0] i; + integer j; + begin + permute_index = 0; + for (j = 0; j < WIDTH; j = j + 1) + permute_index[WIDTH-1 - j] = i[j]; + end + endfunction + + function [2**WIDTH-1:0] permute_init; + input [2**WIDTH-1:0] orig; + integer i; + begin + permute_init = 0; + for (i = 0; i < 2**WIDTH; i = i + 1) + permute_init[i] = orig[permute_index(i)]; + end + endfunction + + parameter [2**WIDTH-1:0] P_LUT = permute_init(LUT); + generate if (WIDTH == 1) begin - if (LUT == 2'b01) begin + if (P_LUT == 2'b01) begin INV _TECHMAP_REPLACE_ (.O(Y), .I(A[0])); end else begin - LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + LUT1 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0])); end end else if (WIDTH == 2) begin - LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1])); + LUT2 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[1]), .I1(A[0])); end else if (WIDTH == 3) begin - LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2])); + LUT3 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[2]), .I1(A[1]), .I2(A[0])); end else if (WIDTH == 4) begin - LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3])); - end else - if (WIDTH == 5 && WIDTH <= `LUT_WIDTH) begin - LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4])); + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[3]), .I1(A[2]), .I2(A[1]), + .I3(A[0])); end else - if (WIDTH == 6 && WIDTH <= `LUT_WIDTH) begin - LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); + if (WIDTH == 5) begin + LUT5 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[4]), .I1(A[3]), .I2(A[2]), + .I3(A[1]), .I4(A[0])); end else - if (WIDTH == 5 && WIDTH > `LUT_WIDTH) begin - wire f0, f1; - \$lut #(.LUT(LUT[15: 0]), .WIDTH(4)) lut0 (.A(A[3:0]), .Y(f0)); - \$lut #(.LUT(LUT[31:16]), .WIDTH(4)) lut1 (.A(A[3:0]), .Y(f1)); - MUXF5 mux5(.I0(f0), .I1(f1), .S(A[4]), .O(Y)); - end else - if (WIDTH == 6 && WIDTH > `LUT_WIDTH) begin - wire f0, f1; - \$lut #(.LUT(LUT[31: 0]), .WIDTH(5)) lut0 (.A(A[4:0]), .Y(f0)); - \$lut #(.LUT(LUT[63:32]), .WIDTH(5)) lut1 (.A(A[4:0]), .Y(f1)); - MUXF6 mux6(.I0(f0), .I1(f1), .S(A[5]), .O(Y)); + if (WIDTH == 6) begin + LUT6 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); end else if (WIDTH == 7) begin - wire f0, f1; - \$lut #(.LUT(LUT[ 63: 0]), .WIDTH(6)) lut0 (.A(A[5:0]), .Y(f0)); - \$lut #(.LUT(LUT[127:64]), .WIDTH(6)) lut1 (.A(A[5:0]), .Y(f1)); - MUXF7 mux7(.I0(f0), .I1(f1), .S(A[6]), .O(Y)); + wire T0, T1; + LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), + .I0(A[6]), .I1(A[5]), .I2(A[4]), + .I3(A[3]), .I4(A[2]), .I5(A[1])); + LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), + .I0(A[6]), .I1(A[5]), .I2(A[4]), + .I3(A[3]), .I4(A[2]), .I5(A[1])); + MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[0])); end else if (WIDTH == 8) begin - wire f0, f1; - \$lut #(.LUT(LUT[127: 0]), .WIDTH(7)) lut0 (.A(A[6:0]), .Y(f0)); - \$lut #(.LUT(LUT[255:128]), .WIDTH(7)) lut1 (.A(A[6:0]), .Y(f1)); - MUXF8 mux8(.I0(f0), .I1(f1), .S(A[7]), .O(Y)); - end else - if (WIDTH == 9) begin - wire f0, f1; - \$lut #(.LUT(LUT[255: 0]), .WIDTH(8)) lut0 (.A(A[7:0]), .Y(f0)); - \$lut #(.LUT(LUT[511:256]), .WIDTH(8)) lut1 (.A(A[7:0]), .Y(f1)); - MUXF9 mux9(.I0(f0), .I1(f1), .S(A[8]), .O(Y)); + wire T0, T1, T2, T3, T4, T5; + LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), + .I0(A[7]), .I1(A[6]), .I2(A[5]), + .I3(A[4]), .I4(A[3]), .I5(A[2])); + LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), + .I0(A[7]), .I1(A[6]), .I2(A[5]), + .I3(A[4]), .I4(A[3]), .I5(A[2])); + LUT6 #(.INIT(P_LUT[191:128])) fpga_lut_2 (.O(T2), + .I0(A[7]), .I1(A[6]), .I2(A[5]), + .I3(A[4]), .I4(A[3]), .I5(A[2])); + LUT6 #(.INIT(P_LUT[255:192])) fpga_lut_3 (.O(T3), + .I0(A[7]), .I1(A[6]), .I2(A[5]), + .I3(A[4]), .I4(A[3]), .I5(A[2])); + MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[1])); + MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[1])); + MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[0])); end else begin wire _TECHMAP_FAIL_ = 1; end diff --git a/techlibs/xilinx/lut6_lutrams.txt b/techlibs/xilinx/lutrams.txt similarity index 100% rename from techlibs/xilinx/lut6_lutrams.txt rename to techlibs/xilinx/lutrams.txt diff --git a/techlibs/xilinx/lutrams_map.v b/techlibs/xilinx/lutrams_map.v index 3ac1143bbd6..77041ca86f9 100644 --- a/techlibs/xilinx/lutrams_map.v +++ b/techlibs/xilinx/lutrams_map.v @@ -1,36 +1,4 @@ -module \$__XILINX_RAM16X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); - parameter [15:0] INIT = 16'bx; - parameter CLKPOL2 = 1; - input CLK1; - - input [3:0] A1ADDR; - output A1DATA; - - input [3:0] B1ADDR; - input B1DATA; - input B1EN; - - RAM16X1D #( - .INIT(INIT), - .IS_WCLK_INVERTED(!CLKPOL2) - ) _TECHMAP_REPLACE_ ( - .DPRA0(A1ADDR[0]), - .DPRA1(A1ADDR[1]), - .DPRA2(A1ADDR[2]), - .DPRA3(A1ADDR[3]), - .DPO(A1DATA), - - .A0(B1ADDR[0]), - .A1(B1ADDR[1]), - .A2(B1ADDR[2]), - .A3(B1ADDR[3]), - .D(B1DATA), - .WCLK(CLK1), - .WE(B1EN) - ); -endmodule - module \$__XILINX_RAM32X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); parameter [31:0] INIT = 32'bx; parameter CLKPOL2 = 1; @@ -127,153 +95,3 @@ module \$__XILINX_RAM128X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); ); endmodule - -module \$__XILINX_RAM32X6SDP (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); - parameter [32*6-1:0] INIT = {32*6{1'bx}}; - parameter CLKPOL2 = 1; - input CLK1; - - input [4:0] A1ADDR; - output [5:0] A1DATA; - - input [4:0] B1ADDR; - input [5:0] B1DATA; - input B1EN; - - wire [1:0] DOD_unused; - - RAM32M #( - .INIT_A({INIT[187:186], INIT[181:180], INIT[175:174], INIT[169:168], INIT[163:162], INIT[157:156], INIT[151:150], INIT[145:144], INIT[139:138], INIT[133:132], INIT[127:126], INIT[121:120], INIT[115:114], INIT[109:108], INIT[103:102], INIT[ 97: 96], INIT[ 91: 90], INIT[ 85: 84], INIT[ 79: 78], INIT[ 73: 72], INIT[ 67: 66], INIT[ 61: 60], INIT[ 55: 54], INIT[ 49: 48], INIT[ 43: 42], INIT[ 37: 36], INIT[ 31: 30], INIT[ 25: 24], INIT[ 19: 18], INIT[ 13: 12], INIT[ 7: 6], INIT[ 1: 0]}), - .INIT_B({INIT[189:188], INIT[183:182], INIT[177:176], INIT[171:170], INIT[165:164], INIT[159:158], INIT[153:152], INIT[147:146], INIT[141:140], INIT[135:134], INIT[129:128], INIT[123:122], INIT[117:116], INIT[111:110], INIT[105:104], INIT[ 99: 98], INIT[ 93: 92], INIT[ 87: 86], INIT[ 81: 80], INIT[ 75: 74], INIT[ 69: 68], INIT[ 63: 62], INIT[ 57: 56], INIT[ 51: 50], INIT[ 45: 44], INIT[ 39: 38], INIT[ 33: 32], INIT[ 27: 26], INIT[ 21: 20], INIT[ 15: 14], INIT[ 9: 8], INIT[ 3: 2]}), - .INIT_C({INIT[191:190], INIT[185:184], INIT[179:178], INIT[173:172], INIT[167:166], INIT[161:160], INIT[155:154], INIT[149:148], INIT[143:142], INIT[137:136], INIT[131:130], INIT[125:124], INIT[119:118], INIT[113:112], INIT[107:106], INIT[101:100], INIT[ 95: 94], INIT[ 89: 88], INIT[ 83: 82], INIT[ 77: 76], INIT[ 71: 70], INIT[ 65: 64], INIT[ 59: 58], INIT[ 53: 52], INIT[ 47: 46], INIT[ 41: 40], INIT[ 35: 34], INIT[ 29: 28], INIT[ 23: 22], INIT[ 17: 16], INIT[ 11: 10], INIT[ 5: 4]}), - .INIT_D(64'bx), - .IS_WCLK_INVERTED(!CLKPOL2) - ) _TECHMAP_REPLACE_ ( - .ADDRA(A1ADDR), - .ADDRB(A1ADDR), - .ADDRC(A1ADDR), - .DOA(A1DATA[1:0]), - .DOB(A1DATA[3:2]), - .DOC(A1DATA[5:4]), - .DOD(DOD_unused), - - .ADDRD(B1ADDR), - .DIA(B1DATA[1:0]), - .DIB(B1DATA[3:2]), - .DIC(B1DATA[5:4]), - .DID(2'b00), - .WCLK(CLK1), - .WE(B1EN) - ); -endmodule - -module \$__XILINX_RAM64X3SDP (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); - parameter [64*3-1:0] INIT = {64*3{1'bx}}; - parameter CLKPOL2 = 1; - input CLK1; - - input [5:0] A1ADDR; - output [2:0] A1DATA; - - input [5:0] B1ADDR; - input [2:0] B1DATA; - input B1EN; - - wire DOD_unused; - - RAM64M #( - .INIT_A({INIT[189], INIT[186], INIT[183], INIT[180], INIT[177], INIT[174], INIT[171], INIT[168], INIT[165], INIT[162], INIT[159], INIT[156], INIT[153], INIT[150], INIT[147], INIT[144], INIT[141], INIT[138], INIT[135], INIT[132], INIT[129], INIT[126], INIT[123], INIT[120], INIT[117], INIT[114], INIT[111], INIT[108], INIT[105], INIT[102], INIT[ 99], INIT[ 96], INIT[ 93], INIT[ 90], INIT[ 87], INIT[ 84], INIT[ 81], INIT[ 78], INIT[ 75], INIT[ 72], INIT[ 69], INIT[ 66], INIT[ 63], INIT[ 60], INIT[ 57], INIT[ 54], INIT[ 51], INIT[ 48], INIT[ 45], INIT[ 42], INIT[ 39], INIT[ 36], INIT[ 33], INIT[ 30], INIT[ 27], INIT[ 24], INIT[ 21], INIT[ 18], INIT[ 15], INIT[ 12], INIT[ 9], INIT[ 6], INIT[ 3], INIT[ 0]}), - .INIT_B({INIT[190], INIT[187], INIT[184], INIT[181], INIT[178], INIT[175], INIT[172], INIT[169], INIT[166], INIT[163], INIT[160], INIT[157], INIT[154], INIT[151], INIT[148], INIT[145], INIT[142], INIT[139], INIT[136], INIT[133], INIT[130], INIT[127], INIT[124], INIT[121], INIT[118], INIT[115], INIT[112], INIT[109], INIT[106], INIT[103], INIT[100], INIT[ 97], INIT[ 94], INIT[ 91], INIT[ 88], INIT[ 85], INIT[ 82], INIT[ 79], INIT[ 76], INIT[ 73], INIT[ 70], INIT[ 67], INIT[ 64], INIT[ 61], INIT[ 58], INIT[ 55], INIT[ 52], INIT[ 49], INIT[ 46], INIT[ 43], INIT[ 40], INIT[ 37], INIT[ 34], INIT[ 31], INIT[ 28], INIT[ 25], INIT[ 22], INIT[ 19], INIT[ 16], INIT[ 13], INIT[ 10], INIT[ 7], INIT[ 4], INIT[ 1]}), - .INIT_C({INIT[191], INIT[188], INIT[185], INIT[182], INIT[179], INIT[176], INIT[173], INIT[170], INIT[167], INIT[164], INIT[161], INIT[158], INIT[155], INIT[152], INIT[149], INIT[146], INIT[143], INIT[140], INIT[137], INIT[134], INIT[131], INIT[128], INIT[125], INIT[122], INIT[119], INIT[116], INIT[113], INIT[110], INIT[107], INIT[104], INIT[101], INIT[ 98], INIT[ 95], INIT[ 92], INIT[ 89], INIT[ 86], INIT[ 83], INIT[ 80], INIT[ 77], INIT[ 74], INIT[ 71], INIT[ 68], INIT[ 65], INIT[ 62], INIT[ 59], INIT[ 56], INIT[ 53], INIT[ 50], INIT[ 47], INIT[ 44], INIT[ 41], INIT[ 38], INIT[ 35], INIT[ 32], INIT[ 29], INIT[ 26], INIT[ 23], INIT[ 20], INIT[ 17], INIT[ 14], INIT[ 11], INIT[ 8], INIT[ 5], INIT[ 2]}), - .INIT_D(64'bx), - .IS_WCLK_INVERTED(!CLKPOL2) - ) _TECHMAP_REPLACE_ ( - .ADDRA(A1ADDR), - .ADDRB(A1ADDR), - .ADDRC(A1ADDR), - .DOA(A1DATA[0]), - .DOB(A1DATA[1]), - .DOC(A1DATA[2]), - .DOD(DOD_unused), - - .ADDRD(B1ADDR), - .DIA(B1DATA[0]), - .DIB(B1DATA[1]), - .DIC(B1DATA[2]), - .DID(1'b0), - .WCLK(CLK1), - .WE(B1EN) - ); -endmodule - -module \$__XILINX_RAM32X2Q (CLK1, A1ADDR, A1DATA, A2ADDR, A2DATA, A3ADDR, A3DATA, B1ADDR, B1DATA, B1EN); - parameter [63:0] INIT = 64'bx; - parameter CLKPOL2 = 1; - input CLK1; - - input [4:0] A1ADDR, A2ADDR, A3ADDR; - output [1:0] A1DATA, A2DATA, A3DATA; - - input [4:0] B1ADDR; - input [1:0] B1DATA; - input B1EN; - - RAM32M #( - .INIT_A(INIT), - .INIT_B(INIT), - .INIT_C(INIT), - .INIT_D(INIT), - .IS_WCLK_INVERTED(!CLKPOL2) - ) _TECHMAP_REPLACE_ ( - .ADDRA(A1ADDR), - .ADDRB(A2ADDR), - .ADDRC(A3ADDR), - .DOA(A1DATA), - .DOB(A2DATA), - .DOC(A3DATA), - - .ADDRD(B1ADDR), - .DIA(B1DATA), - .DIB(B1DATA), - .DIC(B1DATA), - .DID(B1DATA), - .WCLK(CLK1), - .WE(B1EN) - ); -endmodule - -module \$__XILINX_RAM64X1Q (CLK1, A1ADDR, A1DATA, A2ADDR, A2DATA, A3ADDR, A3DATA, B1ADDR, B1DATA, B1EN); - parameter [63:0] INIT = 64'bx; - parameter CLKPOL2 = 1; - input CLK1; - - input [5:0] A1ADDR, A2ADDR, A3ADDR; - output A1DATA, A2DATA, A3DATA; - - input [5:0] B1ADDR; - input B1DATA; - input B1EN; - - RAM64M #( - .INIT_A(INIT), - .INIT_B(INIT), - .INIT_C(INIT), - .INIT_D(INIT), - .IS_WCLK_INVERTED(!CLKPOL2) - ) _TECHMAP_REPLACE_ ( - .ADDRA(A1ADDR), - .ADDRB(A2ADDR), - .ADDRC(A3ADDR), - .DOA(A1DATA), - .DOB(A2DATA), - .DOC(A3DATA), - - .ADDRD(B1ADDR), - .DIA(B1DATA), - .DIB(B1DATA), - .DIC(B1DATA), - .DID(B1DATA), - .WCLK(CLK1), - .WE(B1EN) - ); -endmodule diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index bb31d21ec7c..91aaf211854 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -30,11 +30,8 @@ module \$shiftx (A, B, Y); parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - (* force_downto *) input [A_WIDTH-1:0] A; - (* force_downto *) input [B_WIDTH-1:0] B; - (* force_downto *) output [Y_WIDTH-1:0] Y; parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b66dc850dd6..2c5686a3564 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -26,17 +26,14 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +#define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate + // to one LUT6 (instead of a LUT5 + LUT2) + struct SynthXilinxPass : public ScriptPass { SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { } - void on_register() override - { - RTLIL::constpad["synth_xilinx.abc9.xc7.W"] = "300"; // Number with which ABC will map a 6-input gate - // to one LUT6 (instead of a LUT5 + LUT2) - } - - void help() override + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -49,25 +46,10 @@ struct SynthXilinxPass : public ScriptPass log(" -top \n"); log(" use the specified module as top module\n"); log("\n"); - log(" -family \n"); + log(" -family {xcup|xcu|xc7|xc6v|xc5v|xc6s}\n"); log(" run synthesis for the specified Xilinx architecture\n"); log(" generate the synthesis netlist for the specified family.\n"); - log(" supported values:\n"); - log(" - xcup: Ultrascale Plus\n"); - log(" - xcu: Ultrascale\n"); - log(" - xc7: Series 7 (default)\n"); - log(" - xc6s: Spartan 6\n"); - log(" - xc6v: Virtex 6\n"); - log(" - xc5v: Virtex 5 (EXPERIMENTAL)\n"); - log(" - xc4v: Virtex 4 (EXPERIMENTAL)\n"); - log(" - xc3sda: Spartan 3A DSP (EXPERIMENTAL)\n"); - log(" - xc3sa: Spartan 3A (EXPERIMENTAL)\n"); - log(" - xc3se: Spartan 3E (EXPERIMENTAL)\n"); - log(" - xc3s: Spartan 3 (EXPERIMENTAL)\n"); - log(" - xc2vp: Virtex 2 Pro (EXPERIMENTAL)\n"); - log(" - xc2v: Virtex 2 (EXPERIMENTAL)\n"); - log(" - xcve: Virtex E, Spartan 2E (EXPERIMENTAL)\n"); - log(" - xcv: Virtex, Spartan 2 (EXPERIMENTAL)\n"); + log(" default: xc7\n"); log("\n"); log(" -edif \n"); log(" write the design to the specified edif file. writing of an output file\n"); @@ -82,7 +64,7 @@ struct SynthXilinxPass : public ScriptPass log(" (this feature is experimental and incomplete)\n"); log("\n"); log(" -ise\n"); - log(" generate an output netlist suitable for ISE\n"); + log(" generate an output netlist suitable for ISE (enables -iopad)\n"); log("\n"); log(" -nobram\n"); log(" do not use block RAM cells in output netlist\n"); @@ -97,14 +79,16 @@ struct SynthXilinxPass : public ScriptPass log(" do not use XORCY/MUXCY/CARRY4 cells in output netlist\n"); log("\n"); log(" -nowidelut\n"); - log(" do not use MUXF[5-9] resources to implement LUTs larger than native for the target\n"); + log(" do not use MUXF[78] resources to implement LUTs larger than LUT6s\n"); log("\n"); log(" -nodsp\n"); - log(" do not use DSP48*s to implement multipliers and associated logic\n"); + log(" do not use DSP48E1s to implement multipliers and associated logic\n"); + log("\n"); + log(" -iopad\n"); + log(" enable I/O buffer insertion (selected automatically by -ise)\n"); log("\n"); log(" -noiopad\n"); - log(" disable I/O buffer insertion (useful for hierarchical or \n"); - log(" out-of-context flows)\n"); + log(" disable I/O buffer insertion (only useful with -ise)\n"); log("\n"); log(" -noclkbuf\n"); log(" disable automatic clock buffer insertion\n"); @@ -125,12 +109,8 @@ struct SynthXilinxPass : public ScriptPass log(" -flatten\n"); log(" flatten design before synthesis\n"); log("\n"); - log(" -dff\n"); - log(" run 'abc'/'abc9' with -dff option\n"); - log("\n"); log(" -retime\n"); - log(" run 'abc' with '-D 1' option to enable flip-flop retiming.\n"); - log(" implies -dff.\n"); + log(" run 'abc' with -dff option\n"); log("\n"); log(" -abc9\n"); log(" use new ABC9 flow (EXPERIMENTAL)\n"); @@ -142,14 +122,11 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, family; - bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram; - bool abc9, dff; + bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram, abc9; bool flatten_before_abc; int widemux; - int lut_size; - int widelut_size; - void clear_flags() override + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; edif_file.clear(); @@ -159,6 +136,7 @@ struct SynthXilinxPass : public ScriptPass retime = false; vpr = false; ise = false; + iopad = false; noiopad = false; noclkbuf = false; nocarry = false; @@ -170,13 +148,11 @@ struct SynthXilinxPass : public ScriptPass nodsp = false; uram = false; abc9 = false; - dff = false; flatten_before_abc = false; widemux = 0; - lut_size = 6; } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string run_from, run_to; clear_flags(); @@ -217,7 +193,6 @@ struct SynthXilinxPass : public ScriptPass continue; } if (args[argidx] == "-retime") { - dff = true; retime = true; continue; } @@ -238,6 +213,7 @@ struct SynthXilinxPass : public ScriptPass continue; } if (args[argidx] == "-iopad") { + iopad = true; continue; } if (args[argidx] == "-noiopad") { @@ -280,46 +256,13 @@ struct SynthXilinxPass : public ScriptPass uram = true; continue; } - if (args[argidx] == "-dff") { - dff = true; - continue; - } break; } extra_args(args, argidx, design); - if (family == "xcup" || family == "xcu") { - lut_size = 6; - widelut_size = 9; - } else if (family == "xc7" || - family == "xc6v" || - family == "xc5v" || - family == "xc6s") { - lut_size = 6; - widelut_size = 8; - } else if (family == "xc4v" || - family == "xc3sda" || - family == "xc3sa" || - family == "xc3se" || - family == "xc3s" || - family == "xc2vp" || - family == "xc2v") { - lut_size = 4; - widelut_size = 8; - } else if (family == "xcve" || family == "xcv") { - lut_size = 4; - widelut_size = 6; - } else + if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6v" && family != "xc5v" && family != "xc6s") log_cmd_error("Invalid Xilinx -family setting: '%s'.\n", family.c_str()); - if (widemux != 0 && lut_size != 6) - log_cmd_error("-widemux is not currently supported for LUT4-based architectures.\n"); - - if (lut_size != 6) { - log_warning("Shift register inference not yet supported for family %s.\n", family.c_str()); - nosrl = true; - } - if (widemux != 0 && widemux < 2) log_cmd_error("-widemux value must be 0 or >= 2.\n"); @@ -337,11 +280,9 @@ struct SynthXilinxPass : public ScriptPass log_pop(); } - void script() override + void script() YS_OVERRIDE { - std::string lut_size_s = std::to_string(lut_size); - if (help_mode) - lut_size_s = "[46]"; + bool do_iopad = iopad || (ise && !noiopad); std::string ff_map_file; if (help_mode) ff_map_file = "+/xilinx/{family}_ff_map.v"; @@ -351,11 +292,10 @@ struct SynthXilinxPass : public ScriptPass ff_map_file = "+/xilinx/xc7_ff_map.v"; if (check_label("begin")) { - std::string read_args; if (vpr) - read_args += " -D_EXPLICIT_CARRY"; - read_args += " -lib -specify +/xilinx/cells_sim.v"; - run("read_verilog" + read_args); + run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); + else + run("read_verilog -lib +/xilinx/cells_sim.v"); run("read_verilog -lib +/xilinx/cells_xtra.v"); @@ -366,11 +306,7 @@ struct SynthXilinxPass : public ScriptPass run("proc"); if (flatten || help_mode) run("flatten", "(with '-flatten')"); - if (active_design) - active_design->scratchpad_unset("tribuf.added_something"); run("tribuf -logic"); - if (noiopad && active_design && active_design->scratchpad_get_bool("tribuf.added_something")) - log_error("Tristate buffers are unsupported without the '-iopad' option.\n"); run("deminout"); run("opt_expr"); run("opt_clean"); @@ -393,6 +329,8 @@ struct SynthXilinxPass : public ScriptPass run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); run("clean", " (skip if '-nosrl' and '-widemux=0')"); } + + run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); } if (check_label("map_dsp", "(skip if '-nodsp')")) { @@ -401,7 +339,7 @@ struct SynthXilinxPass : public ScriptPass // NB: Xilinx multipliers are signed only if (help_mode) run("techmap -map +/mul2dsp.v -map +/xilinx/{family}_dsp_map.v {options}"); - else if (family == "xc2v" || family == "xc2vp" || family == "xc3s" || family == "xc3se" || family == "xc3sa") + else if (family == "xc2v" || family == "xc3s" || family == "xc3se" || family == "xc3sa") run("techmap -map +/mul2dsp.v -map +/xilinx/xc3s_mult_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller @@ -449,16 +387,12 @@ struct SynthXilinxPass : public ScriptPass run("opt_expr -fine"); run("wreduce"); run("select -clear"); - if (help_mode) - run("xilinx_dsp -family "); - else - run("xilinx_dsp -family " + family); + run("xilinx_dsp"); run("chtype -set $mul t:$__soft_mul"); } } if (check_label("coarse")) { - run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=" + lut_size_s); run("alumacc"); run("share"); run("opt"); @@ -487,19 +421,7 @@ struct SynthXilinxPass : public ScriptPass run("memory_bram -rules +/xilinx/{family}_brams.txt"); run("techmap -map +/xilinx/{family}_brams_map.v"); } else if (!nobram) { - if (family == "xc2v" || family == "xc2vp" || family == "xc3s" || family == "xc3se") { - run("memory_bram -rules +/xilinx/xc2v_brams.txt"); - run("techmap -map +/xilinx/xc2v_brams_map.v"); - } else if (family == "xc3sa") { - // Superset of Virtex 2 primitives — uses common map file. - run("memory_bram -rules +/xilinx/xc3sa_brams.txt"); - run("techmap -map +/xilinx/xc2v_brams_map.v"); - } else if (family == "xc3sda") { - // Supported block RAMs for Spartan 3A DSP are - // a subset of Spartan 6's ones. - run("memory_bram -rules +/xilinx/xc3sda_brams.txt"); - run("techmap -map +/xilinx/xc6s_brams_map.v"); - } else if (family == "xc6s") { + if (family == "xc6s") { run("memory_bram -rules +/xilinx/xc6s_brams.txt"); run("techmap -map +/xilinx/xc6s_brams_map.v"); } else if (family == "xc6v" || family == "xc7") { @@ -516,21 +438,12 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_lutram", "(skip if '-nolutram')")) { if (!nolutram || help_mode) { - run("memory_bram -rules +/xilinx/lut" + lut_size_s + "_lutrams.txt"); + run("memory_bram -rules +/xilinx/lutrams.txt"); run("techmap -map +/xilinx/lutrams_map.v"); } } if (check_label("map_ffram")) { - // Required for dff2dffs to work. - run("simplemap t:$dff t:$adff t:$mux"); - // Needs to be done before opt -mux_bool happens. - if (help_mode) - run("dff2dffs [-match-init]", "(-match-init for xc6s only)"); - else if (family == "xc6s") - run("dff2dffs -match-init"); - else - run("dff2dffs"); if (widemux > 0) run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover // performs less efficiently @@ -540,10 +453,14 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("dff2dffe -direct-match $_DFF_* -direct-match $_SDFF_*"); - if (help_mode) - run("muxcover ('-widemux' only)"); + run("dffsr2dff"); + run("dff2dffe"); + if (help_mode) { + run("simplemap t:$mux", " ('-widemux' only)"); + run("muxcover , ('-widemux' only)"); + } else if (widemux > 0) { + run("simplemap t:$mux"); constexpr int cost_mux2 = 100; std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { @@ -570,15 +487,19 @@ struct SynthXilinxPass : public ScriptPass if (!nosrl || help_mode) run("xilinx_srl -variable -minlen 3", "(skip if '-nosrl')"); - std::string techmap_args = " -map +/techmap.v -D LUT_SIZE=" + lut_size_s; + std::string techmap_args = " -map +/techmap.v"; if (help_mode) techmap_args += " [-map +/xilinx/mux_map.v]"; else if (widemux > 0) techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", widemux); - if (!nocarry) { + if (help_mode) + techmap_args += " [-map +/xilinx/arith_map.v]"; + else if (!nocarry) { techmap_args += " -map +/xilinx/arith_map.v"; if (vpr) techmap_args += " -D _EXPLICIT_CARRY"; + else if (abc9) + techmap_args += " -D _CLB_CARRY"; } run("techmap " + techmap_args); run("opt -fast"); @@ -586,8 +507,8 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_cells")) { // Needs to be done before logic optimization, so that inverters (OE vs T) are handled. - if (help_mode || !noiopad) - run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(skip if '-noiopad')"); + if (help_mode || do_iopad) + run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(only if '-iopad' or '-ise' and not '-noiopad')"); std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v"; if (widemux > 0) techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); @@ -595,11 +516,9 @@ struct SynthXilinxPass : public ScriptPass run("clean"); } - if (check_label("map_ffs", "('-abc9' only)")) { + if (check_label("map_ffs")) { if (abc9 || help_mode) { - if (dff || help_mode) - run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "('-dff' only)"); - run("techmap -map " + ff_map_file); + run("techmap -map " + ff_map_file, "('-abc9' only)"); } } @@ -608,48 +527,27 @@ struct SynthXilinxPass : public ScriptPass if (flatten_before_abc) run("flatten"); if (help_mode) - run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')"); + run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut'; option for '-retime')"); else if (abc9) { - if (lut_size != 6) - log_error("'synth_xilinx -abc9' not currently supported for LUT4-based devices.\n"); if (family != "xc7") log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " "will use timing for 'xc7' instead.\n", family.c_str()); - run("read_verilog -icells -lib -specify +/xilinx/abc9_model.v"); - std::string abc9_opts; - std::string k = "synth_xilinx.abc9.W"; - if (active_design && active_design->scratchpad.count(k)) - abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str()); - else { - k = stringf("synth_xilinx.abc9.%s.W", family.c_str()); - abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k, RTLIL::constpad.at("synth_xilinx.abc9.xc7.W")).c_str()); - } + run("techmap -map +/xilinx/abc9_map.v -max_iter 1"); + run("read_verilog -icells -lib +/xilinx/abc9_model.v"); + std::string abc9_opts = " -box +/xilinx/abc9_xc7.box"; + abc9_opts += stringf(" -W %d", XC7_WIRE_DELAY); + abc9_opts += " -nomfs"; if (nowidelut) - abc9_opts += stringf(" -maxlut %d", lut_size); - if (dff) - abc9_opts += " -dff"; + abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut"; + else + abc9_opts += " -lut +/xilinx/abc9_xc7.lut"; run("abc9" + abc9_opts); } else { - std::string abc_opts; - if (lut_size != 6) { - if (nowidelut) - abc_opts += " -lut " + lut_size_s; - else - abc_opts += " -lut " + lut_size_s + ":" + std::to_string(widelut_size); - } else { - if (nowidelut) - abc_opts += " -luts 2:2,3,6:5"; - else if (widelut_size == 8) - abc_opts += " -luts 2:2,3,6:5,10,20"; - else - abc_opts += " -luts 2:2,3,6:5,10,20,40"; - } - if (dff) - abc_opts += " -dff"; - if (retime) - abc_opts += " -D 1"; - run("abc" + abc_opts); + if (nowidelut) + run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); + else + run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); } run("clean"); @@ -658,25 +556,21 @@ struct SynthXilinxPass : public ScriptPass if (!nosrl || help_mode) run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')"); std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"; - if (help_mode || !abc9) - techmap_args += stringf(" -map %s", ff_map_file.c_str()); - techmap_args += " -D LUT_WIDTH=" + lut_size_s; - run("techmap " + techmap_args); if (help_mode) - run("xilinx_dffopt [-lut4]"); - else if (lut_size == 4) - run("xilinx_dffopt -lut4"); + techmap_args += " [-map " + ff_map_file + "]"; + else if (abc9) + techmap_args += " -map +/xilinx/abc9_unmap.v"; else - run("xilinx_dffopt"); - run("opt_lut_ins -tech xilinx"); + techmap_args += " -map " + ff_map_file; + run("techmap " + techmap_args); + run("clean"); } if (check_label("finalize")) { if (help_mode || !noclkbuf) - run("clkbufmap -buf BUFG O:I", "(skip if '-noclkbuf')"); + run("clkbufmap -buf BUFG O:I ", "(skip if '-noclkbuf')"); if (help_mode || ise) run("extractinv -inv INV O:I", "(only if '-ise')"); - run("clean"); } if (check_label("check")) { diff --git a/techlibs/xilinx/tests/.gitignore b/techlibs/xilinx/tests/.gitignore index 0d9c28fdece..ef3699bd20b 100644 --- a/techlibs/xilinx/tests/.gitignore +++ b/techlibs/xilinx/tests/.gitignore @@ -8,11 +8,4 @@ dsp_work*/ test_dsp_model_ref.v test_dsp_model_uut.v test_dsp_model -test_dsp48a_model_ref.v -test_dsp48a1_model_ref.v -test_dsp48a1_model_uut.v -test_dsp48a1_model -test_dsp48_model_ref.v -test_dsp48_model_uut.v -test_dsp48_model *.vcd diff --git a/techlibs/xilinx/tests/test_dsp48_model.sh b/techlibs/xilinx/tests/test_dsp48_model.sh deleted file mode 100644 index 9a73f9b0c3e..00000000000 --- a/techlibs/xilinx/tests/test_dsp48_model.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -ex -if [ -z $ISE_DIR ]; then - ISE_DIR=/opt/Xilinx/ISE/14.7 -fi -sed 's/DSP48 /DSP48_UUT /; /DSP48_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp48_model_uut.v -if [ ! -f "test_dsp48_model_ref.v" ]; then - cp $ISE_DIR/ISE_DS/ISE/verilog/src/unisims/DSP48.v test_dsp48_model_ref.v -fi -for tb in mult_allreg mult_noreg mult_inreg -do - iverilog -s $tb -s glbl -o test_dsp48_model test_dsp48_model.v test_dsp48_model_uut.v test_dsp48_model_ref.v $ISE_DIR/ISE_DS/ISE/verilog/src/glbl.v - vvp -N ./test_dsp48_model -done diff --git a/techlibs/xilinx/tests/test_dsp48_model.v b/techlibs/xilinx/tests/test_dsp48_model.v deleted file mode 100644 index d69c00e9345..00000000000 --- a/techlibs/xilinx/tests/test_dsp48_model.v +++ /dev/null @@ -1,287 +0,0 @@ -`timescale 1ns / 1ps - -module testbench; - parameter integer AREG = 1; - parameter integer BREG = 1; - parameter integer CREG = 1; - parameter integer MREG = 1; - parameter integer PREG = 1; - parameter integer CARRYINREG = 1; - parameter integer CARRYINSELREG = 1; - parameter integer OPMODEREG = 1; - parameter integer SUBTRACTREG = 1; - parameter B_INPUT = "DIRECT"; - parameter LEGACY_MODE = "NONE"; - - reg CLK; - reg CEA, CEB, CEC, CEM, CEP, CECARRYIN, CECINSUB, CECTRL; - reg RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL; - reg [17:0] A; - reg [17:0] B; - reg [47:0] C; - reg [17:0] BCIN; - reg [47:0] PCIN; - reg CARRYIN; - reg [6:0] OPMODE; - reg SUBTRACT; - reg [1:0] CARRYINSEL; - - output [47:0] P, REF_P; - output [17:0] BCOUT, REF_BCOUT; - output [47:0] PCOUT, REF_PCOUT; - - integer errcount = 0; - - reg ERROR_FLAG = 0; - - task clkcycle; - begin - #5; - CLK = ~CLK; - #10; - CLK = ~CLK; - #2; - ERROR_FLAG = 0; - if (REF_BCOUT !== BCOUT) begin - $display("ERROR at %1t: REF_BCOUT=%b UUT_BCOUT=%b DIFF=%b", $time, REF_BCOUT, BCOUT, REF_BCOUT ^ BCOUT); - errcount = errcount + 1; - ERROR_FLAG = 1; - end - if (REF_P !== P) begin - $display("ERROR at %1t: REF_P=%b UUT_P=%b DIFF=%b", $time, REF_P, P, REF_P ^ P); - errcount = errcount + 1; - ERROR_FLAG = 1; - end - if (REF_PCOUT !== PCOUT) begin - $display("ERROR at %1t: REF_PCOUT=%b UUT_PCOUT=%b DIFF=%b", $time, REF_PCOUT, PCOUT, REF_PCOUT ^ PCOUT); - errcount = errcount + 1; - ERROR_FLAG = 1; - end - #3; - end - endtask - - reg config_valid = 0; - task drc; - begin - config_valid = 1; - - if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0; - if (OPMODE[1:0] == 2'b00 && CARRYINSEL == 2'b10) config_valid = 0; - if (OPMODE[1:0] == 2'b10 && CARRYINSEL == 2'b10) config_valid = 0; - if (OPMODE[1:0] == 2'b00 && CARRYINSEL == 2'b11) config_valid = 0; - if (OPMODE[1:0] == 2'b10 && CARRYINSEL == 2'b11) config_valid = 0; - if (OPMODE[3:2] == 2'b10) config_valid = 0; - if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0; - if ((OPMODE[6:4] == 3'b010 || OPMODE[6:4] == 3'b110) && PREG != 1) config_valid = 0; - if (OPMODE[6:4] == 3'b100) config_valid = 0; - if (OPMODE[6:4] == 3'b111) config_valid = 0; - if (OPMODE[6:4] == 3'b000 && CARRYINSEL == 2'b01) config_valid = 0; - if (OPMODE[6:4] == 3'b011 && CARRYINSEL == 2'b01) config_valid = 0; - - // Xilinx models consider these combinations invalid for an unknown reason. - if (CARRYINSEL == 2'b01 && OPMODE[3:2] == 2'b00) config_valid = 0; - if (CARRYINSEL == 2'b10 && OPMODE == 7'b0000011) config_valid = 0; - if (CARRYINSEL == 2'b10 && OPMODE == 7'b0000101) config_valid = 0; - if (CARRYINSEL == 2'b10 && OPMODE == 7'b0100011) config_valid = 0; - if (CARRYINSEL == 2'b10 && OPMODE == 7'b0111111) config_valid = 0; - if (CARRYINSEL == 2'b10 && OPMODE == 7'b1100011) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b0000011) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b0000101) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b0011111) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b0010011) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b0100011) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b0100101) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b0101111) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b0110011) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b0111111) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b1010011) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b1011111) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b1100011) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b1100101) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE == 7'b1101111) config_valid = 0; - - if (CARRYINSEL == 2'b10 && OPMODE[3:0] == 4'b0101 && MREG == 1) config_valid = 0; - if (CARRYINSEL == 2'b11 && OPMODE[3:0] == 4'b0101 && MREG == 0) config_valid = 0; - end - endtask - - initial begin - $dumpfile("test_dsp48_model.vcd"); - $dumpvars(0, testbench); - - #2; - CLK = 1'b0; - {CEA, CEB, CEC, CEM, CEP, CECARRYIN, CECINSUB, CECTRL} = 8'b11111111; - {A, B, C, PCIN, OPMODE, SUBTRACT, CARRYIN, CARRYINSEL} = 0; - {RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL} = 7'b1111111; - repeat (10) begin - #10; - CLK = 1'b1; - #10; - CLK = 1'b0; - #10; - CLK = 1'b1; - #10; - CLK = 1'b0; - end - {RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL} = 0; - - repeat (100000) begin - clkcycle; - config_valid = 0; - while (!config_valid) begin - A = $urandom; - B = $urandom; - C = {$urandom, $urandom}; - BCIN = $urandom; - PCIN = {$urandom, $urandom}; - - {CEA, CEB, CEC, CEM, CEP, CECARRYIN, CECINSUB, CECTRL} = $urandom | $urandom | $urandom; - {RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom; - {CARRYIN, CARRYINSEL, OPMODE, SUBTRACT} = $urandom; - - drc; - end - end - - if (errcount == 0) begin - $display("All tests passed."); - $finish; - end else begin - $display("Caught %1d errors.", errcount); - $stop; - end - end - - DSP48 #( - .AREG (AREG), - .BREG (BREG), - .CREG (CREG), - .MREG (MREG), - .PREG (PREG), - .CARRYINREG (CARRYINREG), - .CARRYINSELREG (CARRYINSELREG), - .OPMODEREG (OPMODEREG), - .SUBTRACTREG (SUBTRACTREG), - .B_INPUT (B_INPUT), - .LEGACY_MODE (LEGACY_MODE) - ) ref ( - .A (A), - .B (B), - .C (C), - .BCIN (BCIN), - .PCIN (PCIN), - .CARRYIN (CARRYIN), - .OPMODE (OPMODE), - .SUBTRACT (SUBTRACT), - .CARRYINSEL (CARRYINSEL), - .BCOUT (REF_BCOUT), - .P (REF_P), - .PCOUT (REF_PCOUT), - .CEA (CEA), - .CEB (CEB), - .CEC (CEC), - .CEM (CEM), - .CEP (CEP), - .CECARRYIN (CECARRYIN), - .CECINSUB (CECINSUB), - .CECTRL (CECTRL), - .CLK (CLK), - .RSTA (RSTA), - .RSTB (RSTB), - .RSTC (RSTC), - .RSTM (RSTM), - .RSTP (RSTP), - .RSTCARRYIN (RSTCARRYIN), - .RSTCTRL (RSTCTRL) - ); - - DSP48_UUT #( - .AREG (AREG), - .BREG (BREG), - .CREG (CREG), - .MREG (MREG), - .PREG (PREG), - .CARRYINREG (CARRYINREG), - .CARRYINSELREG (CARRYINSELREG), - .OPMODEREG (OPMODEREG), - .SUBTRACTREG (SUBTRACTREG), - .B_INPUT (B_INPUT), - .LEGACY_MODE (LEGACY_MODE) - ) uut ( - .A (A), - .B (B), - .C (C), - .BCIN (BCIN), - .PCIN (PCIN), - .CARRYIN (CARRYIN), - .OPMODE (OPMODE), - .SUBTRACT (SUBTRACT), - .CARRYINSEL (CARRYINSEL), - .BCOUT (BCOUT), - .P (P), - .PCOUT (PCOUT), - .CEA (CEA), - .CEB (CEB), - .CEC (CEC), - .CEM (CEM), - .CEP (CEP), - .CECARRYIN (CECARRYIN), - .CECINSUB (CECINSUB), - .CECTRL (CECTRL), - .CLK (CLK), - .RSTA (RSTA), - .RSTB (RSTB), - .RSTC (RSTC), - .RSTM (RSTM), - .RSTP (RSTP), - .RSTCARRYIN (RSTCARRYIN), - .RSTCTRL (RSTCTRL) - ); -endmodule - -module mult_noreg; - testbench #( - .AREG (0), - .BREG (0), - .CREG (0), - .MREG (0), - .PREG (0), - .CARRYINREG (0), - .CARRYINSELREG (0), - .OPMODEREG (0), - .SUBTRACTREG (0), - .B_INPUT ("DIRECT") - ) testbench (); -endmodule - -module mult_allreg; - testbench #( - .AREG (1), - .BREG (1), - .CREG (1), - .MREG (1), - .PREG (1), - .CARRYINREG (1), - .CARRYINSELREG (1), - .OPMODEREG (1), - .SUBTRACTREG (1), - .B_INPUT ("CASCADE") - ) testbench (); -endmodule - -module mult_inreg; - testbench #( - .AREG (1), - .BREG (1), - .CREG (1), - .MREG (0), - .PREG (0), - .CARRYINREG (1), - .CARRYINSELREG (0), - .OPMODEREG (0), - .SUBTRACTREG (0), - .B_INPUT ("DIRECT") - ) testbench (); -endmodule diff --git a/techlibs/xilinx/tests/test_dsp48a1_model.sh b/techlibs/xilinx/tests/test_dsp48a1_model.sh deleted file mode 100644 index a14a78e7267..00000000000 --- a/techlibs/xilinx/tests/test_dsp48a1_model.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -ex -if [ -z $ISE_DIR ]; then - ISE_DIR=/opt/Xilinx/ISE/14.7 -fi -sed 's/DSP48A1/MARKER1/; s/DSP48A/DSP48A_UUT/; s/MARKER1/DSP48A1_UUT/; /module DSP48A_UUT/,/endmodule/ p; /module DSP48A1_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp48a1_model_uut.v -if [ ! -f "test_dsp48a1_model_ref.v" ]; then - cp $ISE_DIR/ISE_DS/ISE/verilog/src/unisims/DSP48A1.v test_dsp48a1_model_ref.v -fi -if [ ! -f "test_dsp48a_model_ref.v" ]; then - cp $ISE_DIR/ISE_DS/ISE/verilog/src/unisims/DSP48A.v test_dsp48a_model_ref.v -fi -for tb in mult_allreg mult_noreg mult_inreg -do - iverilog -s $tb -s glbl -o test_dsp48a1_model test_dsp48a1_model.v test_dsp48a1_model_uut.v test_dsp48a1_model_ref.v test_dsp48a_model_ref.v $ISE_DIR/ISE_DS/ISE/verilog/src/glbl.v - vvp -N ./test_dsp48a1_model -done diff --git a/techlibs/xilinx/tests/test_dsp48a1_model.v b/techlibs/xilinx/tests/test_dsp48a1_model.v deleted file mode 100644 index 66346b47bfa..00000000000 --- a/techlibs/xilinx/tests/test_dsp48a1_model.v +++ /dev/null @@ -1,331 +0,0 @@ -`timescale 1ns / 1ps - -module testbench; - parameter integer A0REG = 1; - parameter integer A1REG = 1; - parameter integer B0REG = 1; - parameter integer B1REG = 1; - parameter integer CREG = 1; - parameter integer DREG = 1; - parameter integer MREG = 1; - parameter integer PREG = 1; - parameter integer CARRYINREG = 1; - parameter integer CARRYOUTREG = 1; - parameter integer OPMODEREG = 1; - parameter CARRYINSEL = "OPMODE5"; - parameter RSTTYPE = "SYNC"; - - reg CLK; - reg CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE; - reg RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE; - reg [17:0] A; - reg [17:0] B; - reg [47:0] C; - reg [17:0] D; - reg [47:0] PCIN; - reg [7:0] OPMODE; - reg CARRYIN; - - output CARRYOUTF, REF_CARRYOUTF; - output CARRYOUT, REF_CARRYOUT, REF_OLD_CARRYOUT; - output [35:0] M, REF_M; - output [47:0] P, REF_P, REF_OLD_P; - output [17:0] BCOUT, REF_BCOUT, REF_OLD_BCOUT; - output [47:0] PCOUT, REF_PCOUT, REF_OLD_PCOUT; - - integer errcount = 0; - - reg ERROR_FLAG = 0; - - task clkcycle; - begin - #5; - CLK = ~CLK; - #10; - CLK = ~CLK; - #2; - ERROR_FLAG = 0; - if (REF_BCOUT !== BCOUT || REF_OLD_BCOUT != BCOUT) begin - $display("ERROR at %1t: REF_BCOUT=%b REF_OLD_BCOUT=%b UUT_BCOUT=%b DIFF=%b", $time, REF_BCOUT, REF_OLD_BCOUT, BCOUT, REF_BCOUT ^ BCOUT); - errcount = errcount + 1; - ERROR_FLAG = 1; - end - if (REF_M !== M) begin - $display("ERROR at %1t: REF_M=%b UUT_M=%b DIFF=%b", $time, REF_M, M, REF_M ^ M); - errcount = errcount + 1; - ERROR_FLAG = 1; - end - if (REF_P !== P || REF_OLD_P != P) begin - $display("ERROR at %1t: REF_P=%b REF_OLD_P=%b UUT_P=%b DIFF=%b", $time, REF_P, REF_OLD_P, P, REF_P ^ P); - errcount = errcount + 1; - ERROR_FLAG = 1; - end - if (REF_PCOUT !== PCOUT || REF_OLD_PCOUT != PCOUT) begin - $display("ERROR at %1t: REF_PCOUT=%b REF_OLD_PCOUT=%b UUT_PCOUT=%b DIFF=%b", $time, REF_PCOUT, REF_OLD_PCOUT, PCOUT, REF_PCOUT ^ PCOUT); - errcount = errcount + 1; - ERROR_FLAG = 1; - end - if (REF_CARRYOUT !== CARRYOUT || (REF_OLD_CARRYOUT != CARRYOUT && !CARRYOUTREG)) begin - $display("ERROR at %1t: REF_CARRYOUT=%b REF_OLD_CARRYOUT=%b UUT_CARRYOUT=%b DIFF=%b", $time, REF_CARRYOUT, REF_OLD_CARRYOUT, CARRYOUT, REF_CARRYOUT ^ CARRYOUT); - errcount = errcount + 1; - ERROR_FLAG = 1; - end - if (REF_CARRYOUTF !== CARRYOUTF) begin - $display("ERROR at %1t: REF_CARRYOUTF=%b UUT_CARRYOUTF=%b", $time, REF_CARRYOUTF, CARRYOUTF); - errcount = errcount + 1; - ERROR_FLAG = 1; - end - #3; - end - endtask - - reg config_valid = 0; - task drc; - begin - config_valid = 1; - - if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0; - if (OPMODE[3:2] == 2'b10 && PREG != 1) config_valid = 0; - end - endtask - - initial begin - $dumpfile("test_dsp48a1_model.vcd"); - $dumpvars(0, testbench); - - #2; - CLK = 1'b0; - {CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE} = 8'b11111111; - {A, B, C, D, PCIN, OPMODE, CARRYIN} = 0; - {RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = 8'b11111111; - repeat (10) begin - #10; - CLK = 1'b1; - #10; - CLK = 1'b0; - #10; - CLK = 1'b1; - #10; - CLK = 1'b0; - end - {RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = 0; - - repeat (10000) begin - clkcycle; - config_valid = 0; - while (!config_valid) begin - A = $urandom; - B = $urandom; - C = {$urandom, $urandom}; - D = $urandom; - PCIN = {$urandom, $urandom}; - - {CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE} = $urandom | $urandom | $urandom; - {RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom; - {CARRYIN, OPMODE} = $urandom; - - drc; - end - end - - if (errcount == 0) begin - $display("All tests passed."); - $finish; - end else begin - $display("Caught %1d errors.", errcount); - $stop; - end - end - - DSP48A #( - .A0REG (A0REG), - .A1REG (A1REG), - .B0REG (B0REG), - .B1REG (B1REG), - .CREG (CREG), - .DREG (DREG), - .MREG (MREG), - .PREG (PREG), - .CARRYINREG (CARRYINREG), - .OPMODEREG (OPMODEREG), - .CARRYINSEL (CARRYINSEL), - .RSTTYPE (RSTTYPE) - ) ref_old ( - .A (A), - .B (B), - .C (C), - .D (D), - .PCIN (PCIN), - .CARRYIN (CARRYIN), - .OPMODE (OPMODE), - .BCOUT (REF_OLD_BCOUT), - .CARRYOUT (REF_OLD_CARRYOUT), - .P (REF_OLD_P), - .PCOUT (REF_OLD_PCOUT), - .CEA (CEA), - .CEB (CEB), - .CEC (CEC), - .CED (CED), - .CEM (CEM), - .CEP (CEP), - .CECARRYIN (CECARRYIN), - .CEOPMODE (CEOPMODE), - .CLK (CLK), - .RSTA (RSTA), - .RSTB (RSTB), - .RSTC (RSTC), - .RSTD (RSTD), - .RSTM (RSTM), - .RSTP (RSTP), - .RSTCARRYIN (RSTCARRYIN), - .RSTOPMODE (RSTOPMODE) - ); - - DSP48A1 #( - .A0REG (A0REG), - .A1REG (A1REG), - .B0REG (B0REG), - .B1REG (B1REG), - .CREG (CREG), - .DREG (DREG), - .MREG (MREG), - .PREG (PREG), - .CARRYINREG (CARRYINREG), - .CARRYOUTREG (CARRYOUTREG), - .OPMODEREG (OPMODEREG), - .CARRYINSEL (CARRYINSEL), - .RSTTYPE (RSTTYPE) - ) ref ( - .A (A), - .B (B), - .C (C), - .D (D), - .PCIN (PCIN), - .CARRYIN (CARRYIN), - .OPMODE (OPMODE), - .BCOUT (REF_BCOUT), - .CARRYOUTF (REF_CARRYOUTF), - .CARRYOUT (REF_CARRYOUT), - .P (REF_P), - .M (REF_M), - .PCOUT (REF_PCOUT), - .CEA (CEA), - .CEB (CEB), - .CEC (CEC), - .CED (CED), - .CEM (CEM), - .CEP (CEP), - .CECARRYIN (CECARRYIN), - .CEOPMODE (CEOPMODE), - .CLK (CLK), - .RSTA (RSTA), - .RSTB (RSTB), - .RSTC (RSTC), - .RSTD (RSTD), - .RSTM (RSTM), - .RSTP (RSTP), - .RSTCARRYIN (RSTCARRYIN), - .RSTOPMODE (RSTOPMODE) - ); - - DSP48A1_UUT #( - .A0REG (A0REG), - .A1REG (A1REG), - .B0REG (B0REG), - .B1REG (B1REG), - .CREG (CREG), - .DREG (DREG), - .MREG (MREG), - .PREG (PREG), - .CARRYINREG (CARRYINREG), - .CARRYOUTREG (CARRYOUTREG), - .OPMODEREG (OPMODEREG), - .CARRYINSEL (CARRYINSEL), - .RSTTYPE (RSTTYPE) - ) uut ( - .A (A), - .B (B), - .C (C), - .D (D), - .PCIN (PCIN), - .CARRYIN (CARRYIN), - .OPMODE (OPMODE), - .BCOUT (BCOUT), - .CARRYOUTF (CARRYOUTF), - .CARRYOUT (CARRYOUT), - .P (P), - .M (M), - .PCOUT (PCOUT), - .CEA (CEA), - .CEB (CEB), - .CEC (CEC), - .CED (CED), - .CEM (CEM), - .CEP (CEP), - .CECARRYIN (CECARRYIN), - .CEOPMODE (CEOPMODE), - .CLK (CLK), - .RSTA (RSTA), - .RSTB (RSTB), - .RSTC (RSTC), - .RSTD (RSTD), - .RSTM (RSTM), - .RSTP (RSTP), - .RSTCARRYIN (RSTCARRYIN), - .RSTOPMODE (RSTOPMODE) - ); -endmodule - -module mult_noreg; - testbench #( - .A0REG (0), - .A1REG (0), - .B0REG (0), - .B1REG (0), - .CREG (0), - .DREG (0), - .MREG (0), - .PREG (0), - .CARRYINREG (0), - .CARRYOUTREG (0), - .OPMODEREG (0), - .CARRYINSEL ("CARRYIN"), - .RSTTYPE ("SYNC") - ) testbench (); -endmodule - -module mult_allreg; - testbench #( - .A0REG (1), - .A1REG (1), - .B0REG (1), - .B1REG (1), - .CREG (1), - .DREG (1), - .MREG (1), - .PREG (1), - .CARRYINREG (1), - .CARRYOUTREG (1), - .OPMODEREG (1), - .CARRYINSEL ("OPMODE5"), - .RSTTYPE ("SYNC") - ) testbench (); -endmodule - -module mult_inreg; - testbench #( - .A0REG (1), - .A1REG (1), - .B0REG (1), - .B1REG (1), - .CREG (1), - .DREG (1), - .MREG (0), - .PREG (0), - .CARRYINREG (1), - .CARRYOUTREG (0), - .OPMODEREG (0), - .CARRYINSEL ("CARRYIN"), - .RSTTYPE ("SYNC") - ) testbench (); -endmodule diff --git a/techlibs/xilinx/tests/test_dsp_model.sh b/techlibs/xilinx/tests/test_dsp_model.sh index d005cd40c73..ae925c40218 100644 --- a/techlibs/xilinx/tests/test_dsp_model.sh +++ b/techlibs/xilinx/tests/test_dsp_model.sh @@ -1,17 +1,14 @@ #!/bin/bash set -ex -if [ -z $VIVADO_DIR ]; then - VIVADO_DIR=/opt/Xilinx/Vivado/2019.1 -fi sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.v if [ ! -f "test_dsp_model_ref.v" ]; then - cp $VIVADO_DIR/data/verilog/src/unisims/DSP48E1.v test_dsp_model_ref.v + cat /opt/Xilinx/Vivado/2019.1/data/verilog/src/unisims/DSP48E1.v > test_dsp_model_ref.v fi for tb in macc_overflow_underflow \ - simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \ - mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc \ + simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \ + mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc \ mult_allreg_preadd_nocasc mult_noreg_preadd_nocasc mult_inreg_preadd_nocasc do - iverilog -s $tb -s glbl -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v $VIVADO_DIR/data/verilog/src/glbl.v + iverilog -s $tb -s glbl -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v /opt/Xilinx/Vivado/2019.1/data/verilog/src/glbl.v vvp -N ./test_dsp_model done diff --git a/techlibs/xilinx/xc2v_brams.txt b/techlibs/xilinx/xc2v_brams.txt deleted file mode 100644 index ac8cfb5527e..00000000000 --- a/techlibs/xilinx/xc2v_brams.txt +++ /dev/null @@ -1,31 +0,0 @@ -# Virtex 2, Virtex 2 Pro, Spartan 3, Spartan 3E block RAM rules. - -bram $__XILINX_RAMB16 - init 1 - abits 9 @a9d36 - dbits 36 @a9d36 - abits 10 @a10d18 - dbits 18 @a10d18 - abits 11 @a11d9 - dbits 9 @a11d9 - abits 12 @a12d4 - dbits 4 @a12d4 - abits 13 @a13d2 - dbits 2 @a13d2 - abits 14 @a14d1 - dbits 1 @a14d1 - groups 2 - ports 1 1 - wrmode 0 1 - enable 1 1 - transp 0 0 - clocks 2 3 - clkpol 2 3 -endbram - -match $__XILINX_RAMB16 - min bits 4096 - min efficiency 5 - shuffle_enable B - make_transp -endmatch diff --git a/techlibs/xilinx/xc2v_brams_map.v b/techlibs/xilinx/xc2v_brams_map.v deleted file mode 100644 index dc698f956d6..00000000000 --- a/techlibs/xilinx/xc2v_brams_map.v +++ /dev/null @@ -1,266 +0,0 @@ -// Virtex 2, Virtex 2 Pro, Spartan 3, Spartan 3E, Spartan 3A block RAM -// mapping (Spartan 3A is a superset of the other four). - -// ------------------------------------------------------------------------ - -module \$__XILINX_RAMB16 (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); - parameter CFG_ABITS = 9; - parameter CFG_DBITS = 36; - parameter CFG_ENABLE_B = 1; - - parameter CLKPOL2 = 1; - parameter CLKPOL3 = 1; - parameter [18431:0] INIT = 18432'bx; - - input CLK2; - input CLK3; - - input [CFG_ABITS-1:0] A1ADDR; - output [CFG_DBITS-1:0] A1DATA; - input A1EN; - - input [CFG_ABITS-1:0] B1ADDR; - input [CFG_DBITS-1:0] B1DATA; - input [CFG_ENABLE_B-1:0] B1EN; - - generate if (CFG_DBITS == 1) begin - wire DOB; - RAMB16_S1_S1 #( - `include "brams_init_16.vh" - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), - ) _TECHMAP_REPLACE_ ( - .DIA(1'd0), - .DOA(A1DATA), - .ADDRA(A1ADDR), - .CLKA(CLK2 ^ !CLKPOL2), - .ENA(A1EN), - .SSRA(|0), - .WEA(1'b0), - - .DIB(B1DATA), - .DOB(DOB), - .ADDRB(B1ADDR), - .CLKB(CLK3 ^ !CLKPOL3), - .ENB(|1), - .SSRB(|0), - .WEB(B1EN) - ); - end else if (CFG_DBITS == 2) begin - wire [1:0] DOB; - RAMB16_S2_S2 #( - `include "brams_init_16.vh" - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), - ) _TECHMAP_REPLACE_ ( - .DIA(2'd0), - .DOA(A1DATA), - .ADDRA(A1ADDR), - .CLKA(CLK2 ^ !CLKPOL2), - .ENA(A1EN), - .SSRA(|0), - .WEA(1'b0), - - .DIB(B1DATA), - .DOB(DOB), - .ADDRB(B1ADDR), - .CLKB(CLK3 ^ !CLKPOL3), - .ENB(|1), - .SSRB(|0), - .WEB(B1EN) - ); - end else if (CFG_DBITS == 4) begin - wire [3:0] DOB; - RAMB16_S4_S4 #( - `include "brams_init_16.vh" - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), - ) _TECHMAP_REPLACE_ ( - .DIA(4'd0), - .DOA(A1DATA), - .ADDRA(A1ADDR), - .CLKA(CLK2 ^ !CLKPOL2), - .ENA(A1EN), - .SSRA(|0), - .WEA(1'b0), - - .DIB(B1DATA), - .DOB(DOB), - .ADDRB(B1ADDR), - .CLKB(CLK3 ^ !CLKPOL3), - .ENB(|1), - .SSRB(|0), - .WEB(B1EN) - ); - end else if (CFG_DBITS == 9) begin - wire [7:0] DOB; - wire DOPB; - RAMB16_S9_S9 #( - `include "brams_init_18.vh" - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), - ) _TECHMAP_REPLACE_ ( - .DIA(8'd0), - .DIPA(1'd0), - .DOA(A1DATA[7:0]), - .DOPA(A1DATA[8]), - .ADDRA(A1ADDR), - .CLKA(CLK2 ^ !CLKPOL2), - .ENA(A1EN), - .SSRA(|0), - .WEA(1'b0), - - .DIB(B1DATA[7:0]), - .DIPB(B1DATA[8]), - .DOB(DOB), - .DOPB(DOPB), - .ADDRB(B1ADDR), - .CLKB(CLK3 ^ !CLKPOL3), - .ENB(|1), - .SSRB(|0), - .WEB(B1EN) - ); - end else if (CFG_DBITS == 18) begin - wire [15:0] DOB; - wire [1:0] DOPB; - RAMB16_S18_S18 #( - `include "brams_init_18.vh" - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), - ) _TECHMAP_REPLACE_ ( - .DIA(16'd0), - .DIPA(2'd0), - .DOA({A1DATA[16:9], A1DATA[7:0]}), - .DOPA({A1DATA[17], A1DATA[8]}), - .ADDRA(A1ADDR), - .CLKA(CLK2 ^ !CLKPOL2), - .ENA(A1EN), - .SSRA(|0), - .WEA(1'b0), - - .DIB({B1DATA[16:9], B1DATA[7:0]}), - .DIPB({B1DATA[17], B1DATA[8]}), - .DOB(DOB), - .DOPB(DOPB), - .ADDRB(B1ADDR), - .CLKB(CLK3 ^ !CLKPOL3), - .ENB(|1), - .SSRB(|0), - .WEB(B1EN) - ); - end else if (CFG_DBITS == 36) begin - wire [31:0] DOB; - wire [3:0] DOPB; - RAMB16_S36_S36 #( - `include "brams_init_18.vh" - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), - ) _TECHMAP_REPLACE_ ( - .DIA(32'd0), - .DIPA(4'd0), - .DOA({A1DATA[34:27], A1DATA[25:18], A1DATA[16:9], A1DATA[7:0]}), - .DOPA({A1DATA[35], A1DATA[26], A1DATA[17], A1DATA[8]}), - .ADDRA(A1ADDR), - .CLKA(CLK2 ^ !CLKPOL2), - .ENA(A1EN), - .SSRA(|0), - .WEA(1'b0), - - .DIB({B1DATA[34:27], B1DATA[25:18], B1DATA[16:9], B1DATA[7:0]}), - .DIPB({B1DATA[35], B1DATA[26], B1DATA[17], B1DATA[8]}), - .DOB(DOB), - .DOPB(DOPB), - .ADDRB(B1ADDR), - .CLKB(CLK3 ^ !CLKPOL3), - .ENB(|1), - .SSRB(|0), - .WEB(B1EN) - ); - end else begin - $error("Strange block RAM data width."); - end endgenerate -endmodule - - -// Version with separate byte enables, only available on Spartan 3A. - -module \$__XILINX_RAMB16BWE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); - parameter CFG_ABITS = 9; - parameter CFG_DBITS = 36; - parameter CFG_ENABLE_B = 4; - - parameter CLKPOL2 = 1; - parameter CLKPOL3 = 1; - parameter [18431:0] INIT = 18432'bx; - - input CLK2; - input CLK3; - - input [CFG_ABITS-1:0] A1ADDR; - output [CFG_DBITS-1:0] A1DATA; - input A1EN; - - input [CFG_ABITS-1:0] B1ADDR; - input [CFG_DBITS-1:0] B1DATA; - input [CFG_ENABLE_B-1:0] B1EN; - - generate if (CFG_DBITS == 18) begin - wire [15:0] DOB; - wire [1:0] DOPB; - RAMB16BWE_S18_S18 #( - `include "brams_init_18.vh" - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), - ) _TECHMAP_REPLACE_ ( - .DIA(16'd0), - .DIPA(2'd0), - .DOA({A1DATA[16:9], A1DATA[7:0]}), - .DOPA({A1DATA[17], A1DATA[8]}), - .ADDRA(A1ADDR), - .CLKA(CLK2 ^ !CLKPOL2), - .ENA(A1EN), - .SSRA(|0), - .WEA(2'b00), - - .DIB({B1DATA[16:9], B1DATA[7:0]}), - .DIPB({B1DATA[17], B1DATA[8]}), - .DOB(DOB), - .DOPB(DOPB), - .ADDRB(B1ADDR), - .CLKB(CLK3 ^ !CLKPOL3), - .ENB(|1), - .SSRB(|0), - .WEB(B1EN) - ); - end else if (CFG_DBITS == 36) begin - wire [31:0] DOB; - wire [3:0] DOPB; - RAMB16BWE_S36_S36 #( - `include "brams_init_18.vh" - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), - ) _TECHMAP_REPLACE_ ( - .DIA(32'd0), - .DIPA(4'd0), - .DOA({A1DATA[34:27], A1DATA[25:18], A1DATA[16:9], A1DATA[7:0]}), - .DOPA({A1DATA[35], A1DATA[26], A1DATA[17], A1DATA[8]}), - .ADDRA(A1ADDR), - .CLKA(CLK2 ^ !CLKPOL2), - .ENA(A1EN), - .SSRA(|0), - .WEA(4'b0000), - - .DIB({B1DATA[34:27], B1DATA[25:18], B1DATA[16:9], B1DATA[7:0]}), - .DIPB({B1DATA[35], B1DATA[26], B1DATA[17], B1DATA[8]}), - .DOB(DOB), - .DOPB(DOPB), - .ADDRB(B1ADDR), - .CLKB(CLK3 ^ !CLKPOL3), - .ENB(|1), - .SSRB(|0), - .WEB(B1EN) - ); - end else begin - $error("Strange block RAM data width."); - end endgenerate -endmodule diff --git a/techlibs/xilinx/xc3sa_brams.txt b/techlibs/xilinx/xc3sa_brams.txt deleted file mode 100644 index 22a62bd2c0b..00000000000 --- a/techlibs/xilinx/xc3sa_brams.txt +++ /dev/null @@ -1,51 +0,0 @@ -# Spartan 3A block RAM rules. - -bram $__XILINX_RAMB16 - init 1 - abits 11 @a11d9 - dbits 9 @a11d9 - abits 12 @a12d4 - dbits 4 @a12d4 - abits 13 @a13d2 - dbits 2 @a13d2 - abits 14 @a14d1 - dbits 1 @a14d1 - groups 2 - ports 1 1 - wrmode 0 1 - enable 1 1 - transp 0 0 - clocks 2 3 - clkpol 2 3 -endbram - -bram $__XILINX_RAMB16BWE - init 1 - abits 9 @a9d36 - dbits 36 @a9d36 - abits 10 @a10d18 - dbits 18 @a10d18 - groups 2 - ports 1 1 - wrmode 0 1 - enable 1 4 @a9d36 - enable 1 2 @a10d18 - transp 0 0 - clocks 2 3 - clkpol 2 3 -endbram - -match $__XILINX_RAMB16 - min bits 4096 - min efficiency 5 - shuffle_enable B - make_transp - or_next_if_better -endmatch - -match $__XILINX_RAMB16BWE - min bits 4096 - min efficiency 5 - shuffle_enable B - make_transp -endmatch diff --git a/techlibs/xilinx/xc3sda_brams.txt b/techlibs/xilinx/xc3sda_brams.txt deleted file mode 100644 index 12c68ffd5f9..00000000000 --- a/techlibs/xilinx/xc3sda_brams.txt +++ /dev/null @@ -1,33 +0,0 @@ -# Spartan 3A DSP block RAM rules. - -bram $__XILINX_RAMB16BWER_TDP - init 1 - abits 9 @a9d36 - dbits 36 @a9d36 - abits 10 @a10d18 - dbits 18 @a10d18 - abits 11 @a11d9 - dbits 9 @a11d9 - abits 12 @a12d4 - dbits 4 @a12d4 - abits 13 @a13d2 - dbits 2 @a13d2 - abits 14 @a14d1 - dbits 1 @a14d1 - groups 2 - ports 1 1 - wrmode 0 1 - enable 1 4 @a9d36 - enable 1 2 @a10d18 - enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 - transp 0 0 - clocks 2 3 - clkpol 2 3 -endbram - -match $__XILINX_RAMB16BWER_TDP - min bits 4096 - min efficiency 5 - shuffle_enable B - make_transp -endmatch diff --git a/techlibs/xilinx/xc3sda_dsp_map.v b/techlibs/xilinx/xc3sda_dsp_map.v index 258f903955a..87348a1737c 100644 --- a/techlibs/xilinx/xc3sda_dsp_map.v +++ b/techlibs/xilinx/xc3sda_dsp_map.v @@ -27,7 +27,7 @@ module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); .D(18'b0), .P(P_48), - .OPMODE(8'b0000001) + .OPMODE(8'b0000010) ); assign Y = P_48; endmodule diff --git a/techlibs/xilinx/xc6s_brams.txt b/techlibs/xilinx/xc6s_brams.txt index 6457097db41..17cd8e3558f 100644 --- a/techlibs/xilinx/xc6s_brams.txt +++ b/techlibs/xilinx/xc6s_brams.txt @@ -1,4 +1,3 @@ -# Spartan 6 block RAM rules. bram $__XILINX_RAMB8BWER_SDP init 1 diff --git a/techlibs/xilinx/xc6s_brams_map.v b/techlibs/xilinx/xc6s_brams_map.v index 9577eebe474..16fd15e743d 100644 --- a/techlibs/xilinx/xc6s_brams_map.v +++ b/techlibs/xilinx/xc6s_brams_map.v @@ -1,6 +1,3 @@ -// Spartan 3A DSP and Spartan 6 block RAM mapping (Spartan 6 is a superset of -// Spartan 3A DSP). - module \$__XILINX_RAMB8BWER_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); parameter CLKPOL2 = 1; parameter CLKPOL3 = 1; diff --git a/techlibs/xilinx/xc6s_dsp_map.v b/techlibs/xilinx/xc6s_dsp_map.v index bdce60c149b..e8705723b0f 100644 --- a/techlibs/xilinx/xc6s_dsp_map.v +++ b/techlibs/xilinx/xc6s_dsp_map.v @@ -27,7 +27,7 @@ module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); .D(18'b0), .P(P_48), - .OPMODE(8'b0000001) + .OPMODE(8'b0000010) ); assign Y = P_48; endmodule diff --git a/techlibs/xilinx/xc6s_ff_map.v b/techlibs/xilinx/xc6s_ff_map.v index a1e4218b911..bf35b09e5df 100644 --- a/techlibs/xilinx/xc6s_ff_map.v +++ b/techlibs/xilinx/xc6s_ff_map.v @@ -27,8 +27,6 @@ `ifndef _NO_FFS -// No reset. - module \$_DFF_N_ (input D, C, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) @@ -48,8 +46,6 @@ module \$_DFF_P_ (input D, C, output Q); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -// No reset, enable. - module \$_DFFE_NP_ (input D, C, E, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) @@ -69,168 +65,80 @@ module \$_DFFE_PP_ (input D, C, E, output Q); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -// Async reset. - -module \$_DFF_NP0_ (input D, C, R, output Q); +module \$_DFF_NN0_ (input D, C, R, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1"); else - FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); + FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endgenerate wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -module \$_DFF_PP0_ (input D, C, R, output Q); +module \$_DFF_NP0_ (input D, C, R, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1"); else - FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); - endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule - -module \$_DFF_NP1_ (input D, C, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) - $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); - else - FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); - endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule -module \$_DFF_PP1_ (input D, C, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) - $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); - else - FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); + FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endgenerate wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule - -// Async reset, enable. - -module \$_DFFE_NP0P_ (input D, C, E, R, output Q); +module \$_DFF_PN0_ (input D, C, R, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1"); else - FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R)); + FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endgenerate wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); +module \$_DFF_PP0_ (input D, C, R, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1"); else - FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R)); + FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endgenerate wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -module \$_DFFE_NP1P_ (input D, C, E, R, output Q); +module \$_DFF_NN1_ (input D, C, R, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); else - FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R)); + FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endgenerate wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -module \$_DFFE_PP1P_ (input D, C, E, R, output Q); +module \$_DFF_NP1_ (input D, C, R, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); else - FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R)); - endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule - -// Sync reset. - -module \$_SDFF_NP0_ (input D, C, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) - $error("Spartan 6 doesn't support FFs with reset initialized to 1"); - else - FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R)); - endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule -module \$_SDFF_PP0_ (input D, C, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) - $error("Spartan 6 doesn't support FFs with reset initialized to 1"); - else - FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R)); - endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule - -module \$_SDFF_NP1_ (input D, C, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) - $error("Spartan 6 doesn't support FFs with set initialized to 0"); - else - FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R)); - endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule -module \$_SDFF_PP1_ (input D, C, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) - $error("Spartan 6 doesn't support FFs with set initialized to 0"); - else - FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R)); - endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule - -// Sync reset, enable. - -module \$_SDFFE_NP0P_ (input D, C, E, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) - $error("Spartan 6 doesn't support FFs with reset initialized to 1"); - else - FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R)); - endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule -module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) - $error("Spartan 6 doesn't support FFs with reset initialized to 1"); - else - FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R)); + FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endgenerate wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule - -module \$_SDFFE_NP1P_ (input D, C, E, R, output Q); +module \$_DFF_PN1_ (input D, C, R, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) - $error("Spartan 6 doesn't support FFs with set initialized to 0"); + $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); else - FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R)); + FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endgenerate wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -module \$_SDFFE_PP1P_ (input D, C, E, R, output Q); +module \$_DFF_PP1_ (input D, C, R, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) - $error("Spartan 6 doesn't support FFs with set initialized to 0"); + $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); else - FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R)); + FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endgenerate wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -// Latches (no reset). - module \$_DLATCH_N_ (input E, D, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) @@ -250,7 +158,5 @@ module \$_DLATCH_P_ (input E, D, output Q); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -// Latches with reset (TODO). - `endif diff --git a/techlibs/xilinx/xc7_brams_map.v b/techlibs/xilinx/xc7_brams_map.v index 2b6ad0da60a..7ea49158d27 100644 --- a/techlibs/xilinx/xc7_brams_map.v +++ b/techlibs/xilinx/xc7_brams_map.v @@ -1,5 +1,3 @@ -// Virtex 6 and Series 7 block RAM mapping. - module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); parameter CLKPOL2 = 1; parameter CLKPOL3 = 1; diff --git a/techlibs/xilinx/xc7_ff_map.v b/techlibs/xilinx/xc7_ff_map.v index 750e8f8eb5d..32ca9f560e4 100644 --- a/techlibs/xilinx/xc7_ff_map.v +++ b/techlibs/xilinx/xc7_ff_map.v @@ -37,8 +37,6 @@ `ifndef _NO_FFS -// No reset. - module \$_DFF_N_ (input D, C, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); @@ -50,8 +48,6 @@ module \$_DFF_P_ (input D, C, output Q); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -// No reset, enable. - module \$_DFFE_NP_ (input D, C, E, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); @@ -63,104 +59,48 @@ module \$_DFFE_PP_ (input D, C, E, output Q); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -// Async reset. - -module \$_DFF_NP0_ (input D, C, R, output Q); - parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule -module \$_DFF_PP0_ (input D, C, R, output Q); - parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule - -module \$_DFF_NP1_ (input D, C, R, output Q); - parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule -module \$_DFF_PP1_ (input D, C, R, output Q); - parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule - -// Async reset, enable. - -module \$_DFFE_NP0P_ (input D, C, E, R, output Q); - parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R)); - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule -module \$_DFFE_PP0P_ (input D, C, E, R, output Q); - parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R)); - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule - -module \$_DFFE_NP1P_ (input D, C, E, R, output Q); - parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R)); - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule -module \$_DFFE_PP1P_ (input D, C, E, R, output Q); - parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R)); - wire _TECHMAP_REMOVEINIT_Q_ = 1; -endmodule - -// Sync reset. - -module \$_SDFF_NP0_ (input D, C, R, output Q); +module \$_DFF_NN0_ (input D, C, R, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R)); + FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -module \$_SDFF_PP0_ (input D, C, R, output Q); +module \$_DFF_NP0_ (input D, C, R, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R)); + FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule - -module \$_SDFF_NP1_ (input D, C, R, output Q); +module \$_DFF_PN0_ (input D, C, R, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R)); + FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -module \$_SDFF_PP1_ (input D, C, R, output Q); +module \$_DFF_PP0_ (input D, C, R, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R)); + FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -// Sync reset, enable. - -module \$_SDFFE_NP0P_ (input D, C, E, R, output Q); +module \$_DFF_NN1_ (input D, C, R, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R)); + FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); +module \$_DFF_NP1_ (input D, C, R, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R)); + FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule - -module \$_SDFFE_NP1P_ (input D, C, E, R, output Q); +module \$_DFF_PN1_ (input D, C, R, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R)); + FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -module \$_SDFFE_PP1P_ (input D, C, E, R, output Q); +module \$_DFF_PP1_ (input D, C, R, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; - FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R)); + FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -// Latches (no reset). - module \$_DLATCH_N_ (input E, D, output Q); parameter _TECHMAP_WIREINIT_Q_ = 1'bx; LDCE #(.INIT(_TECHMAP_WIREINIT_Q_), .IS_G_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(1'b0)); @@ -172,7 +112,5 @@ module \$_DLATCH_P_ (input E, D, output Q); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule -// Latches with reset (TODO). - `endif diff --git a/techlibs/xilinx/xc7_xcu_brams.txt b/techlibs/xilinx/xc7_xcu_brams.txt index 9ab23521838..9d94e284c42 100644 --- a/techlibs/xilinx/xc7_xcu_brams.txt +++ b/techlibs/xilinx/xc7_xcu_brams.txt @@ -1,4 +1,3 @@ -# Virtex 6, Series 7, Ultrascale, Ultrascale Plus block RAM rules. bram $__XILINX_RAMB36_SDP init 1 @@ -77,18 +76,8 @@ match $__XILINX_RAMB36_SDP or_next_if_better endmatch -match $__XILINX_RAMB36_SDP - attribute ram_style=block ram_block - attribute !logic_block - shuffle_enable B - make_transp - or_next_if_better -endmatch - match $__XILINX_RAMB18_SDP - attribute !ram_style - attribute !logic_block - min bits 1024 + min bits 4096 min efficiency 5 shuffle_enable B make_transp @@ -103,28 +92,10 @@ match $__XILINX_RAMB36_TDP or_next_if_better endmatch -match $__XILINX_RAMB36_TDP - attribute ram_style=block ram_block - attribute !logic_block - shuffle_enable B - make_transp - or_next_if_better -endmatch - match $__XILINX_RAMB18_TDP - attribute !ram_style - attribute !logic_block - min bits 1024 + min bits 4096 min efficiency 5 shuffle_enable B make_transp - or_next_if_better -endmatch - -match $__XILINX_RAMB18_TDP - attribute ram_style=block ram_block - attribute !logic_block - shuffle_enable B - make_transp endmatch diff --git a/techlibs/xilinx/xcu_brams_map.v b/techlibs/xilinx/xcu_brams_map.v index b6719b2ddeb..6e7925b57bf 100644 --- a/techlibs/xilinx/xcu_brams_map.v +++ b/techlibs/xilinx/xcu_brams_map.v @@ -1,5 +1,3 @@ -// Ultrascale and Ultrascale Plus block RAM mapping. - module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); parameter CLKPOL2 = 1; parameter CLKPOL3 = 1; diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc deleted file mode 100644 index 365f505fb34..00000000000 --- a/techlibs/xilinx/xilinx_dffopt.cc +++ /dev/null @@ -1,368 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * 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 - -typedef std::pair> LutData; - -// Compute a LUT implementing (select ^ select_inv) ? alt_data : data. Returns true if successful. -bool merge_lut(LutData &result, const LutData &data, const LutData select, bool select_inv, SigBit alt_data, int max_lut_size) { - // First, gather input signals -- insert new signals at the beginning - // of the vector, so they don't disturb the likely-critical D LUT input - // timings. - result.second = data.second; - // D lut inputs initially start at 0. - int idx_data = 0; - // Now add the control input LUT inputs. - std::vector idx_sel; - for (auto bit : select.second) { - int idx = -1; - for (int i = 0; i < GetSize(result.second); i++) - if (result.second[i] == bit) - idx = i; - if (idx == -1) { - idx = 0; - // Insert new signal at the beginning and bump all indices. - result.second.insert(result.second.begin(), bit); - idx_data++; - for (int &sidx : idx_sel) - sidx++; - } - idx_sel.push_back(idx); - } - // Insert the Q signal, if any, to the slowest input -- it will have - // no problem meeting timing. - int idx_alt = -1; - if (alt_data.wire) { - // Check if we already have it. - for (int i = 0; i < GetSize(result.second); i++) - if (result.second[i] == alt_data) - idx_alt = i; - // If not, add it. - if (idx_alt == -1) { - idx_alt = 0; - result.second.insert(result.second.begin(), alt_data); - idx_data++; - for (int &sidx : idx_sel) - sidx++; - } - } - - // If LUT would be too large, bail. - if (GetSize(result.second) > max_lut_size) - return false; - - // Okay, we're doing it — compute the LUT mask. - result.first = Const(0, 1 << GetSize(result.second)); - for (int i = 0; i < GetSize(result.first); i++) { - int sel_lut_idx = 0; - for (int j = 0; j < GetSize(select.second); j++) - if (i & 1 << idx_sel[j]) - sel_lut_idx |= 1 << j; - bool select_val = (select.first.bits[sel_lut_idx] == State::S1); - bool new_bit; - if (select_val ^ select_inv) { - // Use alt_data. - if (alt_data.wire) - new_bit = (i & 1 << idx_alt) != 0; - else - new_bit = alt_data.data == State::S1; - } else { - // Use original LUT. - int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1); - new_bit = data.first.bits[lut_idx] == State::S1; - } - result.first.bits[i] = new_bit ? State::S1 : State::S0; - } - return true; -} - -struct XilinxDffOptPass : public Pass { - XilinxDffOptPass() : Pass("xilinx_dffopt", "Xilinx: optimize FF control signal usage") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" xilinx_dffopt [options] [selection]\n"); - log("\n"); - log("Converts hardware clock enable and set/reset signals on FFs to emulation\n"); - log("using LUTs, if doing so would improve area. Operates on post-techmap Xilinx\n"); - log("cells (LUT*, FD*).\n"); - log("\n"); - log(" -lut4\n"); - log(" Assume a LUT4-based device (instead of a LUT6-based device).\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - log_header(design, "Executing XILINX_DFFOPT pass (optimize FF control signal usage).\n"); - - size_t argidx; - int max_lut_size = 6; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-lut4") { - max_lut_size = 4; - continue; - } - break; - } - extra_args(args, argidx, design); - - for (auto module : design->selected_modules()) - { - log("Optimizing FFs in %s.\n", log_id(module)); - - SigMap sigmap(module); - dict> bit_to_lut; - dict bit_uses; - - // Gather LUTs. - for (auto cell : module->selected_cells()) - { - for (auto port : cell->connections()) - for (auto bit : port.second) - bit_uses[sigmap(bit)]++; - if (cell->get_bool_attribute(ID::keep)) - continue; - if (cell->type == ID(INV)) { - SigBit sigout = sigmap(cell->getPort(ID::O)); - SigBit sigin = sigmap(cell->getPort(ID::I)); - bit_to_lut[sigout] = make_pair(LutData(Const(1, 2), {sigin}), cell); - } else if (cell->type.in(ID(LUT1), ID(LUT2), ID(LUT3), ID(LUT4), ID(LUT5), ID(LUT6))) { - SigBit sigout = sigmap(cell->getPort(ID::O)); - const Const &init = cell->getParam(ID::INIT); - std::vector sigin; - sigin.push_back(sigmap(cell->getPort(ID(I0)))); - if (cell->type == ID(LUT1)) - goto lut_sigin_done; - sigin.push_back(sigmap(cell->getPort(ID(I1)))); - if (cell->type == ID(LUT2)) - goto lut_sigin_done; - sigin.push_back(sigmap(cell->getPort(ID(I2)))); - if (cell->type == ID(LUT3)) - goto lut_sigin_done; - sigin.push_back(sigmap(cell->getPort(ID(I3)))); - if (cell->type == ID(LUT4)) - goto lut_sigin_done; - sigin.push_back(sigmap(cell->getPort(ID(I4)))); - if (cell->type == ID(LUT5)) - goto lut_sigin_done; - sigin.push_back(sigmap(cell->getPort(ID(I5)))); -lut_sigin_done: - bit_to_lut[sigout] = make_pair(LutData(init, sigin), cell); - } - } - for (auto wire : module->wires()) - if (wire->port_output || wire->port_input) - for (int i = 0; i < GetSize(wire); i++) - bit_uses[sigmap(SigBit(wire, i))]++; - - // Iterate through FFs. - for (auto cell : module->selected_cells()) - { - bool has_s = false, has_r = false; - if (cell->type.in(ID(FDCE), ID(FDPE), ID(FDCPE), ID(FDCE_1), ID(FDPE_1), ID(FDCPE_1))) { - // Async reset. - } else if (cell->type.in(ID(FDRE), ID(FDRE_1))) { - has_r = true; - } else if (cell->type.in(ID(FDSE), ID(FDSE_1))) { - has_s = true; - } else if (cell->type.in(ID(FDRSE), ID(FDRSE_1))) { - has_r = true; - has_s = true; - } else { - // Not a FF. - continue; - } - if (cell->get_bool_attribute(ID::keep)) - continue; - - // Don't bother if D has more than one use. - SigBit sig_D = sigmap(cell->getPort(ID::D)); - if (bit_uses[sig_D] > 2) - continue; - - // Find the D LUT. - auto it_D = bit_to_lut.find(sig_D); - if (it_D == bit_to_lut.end()) - continue; - LutData lut_d = it_D->second.first; - Cell *cell_d = it_D->second.second; - if (cell->getParam(ID(IS_D_INVERTED)).as_bool()) { - // Flip all bits in the LUT. - for (int i = 0; i < GetSize(lut_d.first); i++) - lut_d.first.bits[i] = (lut_d.first.bits[i] == State::S1) ? State::S0 : State::S1; - } - - LutData lut_d_post_ce; - LutData lut_d_post_s; - LutData lut_d_post_r; - bool worthy_post_ce = false; - bool worthy_post_s = false; - bool worthy_post_r = false; - - // First, unmap CE. - SigBit sig_Q = sigmap(cell->getPort(ID::Q)); - SigBit sig_CE = sigmap(cell->getPort(ID(CE))); - LutData lut_ce = LutData(Const(2, 2), {sig_CE}); - auto it_CE = bit_to_lut.find(sig_CE); - if (it_CE != bit_to_lut.end()) - lut_ce = it_CE->second.first; - if (sig_CE.wire) { - // Merge CE LUT and D LUT into one. If it cannot be done, nothing to do about this FF. - if (!merge_lut(lut_d_post_ce, lut_d, lut_ce, true, sig_Q, max_lut_size)) - continue; - - // If this gets rid of a CE LUT, it's worth it. If not, it still may be worth it, if we can remove set/reset as well. - if (it_CE != bit_to_lut.end()) - worthy_post_ce = true; - } else if (sig_CE.data != State::S1) { - // Strange. Should not happen in a reasonable flow, so bail. - continue; - } else { - lut_d_post_ce = lut_d; - } - - // Second, unmap S, if any. - lut_d_post_s = lut_d_post_ce; - if (has_s) { - SigBit sig_S = sigmap(cell->getPort(ID::S)); - LutData lut_s = LutData(Const(2, 2), {sig_S}); - bool inv_s = cell->getParam(ID(IS_S_INVERTED)).as_bool(); - auto it_S = bit_to_lut.find(sig_S); - if (it_S != bit_to_lut.end()) - lut_s = it_S->second.first; - if (sig_S.wire) { - // Merge S LUT and D LUT into one. If it cannot be done, try to at least merge CE. - if (!merge_lut(lut_d_post_s, lut_d_post_ce, lut_s, inv_s, SigBit(State::S1), max_lut_size)) - goto unmap; - // If this gets rid of an S LUT, it's worth it. - if (it_S != bit_to_lut.end()) - worthy_post_s = true; - } else if (sig_S.data != (inv_s ? State::S1 : State::S0)) { - // Strange. Should not happen in a reasonable flow, so bail. - continue; - } - } - - // Third, unmap R, if any. - lut_d_post_r = lut_d_post_s; - if (has_r) { - SigBit sig_R = sigmap(cell->getPort(ID::R)); - LutData lut_r = LutData(Const(2, 2), {sig_R}); - bool inv_r = cell->getParam(ID(IS_R_INVERTED)).as_bool(); - auto it_R = bit_to_lut.find(sig_R); - if (it_R != bit_to_lut.end()) - lut_r = it_R->second.first; - if (sig_R.wire) { - // Merge R LUT and D LUT into one. If it cannot be done, try to at least merge CE/S. - if (!merge_lut(lut_d_post_r, lut_d_post_s, lut_r, inv_r, SigBit(State::S0), max_lut_size)) - goto unmap; - // If this gets rid of an S LUT, it's worth it. - if (it_R != bit_to_lut.end()) - worthy_post_r = true; - } else if (sig_R.data != (inv_r ? State::S1 : State::S0)) { - // Strange. Should not happen in a reasonable flow, so bail. - continue; - } - } - -unmap: - LutData final_lut; - if (worthy_post_r) { - final_lut = lut_d_post_r; - } else if (worthy_post_s) { - final_lut = lut_d_post_s; - } else if (worthy_post_ce) { - final_lut = lut_d_post_ce; - } else { - // Nothing to do here. - continue; - } - - std::string ports; - if (worthy_post_r) ports += " + R"; - if (worthy_post_s) ports += " + S"; - if (worthy_post_ce) ports += " + CE"; - log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports.c_str(), log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second)); - - // Okay, we're doing it. Unmap ports. - if (worthy_post_r) { - cell->unsetParam(ID(IS_R_INVERTED)); - cell->setPort(ID::R, Const(0, 1)); - } - if (has_s && (worthy_post_r || worthy_post_s)) { - cell->unsetParam(ID(IS_S_INVERTED)); - cell->setPort(ID::S, Const(0, 1)); - } - cell->setPort(ID(CE), Const(1, 1)); - cell->unsetParam(ID(IS_D_INVERTED)); - - // Create the new LUT. - Cell *lut_cell = 0; - switch (GetSize(final_lut.second)) { - case 1: - lut_cell = module->addCell(NEW_ID, ID(LUT1)); - break; - case 2: - lut_cell = module->addCell(NEW_ID, ID(LUT2)); - break; - case 3: - lut_cell = module->addCell(NEW_ID, ID(LUT3)); - break; - case 4: - lut_cell = module->addCell(NEW_ID, ID(LUT4)); - break; - case 5: - lut_cell = module->addCell(NEW_ID, ID(LUT5)); - break; - case 6: - lut_cell = module->addCell(NEW_ID, ID(LUT6)); - break; - default: - log_assert(!"unknown lut size"); - } - lut_cell->attributes = cell_d->attributes; - Wire *lut_out = module->addWire(NEW_ID); - lut_cell->setParam(ID::INIT, final_lut.first); - cell->setPort(ID::D, lut_out); - lut_cell->setPort(ID::O, lut_out); - lut_cell->setPort(ID(I0), final_lut.second[0]); - if (GetSize(final_lut.second) >= 2) - lut_cell->setPort(ID(I1), final_lut.second[1]); - if (GetSize(final_lut.second) >= 3) - lut_cell->setPort(ID(I2), final_lut.second[2]); - if (GetSize(final_lut.second) >= 4) - lut_cell->setPort(ID(I3), final_lut.second[3]); - if (GetSize(final_lut.second) >= 5) - lut_cell->setPort(ID(I4), final_lut.second[4]); - if (GetSize(final_lut.second) >= 6) - lut_cell->setPort(ID(I5), final_lut.second[5]); - } - } - } -} XilinxDffOptPass; - -PRIVATE_NAMESPACE_END - diff --git a/tests/aiger/.gitignore b/tests/aiger/.gitignore index b76bdb65306..9a26bb8f423 100644 --- a/tests/aiger/.gitignore +++ b/tests/aiger/.gitignore @@ -1,3 +1 @@ /*_ref.v -/*.aag.log -/*.aig.log diff --git a/tests/aiger/neg.ys b/tests/aiger/neg.ys deleted file mode 100644 index 4c1edd8a4f4..00000000000 --- a/tests/aiger/neg.ys +++ /dev/null @@ -1,36 +0,0 @@ -read_verilog <> 12); - j = j ^ (j << 25); - j = j ^ (j >> 27); - end - - always @(posedge clk) begin - data_out_r <= memory[address_in]; - end - - assign data_out = data_out_r; - -endmodule // sync_rom diff --git a/tests/arch/common/lutram.v b/tests/arch/common/lutram.v deleted file mode 100644 index 9534b76198a..00000000000 --- a/tests/arch/common/lutram.v +++ /dev/null @@ -1,42 +0,0 @@ -module lutram_1w1r -#(parameter D_WIDTH=8, A_WIDTH=6) -( - input [D_WIDTH-1:0] data_a, - input [A_WIDTH:1] addr_a, - input we_a, clk, - output reg [D_WIDTH-1:0] q_a -); - // Declare the RAM variable - reg [D_WIDTH-1:0] ram[(2**A_WIDTH)-1:0]; - - // Port A - always @ (posedge clk) - begin - if (we_a) - ram[addr_a] <= data_a; - q_a <= ram[addr_a]; - end -endmodule - - -module lutram_1w3r -#(parameter D_WIDTH=8, A_WIDTH=5) -( - input [D_WIDTH-1:0] data_a, data_b, data_c, - input [A_WIDTH:1] addr_a, addr_b, addr_c, - input we_a, clk, - output reg [D_WIDTH-1:0] q_a, q_b, q_c -); - // Declare the RAM variable - reg [D_WIDTH-1:0] ram[(2**A_WIDTH)-1:0]; - - // Port A - always @ (posedge clk) - begin - if (we_a) - ram[addr_a] <= data_a; - q_a <= ram[addr_a]; - q_b <= ram[addr_b]; - q_c <= ram[addr_c]; - end -endmodule diff --git a/tests/arch/common/memory.v b/tests/arch/common/memory.v new file mode 100644 index 00000000000..cb7753f7b9a --- /dev/null +++ b/tests/arch/common/memory.v @@ -0,0 +1,21 @@ +module top +( + input [7:0] data_a, + input [6:1] addr_a, + input we_a, clk, + output reg [7:0] q_a +); + // Declare the RAM variable + reg [7:0] ram[63:0]; + + // Port A + always @ (posedge clk) + begin + if (we_a) + begin + ram[addr_a] <= data_a; + q_a <= data_a; + end + q_a <= ram[addr_a]; + end +endmodule diff --git a/tests/arch/common/memory_attributes/attributes_test.v b/tests/arch/common/memory_attributes/attributes_test.v deleted file mode 100644 index 275800dd025..00000000000 --- a/tests/arch/common/memory_attributes/attributes_test.v +++ /dev/null @@ -1,88 +0,0 @@ -`default_nettype none -module block_ram #(parameter DATA_WIDTH=4, ADDRESS_WIDTH=10) - (input wire write_enable, clk, - input wire [DATA_WIDTH-1:0] data_in, - input wire [ADDRESS_WIDTH-1:0] address_in, - output wire [DATA_WIDTH-1:0] data_out); - - localparam WORD = (DATA_WIDTH-1); - localparam DEPTH = (2**ADDRESS_WIDTH-1); - - reg [WORD:0] data_out_r; - reg [WORD:0] memory [0:DEPTH]; - - always @(posedge clk) begin - if (write_enable) - memory[address_in] <= data_in; - data_out_r <= memory[address_in]; - end - - assign data_out = data_out_r; -endmodule // block_ram - -`default_nettype none -module distributed_ram #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=4) - (input wire write_enable, clk, - input wire [DATA_WIDTH-1:0] data_in, - input wire [ADDRESS_WIDTH-1:0] address_in, - output wire [DATA_WIDTH-1:0] data_out); - - localparam WORD = (DATA_WIDTH-1); - localparam DEPTH = (2**ADDRESS_WIDTH-1); - - reg [WORD:0] data_out_r; - reg [WORD:0] memory [0:DEPTH]; - - always @(posedge clk) begin - if (write_enable) - memory[address_in] <= data_in; - data_out_r <= memory[address_in]; - end - - assign data_out = data_out_r; -endmodule // distributed_ram - -`default_nettype none -module distributed_ram_manual #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=4) - (input wire write_enable, clk, - input wire [DATA_WIDTH-1:0] data_in, - input wire [ADDRESS_WIDTH-1:0] address_in, - output wire [DATA_WIDTH-1:0] data_out); - - localparam WORD = (DATA_WIDTH-1); - localparam DEPTH = (2**ADDRESS_WIDTH-1); - - reg [WORD:0] data_out_r; - (* ram_style = "block" *) reg [WORD:0] memory [0:DEPTH]; - - always @(posedge clk) begin - if (write_enable) - memory[address_in] <= data_in; - data_out_r <= memory[address_in]; - end - - assign data_out = data_out_r; -endmodule // distributed_ram - -`default_nettype none -module distributed_ram_manual_syn #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=4) - (input wire write_enable, clk, - input wire [DATA_WIDTH-1:0] data_in, - input wire [ADDRESS_WIDTH-1:0] address_in, - output wire [DATA_WIDTH-1:0] data_out); - - localparam WORD = (DATA_WIDTH-1); - localparam DEPTH = (2**ADDRESS_WIDTH-1); - - reg [WORD:0] data_out_r; - (* synthesis, ram_block *) reg [WORD:0] memory [0:DEPTH]; - - always @(posedge clk) begin - if (write_enable) - memory[address_in] <= data_in; - data_out_r <= memory[address_in]; - end - - assign data_out = data_out_r; -endmodule // distributed_ram - diff --git a/tests/arch/ecp5/bug1459.ys b/tests/arch/ecp5/bug1459.ys deleted file mode 100644 index 1142ae0b501..00000000000 --- a/tests/arch/ecp5/bug1459.ys +++ /dev/null @@ -1,25 +0,0 @@ -read_verilog < PDPW16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_ram_sdp -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:PDPW16KD - -## With parameters - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:PDPW16KD # too inefficient -select -assert-count 9 t:TRELLIS_DPR16X4 - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -setattr -set syn_ramstyle "block_ram" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:PDPW16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -setattr -set syn_ramstyle "Block_RAM" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:PDPW16KD # any case works - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -setattr -set ram_block 1 m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:PDPW16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -setattr -set syn_ramstyle "registers" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:PDPW16KD # requested FFRAM explicitly -select -assert-count 180 t:TRELLIS_FF - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -setattr -set logic_block 1 m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:PDPW16KD # requested FFRAM explicitly -select -assert-count 180 t:TRELLIS_FF - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -setattr -set syn_romstyle "ebr" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BROM but this is a RAM - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -setattr -set rom_block 1 m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BROM but this is a RAM - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -setattr -set syn_ramstyle "block_ram" m:memory -synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp -setattr -set ram_block 1 m:memory -synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled - -# RAM bits <= 18K; Data width <= 18; Address width <= 10: -> DP16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:DP16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 9 sync_ram_sdp -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:DP16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 12 -set DATA_WIDTH 4 sync_ram_sdp -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:DP16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 13 -set DATA_WIDTH 2 sync_ram_sdp -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:DP16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 14 -set DATA_WIDTH 1 sync_ram_sdp -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:DP16KD - -## With parameters - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:DP16KD # too inefficient -select -assert-count 5 t:TRELLIS_DPR16X4 - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -setattr -set syn_ramstyle "block_ram" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:DP16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -setattr -set syn_ramstyle "Block_RAM" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:DP16KD # any case works - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -setattr -set ram_block 1 m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:DP16KD - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -setattr -set syn_ramstyle "registers" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:DP16KD # requested FFRAM explicitly -select -assert-count 90 t:TRELLIS_FF - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -setattr -set logic_block 1 m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:DP16KD # requested FFRAM explicitly -select -assert-count 90 t:TRELLIS_FF - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -setattr -set syn_romstyle "ebr" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BROM but this is a RAM - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -setattr -set rom_block 1 m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BROM but this is a RAM - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -setattr -set syn_ramstyle "block_ram" m:memory -synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp -setattr -set ram_block 1 m:memory -synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled - -# RAM bits <= 64; Data width <= 4; Address width <= 4: -> DPR16X4 - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:TRELLIS_DPR16X4 - -## With parameters - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp -setattr -set syn_ramstyle "distributed" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:TRELLIS_DPR16X4 - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp -setattr -set syn_ramstyle "registers" m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:TRELLIS_DPR16X4 # requested FFRAM explicitly -select -assert-count 68 t:TRELLIS_FF - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp -setattr -set logic_block 1 m:memory -synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:TRELLIS_DPR16X4 # requested FFRAM explicitly -select -assert-count 68 t:TRELLIS_FF - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp -setattr -set syn_ramstyle "distributed" m:memory -synth_ecp5 -top sync_ram_sdp -nolutram; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested LUTRAM but LUTRAM is disabled - -# ================================ ROM ================================ -# ROM bits <= 18K; Data width <= 36; Address width <= 9: -> PDPW16KD - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_rom -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:PDPW16KD - -## With parameters - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 0 t:PDPW16KD # too inefficient -select -assert-min 18 t:LUT4 - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom -setattr -set syn_romstyle "ebr" m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:PDPW16KD - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom -setattr -set rom_block 1 m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:PDPW16KD - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom -setattr -set syn_romstyle "logic" m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 0 t:PDPW16KD # requested LUTROM explicitly -select -assert-min 18 t:LUT4 - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom -setattr -set logic_block 1 m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 0 t:PDPW16KD # requested LUTROM explicitly -select -assert-min 18 t:LUT4 - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom -setattr -set syn_ramstyle "block_ram" m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:$mem # requested BRAM but this is a ROM - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom -setattr -set ram_block 1 m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:$mem # requested BRAM but this is a ROM - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom -setattr -set syn_ramstyle "block_rom" m:memory -synth_ecp5 -top sync_rom -nobram; cd sync_rom -select -assert-count 1 t:$mem # requested BROM but BRAM is disabled - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom -setattr -set rom_block 1 m:memory -synth_ecp5 -top sync_rom -nobram; cd sync_rom -select -assert-count 1 t:$mem # requested BROM but BRAM is disabled - -# ROM bits <= 18K; Data width <= 18; Address width <= 10: -> DP16KD - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_rom -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:DP16KD - -## With parameters - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 0 t:DP16KD # too inefficient -select -assert-min 9 t:LUT4 - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom -setattr -set syn_romstyle "ebr" m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:DP16KD - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom -setattr -set rom_block 1 m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:DP16KD - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom -setattr -set syn_romstyle "logic" m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 0 t:DP16KD # requested LUTROM explicitly -select -assert-min 9 t:LUT4 - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom -setattr -set logic_block 1 m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 0 t:DP16KD # requested LUTROM explicitly -select -assert-min 9 t:LUT4 - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom -setattr -set syn_ramstyle "block_ram" m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:$mem # requested BRAM but this is a ROM - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom -setattr -set ram_block 1 m:memory -synth_ecp5 -top sync_rom; cd sync_rom -select -assert-count 1 t:$mem # requested BRAM but this is a ROM - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom -setattr -set syn_ramstyle "block_rom" m:memory -synth_ecp5 -top sync_rom -nobram; cd sync_rom -select -assert-count 1 t:$mem # requested BROM but BRAM is disabled - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom -setattr -set rom_block 1 m:memory -synth_ecp5 -top sync_rom -nobram; cd sync_rom -select -assert-count 1 t:$mem # requested BROM but BRAM is disabled diff --git a/tests/arch/ecp5/lutram.ys b/tests/arch/ecp5/memory.ys similarity index 87% rename from tests/arch/ecp5/lutram.ys rename to tests/arch/ecp5/memory.ys index e1ae7abd524..c82b7b4054d 100644 --- a/tests/arch/ecp5/lutram.ys +++ b/tests/arch/ecp5/memory.ys @@ -1,5 +1,5 @@ -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r +read_verilog ../common/memory.v +hierarchy -top top proc memory -nomap equiv_opt -run :prove -map +/ecp5/cells_sim.v synth_ecp5 @@ -10,7 +10,7 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter design -load postopt -cd lutram_1w1r +cd top select -assert-count 24 t:L6MUX21 select -assert-count 71 t:LUT4 select -assert-count 32 t:PFUMX diff --git a/tests/arch/ecp5/mul.ys b/tests/arch/ecp5/mul.ys index f887e958589..2105be52ce7 100644 --- a/tests/arch/ecp5/mul.ys +++ b/tests/arch/ecp5/mul.ys @@ -3,9 +3,9 @@ hierarchy -top top proc # Blocked by issue #1358 (Missing ECP5 simulation models) #equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -synth_ecp5 +equiv_opt -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -#design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:MULT18X18D select -assert-none t:MULT18X18D %% t:* %D diff --git a/tests/arch/ecp5/opt_lut_ins.ys b/tests/arch/ecp5/opt_lut_ins.ys deleted file mode 100644 index 2bc5469120d..00000000000 --- a/tests/arch/ecp5/opt_lut_ins.ys +++ /dev/null @@ -1,32 +0,0 @@ -read_ilang << EOF - -module \top - - wire input 1 \A - wire input 2 \B - wire input 3 \C - wire input 4 \D - - wire output 5 \Z - - cell \LUT4 $0 - parameter \INIT 16'1111110011000000 - connect \A \A - connect \B \B - connect \C \C - connect \D \D - connect \Z \Z - end -end - -EOF - -read_verilog -lib +/ecp5/cells_sim.v - -equiv_opt -assert -map +/ecp5/cells_sim.v opt_lut_ins -tech ecp5 - -design -load postopt - -select -assert-count 1 top/t:LUT4 -select -assert-count 0 top/w:A %co top/t:LUT4 %i -select -assert-count 1 top/w:B %co top/t:LUT4 %i diff --git a/tests/arch/efinix/counter.ys b/tests/arch/efinix/counter.ys index f8fb29a87b1..d20b8ae271f 100644 --- a/tests/arch/efinix/counter.ys +++ b/tests/arch/efinix/counter.ys @@ -2,7 +2,7 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -assert -multiclock -map +/efinix/cells_sim.v synth_efinix # equivalency check +equiv_opt -map +/efinix/cells_sim.v synth_efinix # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/efinix/fsm.ys b/tests/arch/efinix/fsm.ys index aef720d4662..a2db2ad987a 100644 --- a/tests/arch/efinix/fsm.ys +++ b/tests/arch/efinix/fsm.ys @@ -10,6 +10,7 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd fsm # Constrain all select calls below inside the top module -select -assert-count 1 t:EFX_GBUFCE -select -assert-count 6 t:EFX_FF +select -assert-count 1 t:EFX_GBUFCE +select -assert-count 6 t:EFX_FF +select -assert-count 15 t:EFX_LUT4 select -assert-none t:EFX_GBUFCE t:EFX_FF t:EFX_LUT4 %% t:* %D diff --git a/tests/arch/efinix/lutram.ys b/tests/arch/efinix/memory.ys similarity index 87% rename from tests/arch/efinix/lutram.ys rename to tests/arch/efinix/memory.ys index dcf647ce0f9..6f6acdcde0f 100644 --- a/tests/arch/efinix/lutram.ys +++ b/tests/arch/efinix/memory.ys @@ -1,5 +1,5 @@ -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r +read_verilog ../common/memory.v +hierarchy -top top proc memory -nomap equiv_opt -run :prove -map +/efinix/cells_sim.v synth_efinix @@ -12,7 +12,7 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter design -load postopt -cd lutram_1w1r +cd top select -assert-count 1 t:EFX_GBUFCE select -assert-count 1 t:EFX_RAM_5K select -assert-none t:EFX_GBUFCE t:EFX_RAM_5K %% t:* %D diff --git a/tests/arch/efinix/mux.ys b/tests/arch/efinix/mux.ys index 67006b6f253..b46f641e16b 100644 --- a/tests/arch/efinix/mux.ys +++ b/tests/arch/efinix/mux.ys @@ -16,7 +16,7 @@ proc equiv_opt -assert -map +/efinix/cells_sim.v synth_efinix # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux4 # Constrain all select calls below inside the top module -#select -assert-count 2 t:EFX_LUT4 +select -assert-count 2 t:EFX_LUT4 select -assert-none t:EFX_LUT4 %% t:* %D @@ -26,7 +26,7 @@ proc equiv_opt -assert -map +/efinix/cells_sim.v synth_efinix # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module -#select -assert-count 5 t:EFX_LUT4 +select -assert-count 5 t:EFX_LUT4 select -assert-none t:EFX_LUT4 %% t:* %D @@ -36,6 +36,6 @@ proc equiv_opt -assert -map +/efinix/cells_sim.v synth_efinix # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module -select -assert-max 12 t:EFX_LUT4 +select -assert-count 12 t:EFX_LUT4 select -assert-none t:EFX_LUT4 %% t:* %D diff --git a/tests/arch/gowin/counter.ys b/tests/arch/gowin/counter.ys index bdbc7ee2432..920479d44c6 100644 --- a/tests/arch/gowin/counter.ys +++ b/tests/arch/gowin/counter.ys @@ -2,7 +2,7 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -assert -multiclock -map +/gowin/cells_sim.v synth_gowin # equivalency check +equiv_opt -map +/gowin/cells_sim.v synth_gowin # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/gowin/lutram.ys b/tests/arch/gowin/memory.ys similarity index 87% rename from tests/arch/gowin/lutram.ys rename to tests/arch/gowin/memory.ys index 56f69e7c547..8f88cdd7c63 100644 --- a/tests/arch/gowin/lutram.ys +++ b/tests/arch/gowin/memory.ys @@ -1,5 +1,5 @@ -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r +read_verilog ../common/memory.v +hierarchy -top top proc memory -nomap equiv_opt -run :prove -map +/gowin/cells_sim.v synth_gowin @@ -12,7 +12,7 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter design -load postopt -cd lutram_1w1r +cd top select -assert-count 8 t:RAM16S4 # other logic present that is not simple #select -assert-none t:RAM16S4 %% t:* %D diff --git a/tests/arch/gowin/mux.ys b/tests/arch/gowin/mux.ys index 33b092284fa..afad29a8960 100644 --- a/tests/arch/gowin/mux.ys +++ b/tests/arch/gowin/mux.ys @@ -18,13 +18,13 @@ proc equiv_opt -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux4 # Constrain all select calls below inside the top module -select -assert-count 4 t:LUT* +select -assert-count 4 t:LUT4 select -assert-count 2 t:MUX2_LUT5 select -assert-count 1 t:MUX2_LUT6 select -assert-count 6 t:IBUF select -assert-count 1 t:OBUF -select -assert-none t:LUT* t:MUX2_LUT6 t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT4 t:MUX2_LUT6 t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D design -load read hierarchy -top mux8 @@ -35,7 +35,7 @@ cd mux8 # Constrain all select calls below inside the top module select -assert-count 11 t:IBUF select -assert-count 1 t:OBUF -select -assert-none t:LUT* t:MUX2_LUT6 t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT4 t:MUX2_LUT6 t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D design -load read hierarchy -top mux16 @@ -46,4 +46,4 @@ cd mux16 # Constrain all select calls below inside the top module select -assert-count 20 t:IBUF select -assert-count 1 t:OBUF -select -assert-none t:GND t:VCC t:LUT* t:MUX2_LUT6 t:MUX2_LUT5 t:MUX2_LUT6 t:MUX2_LUT7 t:MUX2_LUT8 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT4 t:MUX2_LUT6 t:MUX2_LUT5 t:MUX2_LUT6 t:MUX2_LUT7 t:MUX2_LUT8 t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/ice40/bug1597.ys b/tests/arch/ice40/bug1597.ys deleted file mode 100644 index b7983cfa40b..00000000000 --- a/tests/arch/ice40/bug1597.ys +++ /dev/null @@ -1,72 +0,0 @@ -read_verilog < SB_RAM40_4K - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 2 sync_ram_sdp -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 4 sync_ram_sdp -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 8 sync_ram_sdp -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 16 sync_ram_sdp -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:SB_RAM40_4K - -## With parameters - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:SB_RAM40_4K # too inefficient -select -assert-min 1 t:SB_DFFE - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -setattr -set syn_ramstyle "block_ram" m:memory -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -setattr -set syn_ramstyle "Block_RAM" m:memory -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:SB_RAM40_4K # any case works - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -setattr -set ram_block 1 m:memory -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -setattr -set syn_ramstyle "registers" m:memory -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly -select -assert-min 1 t:SB_DFFE - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -setattr -set logic_block 1 m:memory -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly -select -assert-min 1 t:SB_DFFE - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -setattr -set syn_romstyle "ebr" m:memory -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BROM but this is a RAM - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -setattr -set rom_block 1 m:memory -synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BROM but this is a RAM - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -setattr -set syn_ramstyle "block_ram" m:memory -synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled - -design -reset; read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp -setattr -set ram_block 1 m:memory -synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp -select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled - -# ================================ ROM ================================ -# ROM bits <= 4K; Data width <= 16; Address width <= 11: -> SB_RAM40_4K - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 2 sync_rom -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 4 sync_rom -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 8 sync_rom -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 16 sync_rom -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 1 t:SB_RAM40_4K - -## With parameters - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 0 t:SB_RAM40_4K # too inefficient -select -assert-min 1 t:SB_LUT4 - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -setattr -set syn_romstyle "ebr" m:memory -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -setattr -set rom_block 1 m:memory -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 1 t:SB_RAM40_4K - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -setattr -set syn_romstyle "logic" m:memory -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly -select -assert-min 1 t:SB_LUT4 - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -setattr -set logic_block 1 m:memory -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly -select -assert-min 1 t:SB_LUT4 - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -setattr -set syn_ramstyle "block_ram" m:memory -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 1 t:$mem # requested BRAM but this is a ROM - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -setattr -set ram_block 1 m:memory -synth_ice40 -top sync_rom; cd sync_rom -select -assert-count 1 t:$mem # requested BRAM but this is a ROM - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -setattr -set syn_romstyle "ebr" m:memory -synth_ice40 -top sync_rom -nobram; cd sync_rom -select -assert-count 1 t:$mem # requested BROM but BRAM is disabled - -design -reset; read_verilog ../common/blockrom.v -chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -setattr -set rom_block 1 m:memory -synth_ice40 -top sync_rom -nobram; cd sync_rom -select -assert-count 1 t:$mem # requested BROM but BRAM is disabled diff --git a/tests/arch/ice40/memory.ys b/tests/arch/ice40/memory.ys new file mode 100644 index 00000000000..c356e67fbb6 --- /dev/null +++ b/tests/arch/ice40/memory.ys @@ -0,0 +1,15 @@ +read_verilog ../common/memory.v +hierarchy -top top +proc +memory -nomap +equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40 +memory +opt -full + +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter + +design -load postopt +cd top +select -assert-count 1 t:SB_RAM40_4K +select -assert-none t:SB_RAM40_4K %% t:* %D diff --git a/tests/arch/ice40/mul.ys b/tests/arch/ice40/mul.ys index b8c3eb94139..9891b77d633 100644 --- a/tests/arch/ice40/mul.ys +++ b/tests/arch/ice40/mul.ys @@ -1,6 +1,6 @@ read_verilog ../common/mul.v hierarchy -top top -equiv_opt -assert -multiclock -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:SB_MAC16 diff --git a/tests/arch/ice40/mux.ys b/tests/arch/ice40/mux.ys index 2b661fd6b1a..99822391d49 100644 --- a/tests/arch/ice40/mux.ys +++ b/tests/arch/ice40/mux.ys @@ -35,7 +35,6 @@ proc equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module -select -assert-min 11 t:SB_LUT4 -select -assert-max 12 t:SB_LUT4 +select -assert-count 11 t:SB_LUT4 select -assert-none t:SB_LUT4 %% t:* %D diff --git a/tests/arch/ice40/rom.v b/tests/arch/ice40/rom.v index 71459fe38de..0a0f41f3754 100644 --- a/tests/arch/ice40/rom.v +++ b/tests/arch/ice40/rom.v @@ -2,8 +2,7 @@ Example from: https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071 [p. 74]. */ module top(data, addr); -output [3:0] data; // Note: this prompts a Yosys warning, but - // vendor doc does not contain 'reg' +output [3:0] data; input [4:0] addr; always @(addr) begin case (addr) diff --git a/tests/arch/ice40/wrapcarry.ys b/tests/arch/ice40/wrapcarry.ys new file mode 100644 index 00000000000..10c029e6892 --- /dev/null +++ b/tests/arch/ice40/wrapcarry.ys @@ -0,0 +1,22 @@ +read_verilog < run-test.mk -exec ${MAKE:-make} -f run-test.mk diff --git a/tests/arch/intel_alm/shifter.ys b/tests/arch/intel_alm/shifter.ys deleted file mode 100644 index 014dbd1a8dc..00000000000 --- a/tests/arch/intel_alm/shifter.ys +++ /dev/null @@ -1,10 +0,0 @@ -read_verilog ../common/shifter.v -hierarchy -top top -proc -flatten -equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 8 t:MISTRAL_FF - -select -assert-none t:MISTRAL_FF %% t:* %D diff --git a/tests/arch/intel_alm/tribuf.ys b/tests/arch/intel_alm/tribuf.ys deleted file mode 100644 index 71b05a74733..00000000000 --- a/tests/arch/intel_alm/tribuf.ys +++ /dev/null @@ -1,13 +0,0 @@ -read_verilog ../common/tribuf.v -hierarchy -top tristate -proc -tribuf -flatten -synth -equiv_opt -assert -map +/simcells.v synth_intel_alm -family cyclonev # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd tristate # Constrain all select calls below inside the top module -#Internal cell type used. Need support it. -select -assert-count 1 t:$_TBUF_ - -select -assert-none t:$_TBUF_ %% t:* %D diff --git a/tests/arch/run-test.sh b/tests/arch/run-test.sh index 170078a7fde..5292d161556 100755 --- a/tests/arch/run-test.sh +++ b/tests/arch/run-test.sh @@ -2,23 +2,12 @@ set -e -declare -A defines=( ["ice40"]="ICE40_HX ICE40_LP ICE40_U" ) - echo "Running syntax check on arch sim models" for arch in ../../techlibs/*; do find $arch -name cells_sim.v | while read path; do - arch_name=$(basename -- $arch) - if [ "${defines[$arch_name]}" ]; then - for def in ${defines[$arch_name]}; do - echo -n "Test $path -D$def ->" - iverilog -t null -I$arch -D$def $path - echo " ok" - done - else - echo -n "Test $path ->" - iverilog -t null -I$arch $path - echo " ok" - fi + echo -n "Test $path ->" + iverilog -t null -I$arch $path + echo " ok" done done diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys deleted file mode 100644 index 210e87477ce..00000000000 --- a/tests/arch/xilinx/abc9_dff.ys +++ /dev/null @@ -1,134 +0,0 @@ -logger -nowarn "Yosys has only limited support for tri-state logic at the moment\. .*" - -read_verilog < RAMB18E1 -read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 1 sync_ram_sdp -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 1 t:RAMB18E1 - -design -reset -read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 18 sync_ram_sdp -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 1 t:RAMB18E1 - -design -reset -read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 14 -set DATA_WIDTH 1 sync_ram_sdp -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 1 t:RAMB18E1 - -design -reset -read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_ram_sdp -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 1 t:RAMB18E1 - -# Anything memory bits < 1024 -> LUTRAM -design -reset -read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 2 sync_ram_sdp -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 0 t:RAMB18E1 -select -assert-count 4 t:RAM128X1D - -# More than 18K bits, data width <= 36 (TDP), and address width from 10 to 15b (non-cascaded) -> RAMB36E1 -design -reset -read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 36 sync_ram_sdp -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 1 t:RAMB36E1 - - -### With parameters - -design -reset -read_verilog ../common/blockram.v -hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 10 -chparam DATA_WIDTH 1 -setattr -set ram_style "block" m:memory -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 1 t:RAMB18E1 - -design -reset -read_verilog ../common/blockram.v -hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 10 -chparam DATA_WIDTH 1 -setattr -set ram_block 1 m:memory -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 1 t:RAMB18E1 - -design -reset -read_verilog ../common/blockram.v -hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 10 -chparam DATA_WIDTH 1 -setattr -set ram_style "dont_infer_a_ram_pretty_please" m:memory -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 0 t:RAMB18E1 - -design -reset -read_verilog ../common/blockram.v -hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 10 -chparam DATA_WIDTH 1 -setattr -set logic_block 1 m:memory -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 0 t:RAMB18E1 - -design -reset -read_verilog ../common/blockram.v -hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 8 -chparam DATA_WIDTH 1 -setattr -set ram_style "block" m:memory -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 1 t:RAMB18E1 - -design -reset -read_verilog ../common/blockram.v -hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 8 -chparam DATA_WIDTH 1 -setattr -set ram_block 1 m:memory -synth_xilinx -top sync_ram_sdp -noiopad -cd sync_ram_sdp -select -assert-count 1 t:RAMB18E1 diff --git a/tests/arch/xilinx/bug1460.ys b/tests/arch/xilinx/bug1460.ys deleted file mode 100644 index 09935ccd80d..00000000000 --- a/tests/arch/xilinx/bug1460.ys +++ /dev/null @@ -1,34 +0,0 @@ -read_verilog < DSP48E1.PCIN -# (i.e. Take all DSP48E1s, expand to find all wires connected -# to its PCOUT port, then remove all DSP48E1s from this -# selection, then expand again to find all cells where -# those wires are connected to the PCIN port, then remove -# all wires from this selection, and lastly intersect -# this selection with all DSP48E1 cells (to check that -# the connected cells are indeed DSPs) -select -assert-count 2 t:DSP48E1 %co:+[PCOUT] t:DSP48E1 %d %co:+[PCIN] w:* %d t:DSP48E1 %i - -design -load read -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s -noiopad -design -load postopt -cd cascade -select -assert-count 3 t:DSP48A1 -select -assert-count 5 t:FDRE # No cascade for A input -select -assert-none t:DSP48A1 t:BUFG t:FDRE %% t:* %D -# Very crude method of checking that DSP48E1.PCOUT -> DSP48E1.PCIN -# (see above for explanation) -select -assert-count 2 t:DSP48A1 %co:+[PCOUT] t:DSP48A1 %d %co:+[PCIN] w:* %d t:DSP48A1 %i - -design -reset -read_verilog < DSP48E1.PCIN -# (see above for explanation) -select -assert-count 1 t:DSP48E1 %co:+[PCOUT] t:DSP48E1 %d %co:+[PCIN] w:* %d t:DSP48E1 %i - -design -load read -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s -noiopad -design -load postopt -cd cascade -select -assert-count 2 t:DSP48A1 -select -assert-count 10 t:FDRE # Cannot cascade because first 'm' DSP - # uses both B0REG and B1REG, whereas 'o' - # only requires 1 -select -assert-none t:DSP48A1 t:BUFG t:FDRE %% t:* %D -# Very crude method of checking that DSP48E1.PCOUT -> DSP48E1.PCIN -# (see above for explanation) -select -assert-count 1 t:DSP48A1 %co:+[PCOUT] t:DSP48A1 %d %co:+[PCIN] w:* %d t:DSP48A1 %i - diff --git a/tests/arch/xilinx/dsp_fastfir.ys b/tests/arch/xilinx/dsp_fastfir.ys index 57fe49bde8f..0067a822b42 100644 --- a/tests/arch/xilinx/dsp_fastfir.ys +++ b/tests/arch/xilinx/dsp_fastfir.ys @@ -63,7 +63,7 @@ module fastfir_dynamictaps(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_re endmodule EOT -synth_xilinx -noiopad +synth_xilinx cd fastfir_dynamictaps select -assert-count 2 t:DSP48E1 select -assert-none t:* t:DSP48E1 %d t:BUFG %d diff --git a/tests/arch/xilinx/fsm.ys b/tests/arch/xilinx/fsm.ys index fec4c6082bc..2a72c34e809 100644 --- a/tests/arch/xilinx/fsm.ys +++ b/tests/arch/xilinx/fsm.ys @@ -3,36 +3,16 @@ hierarchy -top fsm proc flatten -design -save orig - -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx miter -equiv -make_assert -flatten gold gate miter sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd fsm # Constrain all select calls below inside the top module -stat -select -assert-count 1 t:BUFG -select -assert-count 4 t:FDRE -select -assert-count 1 t:FDSE -select -assert-count 1 t:LUT2 -select -assert-count 3 t:LUT5 -select -assert-count 1 t:LUT6 -select -assert-none t:BUFG t:FDRE t:FDSE t:LUT2 t:LUT5 t:LUT6 %% t:* %D - -design -load orig - -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -family xc3se -noiopad -miter -equiv -make_assert -flatten gold gate miter -sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd fsm # Constrain all select calls below inside the top module -stat select -assert-count 1 t:BUFG -select -assert-count 6 t:FDRE -select -assert-count 1 t:LUT1 -select -assert-count 3 t:LUT3 -select -assert-count 6 t:LUT4 -select -assert-count 6 t:MUXF5 -select -assert-none t:BUFG t:FDRE t:LUT1 t:LUT3 t:LUT4 t:MUXF5 %% t:* %D +select -assert-count 5 t:FDRE +select -assert-count 1 t:LUT3 +select -assert-count 2 t:LUT4 +select -assert-count 4 t:LUT6 +select -assert-none t:BUFG t:FDRE t:LUT3 t:LUT4 t:LUT6 %% t:* %D diff --git a/tests/arch/xilinx/latches.ys b/tests/arch/xilinx/latches.ys index e226c2ec8a6..c87a8e38b1c 100644 --- a/tests/arch/xilinx/latches.ys +++ b/tests/arch/xilinx/latches.ys @@ -3,7 +3,7 @@ design -save read hierarchy -top latchp proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd latchp # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE @@ -14,7 +14,7 @@ select -assert-none t:LDCE %% t:* %D design -load read hierarchy -top latchn proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd latchn # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE @@ -26,7 +26,7 @@ select -assert-none t:LDCE t:INV %% t:* %D design -load read hierarchy -top latchsr proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd latchsr # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE diff --git a/tests/arch/xilinx/logic.ys b/tests/arch/xilinx/logic.ys index 61a9314cc04..d5b5c1a3797 100644 --- a/tests/arch/xilinx/logic.ys +++ b/tests/arch/xilinx/logic.ys @@ -1,7 +1,7 @@ read_verilog ../common/logic.v hierarchy -top top proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/xilinx/lutram.ys b/tests/arch/xilinx/lutram.ys deleted file mode 100644 index cc73545017f..00000000000 --- a/tests/arch/xilinx/lutram.ys +++ /dev/null @@ -1,157 +0,0 @@ -#read_verilog ../common/lutram.v -#hierarchy -top lutram_1w1r -chparam A_WIDTH 4 -#proc -#memory -nomap -#equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad -#memory -#opt -full -# -#miter -equiv -flatten -make_assert -make_outputs gold gate miter -#sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter -# -#design -load postopt -#cd lutram_1w1r -#select -assert-count 1 t:BUFG -#select -assert-count 8 t:FDRE -#select -assert-count 8 t:RAM16X1D -#select -assert-none t:BUFG t:FDRE t:RAM16X1D %% t:* %D - - -design -reset -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r -chparam A_WIDTH 5 -proc -memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad -memory -opt -full - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter - -design -load postopt -cd lutram_1w1r -select -assert-count 1 t:BUFG -select -assert-count 8 t:FDRE -select -assert-count 8 t:RAM32X1D -select -assert-none t:BUFG t:FDRE t:RAM32X1D %% t:* %D - - -design -reset -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r -proc -memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad -memory -opt -full - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter - -design -load postopt -cd lutram_1w1r -select -assert-count 1 t:BUFG -select -assert-count 8 t:FDRE -select -assert-count 8 t:RAM64X1D -select -assert-none t:BUFG t:FDRE t:RAM64X1D %% t:* %D - - -design -reset -read_verilog ../common/lutram.v -hierarchy -top lutram_1w3r -proc -memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad -memory -opt -full - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter - -design -load postopt -cd lutram_1w3r -select -assert-count 1 t:BUFG -select -assert-count 24 t:FDRE -select -assert-count 4 t:RAM32M -select -assert-none t:BUFG t:FDRE t:RAM32M %% t:* %D - - -design -reset -read_verilog ../common/lutram.v -hierarchy -top lutram_1w3r -chparam A_WIDTH 6 -proc -memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad -memory -opt -full - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter - -design -load postopt -cd lutram_1w3r -select -assert-count 1 t:BUFG -select -assert-count 24 t:FDRE -select -assert-count 8 t:RAM64M -select -assert-none t:BUFG t:FDRE t:RAM64M %% t:* %D - - -design -reset -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r -chparam A_WIDTH 5 -chparam D_WIDTH 6 -proc -memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad -memory -opt -full - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter - -design -load postopt -cd lutram_1w1r -select -assert-count 1 t:BUFG -select -assert-count 6 t:FDRE -select -assert-count 1 t:RAM32M -select -assert-none t:BUFG t:FDRE t:RAM32M %% t:* %D - - -design -reset -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r -chparam A_WIDTH 6 -chparam D_WIDTH 6 -proc -memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad -memory -opt -full - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter - -design -load postopt -cd lutram_1w1r -select -assert-count 1 t:BUFG -select -assert-count 6 t:FDRE -select -assert-count 2 t:RAM64M -select -assert-none t:BUFG t:FDRE t:RAM64M %% t:* %D - - -design -reset -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r -chparam A_WIDTH 4 -proc -memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -family xc3s -noiopad -memory -opt -full - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter - -design -load postopt -cd lutram_1w1r -select -assert-count 1 t:BUFG -select -assert-count 8 t:FDRE -select -assert-count 8 t:RAM16X1D -select -assert-none t:BUFG t:FDRE t:RAM16X1D %% t:* %D diff --git a/tests/arch/xilinx/macc.sh b/tests/arch/xilinx/macc.sh index 58b97b6465d..2272679ee8f 100644 --- a/tests/arch/xilinx/macc.sh +++ b/tests/arch/xilinx/macc.sh @@ -1,6 +1,3 @@ -../../../yosys -qp "synth_xilinx -top macc2; rename -top macc2_uut" -o macc_uut.v macc.v -iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../../techlibs/xilinx/cells_sim.v -vvp -N ./test_macc -../../../yosys -qp "synth_xilinx -family xc6s -top macc2; rename -top macc2_uut" -o macc_uut.v macc.v +../../../yosys -qp "synth_xilinx -top macc2; rename -top macc2_uut" macc.v -o macc_uut.v iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../../techlibs/xilinx/cells_sim.v vvp -N ./test_macc diff --git a/tests/arch/xilinx/macc.v b/tests/arch/xilinx/macc.v index 1645537fd96..e36b2bab1e5 100644 --- a/tests/arch/xilinx/macc.v +++ b/tests/arch/xilinx/macc.v @@ -10,10 +10,10 @@ module macc # (parameter SIZEIN = 16, SIZEOUT = 40) ( output signed [SIZEOUT-1:0] accum_out ); // Declare registers for intermediate values -reg signed [SIZEIN-1:0] a_reg = 0, b_reg = 0; -reg sload_reg = 0; -reg signed [2*SIZEIN-1:0] mult_reg = 0; -reg signed [SIZEOUT-1:0] adder_out = 0, old_result; +reg signed [SIZEIN-1:0] a_reg, b_reg; +reg sload_reg; +reg signed [2*SIZEIN-1:0] mult_reg; +reg signed [SIZEOUT-1:0] adder_out, old_result; always @* /*(adder_out or sload_reg)*/ begin // Modification necessary to fix sim/synth mismatch if (sload_reg) old_result <= 0; @@ -50,10 +50,10 @@ module macc2 # (parameter SIZEIN = 16, SIZEOUT = 40) ( output overflow ); // Declare registers for intermediate values -reg signed [SIZEIN-1:0] a_reg = 0, b_reg = 0, a_reg2 = 0, b_reg2 = 0; +reg signed [SIZEIN-1:0] a_reg, b_reg, a_reg2, b_reg2; reg signed [2*SIZEIN-1:0] mult_reg = 0; reg signed [SIZEOUT:0] adder_out = 0; -reg overflow_reg = 0; +reg overflow_reg; always @(posedge clk) begin //if (ce) begin diff --git a/tests/arch/xilinx/macc.ys b/tests/arch/xilinx/macc.ys index 61a570f4812..6e884b35a1d 100644 --- a/tests/arch/xilinx/macc.ys +++ b/tests/arch/xilinx/macc.ys @@ -3,10 +3,10 @@ design -save read hierarchy -top macc proc -#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad ### TODO -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad +#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx ### TODO +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -show-inputs -show-outputs miter +sat -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd macc # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG @@ -17,16 +17,15 @@ select -assert-none t:BUFG t:FDRE t:DSP48E1 %% t:* %D design -load read hierarchy -top macc2 proc -#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad ### TODO -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad +#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx ### TODO +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 4 -show-inputs -show-outputs miter +sat -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd macc2 # Constrain all select calls below inside the top module - select -assert-count 1 t:BUFG select -assert-count 1 t:DSP48E1 select -assert-count 1 t:FDRE select -assert-count 1 t:LUT2 -select -assert-count 40 t:LUT3 +select -assert-count 41 t:LUT3 select -assert-none t:BUFG t:DSP48E1 t:FDRE t:LUT2 t:LUT3 %% t:* %D diff --git a/tests/arch/xilinx/memory.ys b/tests/arch/xilinx/memory.ys new file mode 100644 index 00000000000..da1ed0e49e4 --- /dev/null +++ b/tests/arch/xilinx/memory.ys @@ -0,0 +1,17 @@ +read_verilog ../common/memory.v +hierarchy -top top +proc +memory -nomap +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +memory +opt -full + +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter + +design -load postopt +cd top +select -assert-count 1 t:BUFG +select -assert-count 8 t:FDRE +select -assert-count 8 t:RAM64X1D +select -assert-none t:BUFG t:FDRE t:RAM64X1D %% t:* %D diff --git a/tests/arch/xilinx/mul.ys b/tests/arch/xilinx/mul.ys index 490846ff1a6..d7681496660 100644 --- a/tests/arch/xilinx/mul.ys +++ b/tests/arch/xilinx/mul.ys @@ -1,21 +1,9 @@ read_verilog ../common/mul.v hierarchy -top top proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:DSP48E1 select -assert-none t:DSP48E1 %% t:* %D - -design -reset - -read_verilog ../common/mul.v -hierarchy -top top -proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s -noiopad # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 1 t:DSP48A1 -select -assert-none t:DSP48A1 %% t:* %D diff --git a/tests/arch/xilinx/mul_unsigned.ys b/tests/arch/xilinx/mul_unsigned.ys index 980263cbd13..62495b90cf4 100644 --- a/tests/arch/xilinx/mul_unsigned.ys +++ b/tests/arch/xilinx/mul_unsigned.ys @@ -2,24 +2,10 @@ read_verilog mul_unsigned.v hierarchy -top mul_unsigned proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mul_unsigned # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:DSP48E1 select -assert-count 30 t:FDRE select -assert-none t:DSP48E1 t:FDRE t:BUFG %% t:* %D - -design -reset - -read_verilog mul_unsigned.v -hierarchy -top mul_unsigned -proc - -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s -noiopad # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd mul_unsigned # Constrain all select calls below inside the top module -select -assert-count 1 t:BUFG -select -assert-count 1 t:DSP48A1 -select -assert-count 30 t:FDRE -select -assert-none t:DSP48A1 t:FDRE t:BUFG %% t:* %D diff --git a/tests/arch/xilinx/mux.ys b/tests/arch/xilinx/mux.ys index 1b27884488b..821d0fab738 100644 --- a/tests/arch/xilinx/mux.ys +++ b/tests/arch/xilinx/mux.ys @@ -3,7 +3,7 @@ design -save read hierarchy -top mux2 proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux2 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT3 @@ -14,7 +14,7 @@ select -assert-none t:LUT3 %% t:* %D design -load read hierarchy -top mux4 proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux4 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT6 @@ -25,7 +25,7 @@ select -assert-none t:LUT6 %% t:* %D design -load read hierarchy -top mux8 proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT3 @@ -37,13 +37,9 @@ select -assert-none t:LUT3 t:LUT6 %% t:* %D design -load read hierarchy -top mux16 proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module -select -assert-max 2 t:LUT4 -select -assert-min 4 t:LUT6 -select -assert-max 7 t:LUT6 -select -assert-max 2 t:MUXF7 -dump +select -assert-count 5 t:LUT6 -select -assert-none t:LUT6 t:LUT4 t:MUXF7 %% t:* %D +select -assert-none t:LUT6 %% t:* %D diff --git a/tests/arch/xilinx/mux_lut4.ys b/tests/arch/xilinx/mux_lut4.ys deleted file mode 100644 index 3e3256993bc..00000000000 --- a/tests/arch/xilinx/mux_lut4.ys +++ /dev/null @@ -1,51 +0,0 @@ -read_verilog ../common/mux.v -design -save read - -hierarchy -top mux2 -proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc3se -noiopad # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd mux2 # Constrain all select calls below inside the top module -select -assert-count 1 t:LUT3 - -select -assert-none t:LUT3 %% t:* %D - - -design -load read -hierarchy -top mux4 -proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc3se -noiopad # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd mux4 # Constrain all select calls below inside the top module -select -assert-count 4 t:LUT1 -select -assert-count 2 t:MUXF5 -select -assert-count 1 t:MUXF6 - -select -assert-none t:LUT1 t:MUXF5 t:MUXF6 %% t:* %D - - -design -load read -hierarchy -top mux8 -proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc3se -noiopad # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd mux8 # Constrain all select calls below inside the top module -select -assert-count 4 t:LUT1 -select -assert-count 3 t:LUT4 -select -assert-count 2 t:MUXF5 -select -assert-count 1 t:MUXF6 - -select -assert-none t:LUT1 t:LUT4 t:MUXF5 t:MUXF6 %% t:* %D - - -design -load read -hierarchy -top mux16 -proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc3se -noiopad # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd mux16 # Constrain all select calls below inside the top module -select -assert-max 32 t:LUT* -select -assert-max 8 t:MUXF6 -select -assert-max 4 t:MUXF7 - -select -assert-none t:LUT* t:MUXF5 t:MUXF6 t:MUXF7 %% t:* %D diff --git a/tests/arch/xilinx/opt_lut_ins.ys b/tests/arch/xilinx/opt_lut_ins.ys deleted file mode 100644 index a01d021793e..00000000000 --- a/tests/arch/xilinx/opt_lut_ins.ys +++ /dev/null @@ -1,25 +0,0 @@ -read_ilang << EOF - -module \top - - wire width 4 input 1 \A - - wire output 2 \O - - cell \LUT4 $0 - parameter \INIT 16'1111110011000000 - connect \I0 \A [0] - connect \I1 \A [1] - connect \I2 \A [2] - connect \I3 \A [3] - connect \O \O - end -end - -EOF - -equiv_opt -assert -map +/xilinx/cells_sim.v opt_lut_ins -tech xilinx - -design -load postopt - -select -assert-count 1 t:LUT3 diff --git a/tests/arch/xilinx/pmgen_xilinx_srl.ys b/tests/arch/xilinx/pmgen_xilinx_srl.ys index e76fb20ab3d..ea2f204876c 100644 --- a/tests/arch/xilinx/pmgen_xilinx_srl.ys +++ b/tests/arch/xilinx/pmgen_xilinx_srl.ys @@ -1,6 +1,6 @@ read_verilog -icells < $_XOR_+$_NOT_ -select -assert-count 3 t:$_NOT_ - - -design -reset -read_verilog -icells < $_XOR_+$_NOT_ -select -assert-count 1 t:$_NOT_ - - -design -reset -read_verilog < o) = 1; -endspecify -endmodule - -(* whitebox *) -module wb(input a, b, output o); -assign o = a ^ b; -endmodule -EOT -clean - -select -assert-count 1 c:* -select -assert-none t:* t:$and %d -select -assert-count 3 w:* -select -assert-count 4 * - -select -assert-count 3 =c:* -select -assert-count 10 =w:* -select -assert-count 13 =* diff --git a/tests/select/no_warn_assert.ys b/tests/select/no_warn_assert.ys deleted file mode 100644 index 8893158269f..00000000000 --- a/tests/select/no_warn_assert.ys +++ /dev/null @@ -1,2 +0,0 @@ -logger -expect-no-warnings -select -assert-count 0 top/t:ff4 top/w:d0 %co:+[d] %i diff --git a/tests/select/no_warn_prefixed_arg_memb.ys b/tests/select/no_warn_prefixed_arg_memb.ys deleted file mode 100644 index 596a6ed70ed..00000000000 --- a/tests/select/no_warn_prefixed_arg_memb.ys +++ /dev/null @@ -1,5 +0,0 @@ -logger -expect-no-warnings -read_verilog ../../examples/igloo2/example.v -hierarchy -proc -select example/t:$add diff --git a/tests/select/no_warn_prefixed_empty_select_arg.ys b/tests/select/no_warn_prefixed_empty_select_arg.ys deleted file mode 100644 index 617e0d63e5c..00000000000 --- a/tests/select/no_warn_prefixed_empty_select_arg.ys +++ /dev/null @@ -1,3 +0,0 @@ -logger -expect-no-warnings -select n:foo/bar* -select t:$assert diff --git a/tests/select/run-test.sh b/tests/select/run-test.sh deleted file mode 100755 index 44ce7e6741f..00000000000 --- a/tests/select/run-test.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done diff --git a/tests/select/unset.ys b/tests/select/unset.ys deleted file mode 100644 index 4f60781c2f9..00000000000 --- a/tests/select/unset.ys +++ /dev/null @@ -1,10 +0,0 @@ -read_verilog < O) = 0; - (I1 => O) = 0; - (S => O) = 0; -endspecify endmodule // Citation: https://github.com/alexforencich/verilog-ethernet @@ -269,46 +264,3 @@ always @* if (en) q <= d; endmodule - -module abc9_test031(input clk1, clk2, d, output reg q1, q2); -always @(posedge clk1) q1 <= d; -always @(negedge clk2) q2 <= q1; -endmodule - -module abc9_test032(input clk, d, r, output reg q); -always @(posedge clk or posedge r) - if (r) q <= 1'b0; - else q <= d; -endmodule - -module abc9_test033(input clk, d, r, output reg q); -always @(negedge clk or posedge r) - if (r) q <= 1'b1; - else q <= d; -endmodule - -module abc9_test034(input clk, d, output reg q1, q2); -always @(posedge clk) q1 <= d; -always @(posedge clk) q2 <= q1; -endmodule - -module abc9_test035(input clk, d, output reg [1:0] q); -always @(posedge clk) q[0] <= d; -always @(negedge clk) q[1] <= q[0]; -endmodule - -module abc9_test036(input A, B, S, output [1:0] O); - (* keep *) - MUXF8 m ( - .I0(I0), - .I1(I1), - .O(O[0]), - .S(S) - ); - MUXF8 m2 ( - .I0(I0), - .I1(I1), - .O(O[1]), - .S(S) - ); -endmodule diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index 650e42fcab8..0d4262005fd 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -20,13 +20,10 @@ fi cp ../simple/*.v . cp ../simple/*.sv . DOLLAR='?' -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-n 300 -p '\ +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-n 300 -p '\ hierarchy; \ synth -run coarse; \ opt -full; \ - techmap; \ - abc9 -lut 4 -box ../abc9.box; \ - clean; \ + techmap; abc9 -lut 4 -box ../abc.box; \ check -assert; \ - select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \ - setattr -mod -unset blackbox'" + select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'" diff --git a/tests/svtypes/enum_simple.sv b/tests/svtypes/enum_simple.sv deleted file mode 100644 index 4e4d5871c5c..00000000000 --- a/tests/svtypes/enum_simple.sv +++ /dev/null @@ -1,48 +0,0 @@ - -module enum_simple(input clk, input rst); - - enum {s0, s1, s2, s3} test_enum; - typedef enum logic [1:0] { - ts0, ts1, ts2, ts3 - } states_t; - states_t state; - (states_t) state1; - states_t enum_const = ts1; - - always @(posedge clk) begin - if (rst) begin - test_enum <= s3; - state <= ts0; - end else begin - //test_enum - if (test_enum == s0) - test_enum <= s1; - else if (test_enum == s1) - test_enum <= s2; - else if (test_enum == s2) - test_enum <= s3; - else if (test_enum == s3) - test_enum <= s0; - else - assert(1'b0); //should be unreachable - - //state - if (state == ts0) - state <= ts1; - else if (state == ts1) - state <= ts2; - else if (state == ts2) - state <= ts0; - else - assert(1'b0); //should be unreachable - end - end - - always @(*) begin - assert(state != 2'h3); - assert(s0 == '0); - assert(ts0 == '0); - assert(enum_const == ts1); - end - -endmodule diff --git a/tests/svtypes/enum_simple.ys b/tests/svtypes/enum_simple.ys deleted file mode 100644 index 79981657b6f..00000000000 --- a/tests/svtypes/enum_simple.ys +++ /dev/null @@ -1,5 +0,0 @@ - -read_verilog -sv enum_simple.sv -hierarchy; proc; opt -sat -verify -seq 1 -set-at 1 rst 1 -tempinduct -prove-asserts -show-all - diff --git a/tests/svtypes/logic_rom.sv b/tests/svtypes/logic_rom.sv deleted file mode 100644 index 45fe0a4cae1..00000000000 --- a/tests/svtypes/logic_rom.sv +++ /dev/null @@ -1,6 +0,0 @@ -module top(input [3:0] addr, output [7:0] data); - logic [7:0] mem[0:15]; - assign data = mem[addr]; - integer i; - initial for(i = 0; i < 16; i = i + 1) mem[i] = i; -endmodule diff --git a/tests/svtypes/logic_rom.ys b/tests/svtypes/logic_rom.ys deleted file mode 100644 index 7b079c13627..00000000000 --- a/tests/svtypes/logic_rom.ys +++ /dev/null @@ -1,3 +0,0 @@ -read_verilog -sv logic_rom.sv -prep -top top -select -assert-count 1 t:$mem r:SIZE=16 %i r:WIDTH=8 %i diff --git a/tests/svtypes/struct_array.sv b/tests/svtypes/struct_array.sv deleted file mode 100644 index 022ad56c67e..00000000000 --- a/tests/svtypes/struct_array.sv +++ /dev/null @@ -1,22 +0,0 @@ -// test for array indexing in structures - -module top; - - struct packed { - bit [5:0] [7:0] a; // 6 element packed array of bytes - bit [15:0] b; // filler for non-zero offset - } s; - - initial begin - s = '0; - - s.a[2:1] = 16'h1234; - s.a[5] = 8'h42; - - s.b = '1; - s.b[1:0] = '0; - end - - always_comb assert(s==64'h4200_0012_3400_FFFC); - -endmodule diff --git a/tests/svtypes/struct_simple.sv b/tests/svtypes/struct_simple.sv deleted file mode 100644 index c74289cc3eb..00000000000 --- a/tests/svtypes/struct_simple.sv +++ /dev/null @@ -1,48 +0,0 @@ -module top; - localparam BITS=8; - - struct packed { - logic a; - logic[BITS-1:0] b; - byte c; - logic x, y; - } s; - - struct packed signed { - integer a; - logic[15:0] b; - logic[7:0] c; - bit [7:0] d; - } pack1; - - struct packed { - byte a; - struct packed { - byte x, y; - } b; - } s2; - - assign s.a = '1; - assign s.b = '1; - assign s.c = 8'hAA; - assign s.x = '1; - logic[7:0] t; - assign t = s.b; - assign pack1.a = 42; - assign pack1.b = 16'hAAAA; - assign pack1.c = '1; - assign pack1.d = 8'h55; - assign s2.b.x = 'h42; - - always_comb assert(s.a == 1'b1); - always_comb assert(s.c == 8'hAA); - always_comb assert(s.x == 1'b1); - always_comb assert(t == 8'hFF); - always_comb assert(pack1.a == 42); - always_comb assert(pack1.b == 16'hAAAA); - always_comb assert(pack1.c == 8'hFF); - always_comb assert(pack1[15:8] == 8'hFF); - always_comb assert(pack1.d == 8'h55); - always_comb assert(s2.b.x == 'h42); - -endmodule diff --git a/tests/svtypes/typedef_memory.sv b/tests/svtypes/typedef_memory.sv index 37e63c1d001..577e484adaf 100644 --- a/tests/svtypes/typedef_memory.sv +++ b/tests/svtypes/typedef_memory.sv @@ -1,7 +1,7 @@ module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata); typedef logic [3:0] ram16x4_t[0:15]; - ram16x4_t mem; + (ram16x4_t) mem; always @(posedge clk) begin if (wen) mem[addr] <= wdata; diff --git a/tests/svtypes/typedef_memory_2.sv b/tests/svtypes/typedef_memory_2.sv index 6d65131db21..f3089bf55ba 100644 --- a/tests/svtypes/typedef_memory_2.sv +++ b/tests/svtypes/typedef_memory_2.sv @@ -1,7 +1,7 @@ module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata); typedef logic [3:0] nibble; - nibble mem[0:15]; + (nibble) mem[0:15]; always @(posedge clk) begin if (wen) mem[addr] <= wdata; diff --git a/tests/svtypes/typedef_package.sv b/tests/svtypes/typedef_package.sv index 2d83742c58e..a1e16d4b1b6 100644 --- a/tests/svtypes/typedef_package.sv +++ b/tests/svtypes/typedef_package.sv @@ -1,19 +1,11 @@ package pkg; typedef logic [7:0] uint8_t; - typedef enum logic [7:0] {bb=8'hBB, cc=8'hCC} enum8_t; - - localparam uint8_t PCONST = cc; - parameter uint8_t PCONST_COPY = PCONST; endpackage module top; - (* keep *) pkg::uint8_t a = 8'hAA; - (* keep *) pkg::enum8_t b_enum = pkg::bb; + (* keep *) (pkg::uint8_t) a = 8'hAA; - always_comb assert(a == 8'hAA); - always_comb assert(b_enum == 8'hBB); - always_comb assert(pkg::PCONST == pkg::cc); - always_comb assert(pkg::PCONST_COPY == pkg::cc); + always @* assert(a == 8'hAA); endmodule diff --git a/tests/svtypes/typedef_param.sv b/tests/svtypes/typedef_param.sv index d838dd828e3..ddbd471e0c9 100644 --- a/tests/svtypes/typedef_param.sv +++ b/tests/svtypes/typedef_param.sv @@ -6,12 +6,12 @@ module top; typedef logic [1:0] uint2_t; typedef logic signed [3:0] int4_t; typedef logic signed [7:0] int8_t; - typedef int8_t char_t; + typedef (int8_t) char_t; - parameter uint2_t int2 = 2'b10; - localparam int4_t int4 = -1; - localparam int8_t int8 = int4; - localparam char_t ch = int8; + parameter (uint2_t) int2 = 2'b10; + localparam (int4_t) int4 = -1; + localparam (int8_t) int8 = int4; + localparam (char_t) ch = int8; `STATIC_ASSERT(int2 == 2'b10); diff --git a/tests/svtypes/typedef_scopes.sv b/tests/svtypes/typedef_scopes.sv index 5507d84f28e..faa385bd65e 100644 --- a/tests/svtypes/typedef_scopes.sv +++ b/tests/svtypes/typedef_scopes.sv @@ -1,42 +1,23 @@ typedef logic [3:0] outer_uint4_t; -typedef enum logic {s0, s1} outer_enum_t; module top; - outer_uint4_t u4_i = 8'hA5; - outer_enum_t enum4_i = s0; + (outer_uint4_t) u4_i = 8'hA5; always @(*) assert(u4_i == 4'h5); - always @(*) assert(enum4_i == 1'b0); typedef logic [3:0] inner_type; - typedef enum logic [2:0] {s2=2, s3, s4} inner_enum_t; - inner_type inner_i1 = 8'h5A; - inner_enum_t inner_enum1 = s3; + (inner_type) inner_i1 = 8'h5A; always @(*) assert(inner_i1 == 4'hA); - always @(*) assert(inner_enum1 == 3'h3); if (1) begin: genblock typedef logic [7:0] inner_type; - parameter inner_type inner_const = 8'hA5; - typedef enum logic [2:0] {s5=5, s6, s7} inner_enum_t; - inner_type inner_gb_i = inner_const; //8'hA5; - inner_enum_t inner_gb_enum1 = s7; + (inner_type) inner_gb_i = 8'hA5; always @(*) assert(inner_gb_i == 8'hA5); - always @(*) assert(inner_gb_enum1 == 3'h7); end - inner_type inner_i2 = 8'h42; - inner_enum_t inner_enum2 = s4; + (inner_type) inner_i2 = 8'h42; always @(*) assert(inner_i2 == 4'h2); - always @(*) assert(inner_enum2 == 3'h4); -endmodule - -typedef logic[7:0] between_t; -module other; - between_t a = 8'h42; - always @(*) assert(a == 8'h42); endmodule - diff --git a/tests/svtypes/typedef_simple.sv b/tests/svtypes/typedef_simple.sv index 8f89910e5c9..7e760dee479 100644 --- a/tests/svtypes/typedef_simple.sv +++ b/tests/svtypes/typedef_simple.sv @@ -3,12 +3,12 @@ module top; typedef logic [1:0] uint2_t; typedef logic signed [3:0] int4_t; typedef logic signed [7:0] int8_t; - typedef int8_t char_t; + typedef (int8_t) char_t; - (* keep *) uint2_t int2 = 2'b10; - (* keep *) int4_t int4 = -1; - (* keep *) int8_t int8 = int4; - (* keep *) char_t ch = int8; + (* keep *) (uint2_t) int2 = 2'b10; + (* keep *) (int4_t) int4 = -1; + (* keep *) (int8_t) int8 = int4; + (* keep *) (char_t) ch = int8; always @* assert(int2 == 2'b10); diff --git a/tests/svtypes/typedef_struct.sv b/tests/svtypes/typedef_struct.sv deleted file mode 100644 index 7ae00795263..00000000000 --- a/tests/svtypes/typedef_struct.sv +++ /dev/null @@ -1,42 +0,0 @@ -package p; - -typedef struct packed { - byte a; - byte b; -} p_t; - -endpackage - - -module top; - - typedef logic[7:0] t_t; - - typedef struct packed { - bit a; - logic[7:0] b; - t_t t; - } s_t; - - s_t s; - s_t s1; - - p::p_t ps; - - assign s.a = '1; - assign s.b = '1; - assign s.t = 8'h55; - assign s1 = s; - assign ps.a = 8'hAA; - assign ps.b = 8'h55; - - always_comb begin - assert(s.a == 1'b1); - assert(s.b == 8'hFF); - assert(s.t == 8'h55); - assert(s1.t == 8'h55); - assert(ps.a == 8'hAA); - assert(ps.b == 8'h55); - end - -endmodule diff --git a/tests/svtypes/union_simple.sv b/tests/svtypes/union_simple.sv deleted file mode 100644 index 12e4b376f97..00000000000 --- a/tests/svtypes/union_simple.sv +++ /dev/null @@ -1,72 +0,0 @@ -module top; - - typedef struct packed { - byte a,b,c,d; - } byte4_t; - - typedef union packed { - int x; - byte4_t y; - } w_t; - - w_t w; - - assign w.x = 'h42; - always_comb begin - assert(w.y.d == 8'h42); - end - - typedef logic[4:0] reg_addr_t; - typedef logic[6:0] opcode_t; - - typedef struct packed { - bit [6:0] func7; - reg_addr_t rs2; - reg_addr_t rs1; - bit [2:0] func3; - reg_addr_t rd; - opcode_t opcode; - } R_t; - - typedef struct packed { - bit[11:0] imm; - reg_addr_t rs1; - bit[2:0] func3; - reg_addr_t rd; - opcode_t opcode; - } I_t; - - typedef struct packed { - bit[19:0] imm; - reg_addr_t rd; - opcode_t opcode; - } U_t; - - typedef union packed { - R_t r; - I_t i; - U_t u; - } instruction_t; - - instruction_t ir1; - assign ir1 = 32'h0AA01EB7; // lui t4,0xAA01 - always_comb begin - assert(ir1.u.opcode == 'h37); - assert(ir1.r.opcode == 'h37); - assert(ir1.u.rd == 'd29); - assert(ir1.r.rd == 'd29); - assert(ir1.u.imm == 'hAA01); - end - - union packed { - int word; - struct packed { - byte a, b, c, d; - } byte4; - } u; - assign u.word = 'h42; - always_comb begin - assert(u.byte4.d == 'h42); - end - -endmodule diff --git a/tests/techmap/abc9.ys b/tests/techmap/abc9.ys deleted file mode 100644 index 2140dde2672..00000000000 --- a/tests/techmap/abc9.ys +++ /dev/null @@ -1,81 +0,0 @@ -read_verilog < b; -assign gts = $signed(a) > $signed(b); -assign ltu = a < b; -assign lts = $signed(a) < $signed(b); -assign geu = a >= b; -assign ges = $signed(a) >= $signed(b); -assign leu = a <= b; -assign les = $signed(a) <= $signed(b); -endmodule -EOT - -equiv_opt -assert techmap -map +/cmp2lcu.v -D LUT_WIDTH=6 -design -load postopt -select -assert-count 8 t:$lcu r:WIDTH=5 %i -select -assert-none t:$gt t:$ge t:$lt t:$le - -design -load preopt -equiv_opt -assert techmap -map +/cmp2lcu.v -D LUT_WIDTH=4 -design -load postopt -select -assert-count 8 t:$lcu r:WIDTH=7 %i -select -assert-none t:$gt t:$ge t:$lt t:$le - - -design -reset -read_verilog < d; -assign gts = $signed(c) > $signed(d); -assign ltu = c < d; -assign lts = $signed(c) < $signed(d); -assign geu = c >= d; -assign ges = $signed(c) >= $signed(d); -assign leu = c <= d; -assign les = $signed(c) <= $signed(d); -endmodule -EOT -design -save gold - -equiv_opt -assert techmap -map +/cmp2lcu.v -D LUT_WIDTH=5 -design -load postopt -select -assert-count 8 t:$lcu r:WIDTH=2 %i -select -assert-none t:$gt t:$ge t:$lt t:$le - -design -load preopt -equiv_opt -assert techmap -map +/cmp2lcu.v -D LUT_WIDTH=3 -design -load postopt -select -assert-count 8 t:$lcu r:WIDTH=4 %i -select -assert-none t:$gt t:$ge t:$lt t:$le diff --git a/tests/techmap/dff2dffs.ys b/tests/techmap/dff2dffs.ys index 105a89400f0..13f1a3cf3da 100644 --- a/tests/techmap/dff2dffs.ys +++ b/tests/techmap/dff2dffs.ys @@ -31,20 +31,20 @@ design -save ref dff2dffs clean -select -assert-count 1 w:q0 %x t:$_SDFF_PP0_ %i -select -assert-count 1 w:q1 %x t:$_SDFF_PP1_ %i -select -assert-count 1 w:q2 %x t:$_SDFF_PP0_ %i -select -assert-count 1 w:q3 %x t:$_SDFF_PP1_ %i -select -assert-count 1 w:q4 %x t:$_SDFF_PP0_ %i -select -assert-count 1 w:q5 %x t:$_SDFF_PP1_ %i +select -assert-count 1 w:q0 %x t:$__DFFS_PP0_ %i +select -assert-count 1 w:q1 %x t:$__DFFS_PP1_ %i +select -assert-count 1 w:q2 %x t:$__DFFS_PP0_ %i +select -assert-count 1 w:q3 %x t:$__DFFS_PP1_ %i +select -assert-count 1 w:q4 %x t:$__DFFS_PP0_ %i +select -assert-count 1 w:q5 %x t:$__DFFS_PP1_ %i design -load ref dff2dffs -match-init clean -select -assert-count 1 w:q0 %x t:$_SDFF_PP0_ %i -select -assert-count 0 w:q1 %x t:$_SDFF_PP1_ %i -select -assert-count 0 w:q2 %x t:$_SDFF_PP0_ %i -select -assert-count 1 w:q3 %x t:$_SDFF_PP1_ %i -select -assert-count 1 w:q4 %x t:$_SDFF_PP0_ %i -select -assert-count 1 w:q5 %x t:$_SDFF_PP1_ %i +select -assert-count 1 w:q0 %x t:$__DFFS_PP0_ %i +select -assert-count 0 w:q1 %x t:$__DFFS_PP1_ %i +select -assert-count 0 w:q2 %x t:$__DFFS_PP0_ %i +select -assert-count 1 w:q3 %x t:$__DFFS_PP1_ %i +select -assert-count 1 w:q4 %x t:$__DFFS_PP0_ %i +select -assert-count 1 w:q5 %x t:$__DFFS_PP1_ %i diff --git a/tests/techmap/dffinit.ys b/tests/techmap/dffinit.ys deleted file mode 100644 index 218d411f8b9..00000000000 --- a/tests/techmap/dffinit.ys +++ /dev/null @@ -1,25 +0,0 @@ -read_verilog < o) = 1; -endspecify -endmodule - -module abc9_test037(input [1:0] i, output o); -LUT2 #(.mask(4'b0)) lut (.i(i), .o(o)); -endmodule -EOT -abc9 - - -design -reset -read_verilog -icells < 0; -endmodule -EOT - - -design -reset -read_verilog <((-3'sd0)>>(4'sd2)))}}; - - assign y8 = (-(!($signed({3{p9}})<(p4?b4:b5)))); -endmodule -EOT - - -design -reset -read_verilog < args, RTLIL::Design *design) override - { - size_t argidx = 1; - extra_args(args, argidx, design); - log("Plugin test passed!\n"); - } -} TestPass; - -YOSYS_NAMESPACE_END diff --git a/tests/various/plugin.sh b/tests/various/plugin.sh deleted file mode 100644 index 2880c8c06f2..00000000000 --- a/tests/various/plugin.sh +++ /dev/null @@ -1,8 +0,0 @@ -set -e -rm -f plugin.so -CXXFLAGS=$(../../yosys-config --cxxflags) -DATDIR=$(../../yosys-config --datdir) -DATDIR=${DATDIR//\//\\\/} -CXXFLAGS=${CXXFLAGS//$DATDIR/..\/..\/share} -../../yosys-config --exec --cxx ${CXXFLAGS} --ldflags -shared -o plugin.so plugin.cc -../../yosys -m ./plugin.so -p "test" | grep -q "Plugin test passed!" diff --git a/tests/various/pmux2shiftx.v b/tests/various/pmux2shiftx.v index c1994e92ca6..56339408058 100644 --- a/tests/various/pmux2shiftx.v +++ b/tests/various/pmux2shiftx.v @@ -33,7 +33,7 @@ module pmux2shiftx_test ( end endmodule -module issue01135(input [7:0] i, output reg o); +module issue01135(input [7:0] i, output o); always @* case (i[6:3]) 4: o <= i[0]; diff --git a/tests/various/primitives.ys b/tests/various/primitives.ys deleted file mode 100644 index 9307ca50f4c..00000000000 --- a/tests/various/primitives.ys +++ /dev/null @@ -1,16 +0,0 @@ -read_verilog < (Q : D)) = (1, 2:3:4); $setup(D, posedge CLK &&& EN, 5); $hold(posedge CLK, D &&& EN, 6); +`endif endspecify endmodule @@ -35,30 +37,3 @@ specify (posedge clk *> (q +: d)) = (3,1); endspecify endmodule - -module test3(input clk, input [1:0] d, output [1:0] q); -specify - (posedge clk => (q +: d)) = (3,1); - (posedge clk *> (q +: d)) = (3,1); -endspecify -endmodule - -module test4(input clk, d, output q); -specify - $setup(d, posedge clk, 1:2:3); - $setuphold(d, posedge clk, 1:2:3, 4:5:6); -endspecify -endmodule - -module test5(input clk, d, e, output q); -specify - $setup(d, posedge clk &&& e, 1:2:3); -endspecify -endmodule - -module test6(input clk, d, e, output q); -specify - (d[0] *> q[0]) = (3,1); - (posedge clk[0] => (q[0] +: d[0])) = (3,1); -endspecify -endmodule diff --git a/tests/various/specify.ys b/tests/various/specify.ys index d7260d5242e..00597e1e282 100644 --- a/tests/various/specify.ys +++ b/tests/various/specify.ys @@ -4,16 +4,10 @@ cd test select t:$specify2 -assert-count 0 select t:$specify3 -assert-count 1 select t:$specrule -assert-count 2 -select t:$specify3 a:src=specify.v:10.3-10.49 %i -assert-count 1 -select t:$specrule a:src=specify.v:11.3-11.36 %i -assert-count 1 -select t:$specrule a:src=specify.v:12.3-12.35 %i -assert-count 1 cd test2 select t:$specify2 -assert-count 2 select t:$specify3 -assert-count 0 select t:$specrule -assert-count 0 -select t:$specify2 a:src=specify.v:26.3-26.20 %i -assert-count 1 - # ^^ Note use of macro -select t:$specify2 a:src=specify.v:28.3-28.18 %i -assert-count 1 cd write_verilog specify.out design -stash gold @@ -61,23 +55,4 @@ equiv_induct -seq 5 equiv_status -assert design -reset -read_verilog -specify < o) = 1; -endspecify -assign o = ~i; -endmodule - -module test7(input i, output o); - wire w; - test7_sub unused(i, w); - test7_sub used(i, o); -endmodule -EOT -hierarchy -cd test7 -clean -select -assert-count 1 c:used -select -assert-none c:* c:used %d +read_verilog -DSKIP_UNSUPPORTED_IGN_PARSER_CONSTRUCTS specify.v diff --git a/tests/various/src.ys b/tests/various/src.ys deleted file mode 100644 index 89d6700ca24..00000000000 --- a/tests/various/src.ys +++ /dev/null @@ -1,8 +0,0 @@ -logger -expect warning "wire '\\o' is assigned in a block at <&2; exit 1' ERR - -# Simple case -../../yosys -f "verilog -sv" -qp "prep -flatten -top top; select -assert-count 1 t:\$add" - <&1 | grep -F "ERROR: No matching wire for implicit port connection \`b' of cell top.add_i (add)." > /dev/null - -# Incorrectly sized wire -((../../yosys -f "verilog -sv" -qp "hierarchy -top top" - || true) <&1 | grep -F "ERROR: Width mismatch between wire (7 bits) and port (8 bits) for implicit port connection \`b' of cell top.add_i (add)." > /dev/null - -# Defaults -../../yosys -f "verilog -sv" -qp "prep -flatten -top top; select -assert-count 1 t:\$add" - <&1 | grep -F "ERROR: Width mismatch between wire (8 bits) and port (6 bits) for implicit port connection \`q' of cell top.add_i (add)." > /dev/null - -# Mixed implicit and explicit 1 -../../yosys -f "verilog -sv" -qp "prep -flatten -top top; select -assert-count 1 t:\$add" - <&1 | grep -F "Warning: Resizing cell port top.add_i.b from 10 bits to 8 bits." > /dev/null diff --git a/tests/various/xaiger.ys b/tests/various/xaiger.ys deleted file mode 100644 index f612d2e1826..00000000000 --- a/tests/various/xaiger.ys +++ /dev/null @@ -1,13 +0,0 @@ -read_verilog < run-test.mk -exec ${MAKE:-make} -f run-test.mk diff --git a/tests/verilog/task_attr.ys b/tests/verilog/task_attr.ys deleted file mode 100644 index d6e75f85fea..00000000000 --- a/tests/verilog/task_attr.ys +++ /dev/null @@ -1,28 +0,0 @@ -read_verilog <