aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/issue_template.md16
-rw-r--r--.gitignore5
-rw-r--r--.travis.yml5
-rwxr-xr-x.travis/setup.sh2
-rw-r--r--Brewfile1
-rw-r--r--CodingReadme3
-rw-r--r--Makefile159
-rw-r--r--README.md22
-rw-r--r--backends/aiger/aiger.cc4
-rw-r--r--backends/blif/blif.cc72
-rw-r--r--backends/btor/btor.cc4
-rw-r--r--backends/edif/edif.cc4
-rw-r--r--backends/firrtl/firrtl.cc133
-rw-r--r--backends/ilang/ilang_backend.cc8
-rw-r--r--backends/intersynth/intersynth.cc4
-rw-r--r--backends/json/json.cc12
-rw-r--r--backends/protobuf/.gitignore2
-rw-r--r--backends/protobuf/Makefile.inc8
-rw-r--r--backends/protobuf/protobuf.cc370
-rw-r--r--backends/simplec/simplec.cc4
-rw-r--r--backends/smt2/Makefile.inc2
-rw-r--r--backends/smt2/smt2.cc24
-rw-r--r--backends/smt2/smtio.py71
-rw-r--r--backends/smv/smv.cc4
-rw-r--r--backends/spice/spice.cc4
-rw-r--r--backends/table/table.cc4
-rw-r--r--backends/verilog/verilog_backend.cc55
-rw-r--r--examples/basys3/example.xdc3
-rw-r--r--examples/basys3/run_prog.tcl1
-rw-r--r--examples/cmos/counter.ys10
-rw-r--r--examples/cxx-api/evaldemo.cc2
-rw-r--r--frontends/ast/ast.cc44
-rw-r--r--frontends/ast/ast.h14
-rw-r--r--frontends/ast/genrtlil.cc189
-rw-r--r--frontends/ast/simplify.cc244
-rw-r--r--frontends/blif/blifparse.cc44
-rw-r--r--frontends/ilang/.gitignore2
-rw-r--r--frontends/ilang/Makefile.inc7
-rw-r--r--frontends/ilang/ilang_frontend.cc4
-rw-r--r--frontends/ilang/ilang_lexer.l2
-rw-r--r--frontends/json/jsonparse.cc4
-rw-r--r--frontends/liberty/liberty.cc40
-rw-r--r--frontends/verific/verific.cc587
-rw-r--r--frontends/verific/verific.h14
-rw-r--r--frontends/verific/verificsva.cc365
-rw-r--r--frontends/verilog/.gitignore2
-rw-r--r--frontends/verilog/Makefile.inc7
-rw-r--r--frontends/verilog/const2ast.cc8
-rw-r--r--frontends/verilog/preproc.cc7
-rw-r--r--frontends/verilog/verilog_frontend.cc51
-rw-r--r--frontends/verilog/verilog_lexer.l15
-rw-r--r--frontends/verilog/verilog_parser.y277
-rw-r--r--kernel/celledges.h6
-rw-r--r--kernel/driver.cc70
-rw-r--r--kernel/log.cc92
-rw-r--r--kernel/log.h9
-rw-r--r--kernel/modtools.h10
-rw-r--r--kernel/register.cc11
-rw-r--r--kernel/register.h14
-rw-r--r--kernel/rtlil.h2
-rw-r--r--kernel/satgen.h2
-rw-r--r--kernel/yosys.cc55
-rw-r--r--kernel/yosys.h2
-rw-r--r--manual/CHAPTER_Prog/stubnets.cc2
-rw-r--r--manual/PRESENTATION_Prog/my_cmd.cc6
-rw-r--r--misc/yosys.proto175
-rw-r--r--passes/cmds/add.cc4
-rw-r--r--passes/cmds/blackbox.cc4
-rw-r--r--passes/cmds/check.cc4
-rw-r--r--passes/cmds/chformal.cc4
-rw-r--r--passes/cmds/chtype.cc4
-rw-r--r--passes/cmds/connect.cc4
-rw-r--r--passes/cmds/connwrappers.cc4
-rw-r--r--passes/cmds/copy.cc4
-rw-r--r--passes/cmds/cover.cc6
-rw-r--r--passes/cmds/delete.cc4
-rw-r--r--passes/cmds/design.cc6
-rw-r--r--passes/cmds/edgetypes.cc4
-rw-r--r--passes/cmds/logcmd.cc4
-rw-r--r--passes/cmds/ltp.cc4
-rw-r--r--passes/cmds/plugin.cc4
-rw-r--r--passes/cmds/qwp.cc4
-rw-r--r--passes/cmds/rename.cc4
-rw-r--r--passes/cmds/scatter.cc4
-rw-r--r--passes/cmds/scc.cc4
-rw-r--r--passes/cmds/select.cc14
-rw-r--r--passes/cmds/setattr.cc12
-rw-r--r--passes/cmds/setundef.cc242
-rw-r--r--passes/cmds/show.cc27
-rw-r--r--passes/cmds/splice.cc4
-rw-r--r--passes/cmds/splitnets.cc4
-rw-r--r--passes/cmds/stat.cc12
-rw-r--r--passes/cmds/tee.cc4
-rw-r--r--passes/cmds/torder.cc4
-rw-r--r--passes/cmds/trace.cc17
-rw-r--r--passes/cmds/write_file.cc4
-rw-r--r--passes/equiv/equiv_add.cc4
-rw-r--r--passes/equiv/equiv_induct.cc4
-rw-r--r--passes/equiv/equiv_make.cc4
-rw-r--r--passes/equiv/equiv_mark.cc4
-rw-r--r--passes/equiv/equiv_miter.cc4
-rw-r--r--passes/equiv/equiv_purge.cc4
-rw-r--r--passes/equiv/equiv_remove.cc4
-rw-r--r--passes/equiv/equiv_simple.cc4
-rw-r--r--passes/equiv/equiv_status.cc4
-rw-r--r--passes/equiv/equiv_struct.cc4
-rw-r--r--passes/fsm/fsm.cc4
-rw-r--r--passes/fsm/fsm_detect.cc4
-rw-r--r--passes/fsm/fsm_expand.cc4
-rw-r--r--passes/fsm/fsm_export.cc4
-rw-r--r--passes/fsm/fsm_extract.cc4
-rw-r--r--passes/fsm/fsm_info.cc4
-rw-r--r--passes/fsm/fsm_map.cc4
-rw-r--r--passes/fsm/fsm_opt.cc4
-rw-r--r--passes/fsm/fsm_recode.cc4
-rw-r--r--passes/hierarchy/hierarchy.cc78
-rw-r--r--passes/hierarchy/submod.cc4
-rw-r--r--passes/hierarchy/uniquify.cc4
-rw-r--r--passes/memory/memory.cc4
-rw-r--r--passes/memory/memory_bram.cc4
-rw-r--r--passes/memory/memory_collect.cc4
-rw-r--r--passes/memory/memory_dff.cc24
-rw-r--r--passes/memory/memory_map.cc4
-rw-r--r--passes/memory/memory_memx.cc4
-rw-r--r--passes/memory/memory_nordff.cc66
-rw-r--r--passes/memory/memory_share.cc4
-rw-r--r--passes/memory/memory_unpack.cc4
-rw-r--r--passes/opt/opt.cc4
-rw-r--r--passes/opt/opt_clean.cc8
-rw-r--r--passes/opt/opt_demorgan.cc4
-rw-r--r--passes/opt/opt_expr.cc21
-rw-r--r--passes/opt/opt_merge.cc4
-rw-r--r--passes/opt/opt_muxtree.cc4
-rw-r--r--passes/opt/opt_reduce.cc4
-rw-r--r--passes/opt/opt_rmdff.cc4
-rw-r--r--passes/opt/rmports.cc4
-rw-r--r--passes/opt/share.cc4
-rw-r--r--passes/opt/wreduce.cc4
-rw-r--r--passes/proc/proc.cc4
-rw-r--r--passes/proc/proc_arst.cc4
-rw-r--r--passes/proc/proc_clean.cc4
-rw-r--r--passes/proc/proc_dff.cc4
-rw-r--r--passes/proc/proc_dlatch.cc4
-rw-r--r--passes/proc/proc_init.cc4
-rw-r--r--passes/proc/proc_mux.cc4
-rw-r--r--passes/proc/proc_rmdead.cc4
-rw-r--r--passes/sat/Makefile.inc1
-rw-r--r--passes/sat/assertpmux.cc4
-rw-r--r--passes/sat/async2sync.cc147
-rw-r--r--passes/sat/clk2fflogic.cc4
-rw-r--r--passes/sat/eval.cc4
-rw-r--r--passes/sat/expose.cc55
-rw-r--r--passes/sat/freduce.cc4
-rw-r--r--passes/sat/miter.cc4
-rw-r--r--passes/sat/sat.cc5
-rw-r--r--passes/sat/sim.cc6
-rw-r--r--passes/techmap/Makefile.inc2
-rw-r--r--passes/techmap/abc.cc44
-rw-r--r--passes/techmap/aigmap.cc4
-rw-r--r--passes/techmap/alumacc.cc4
-rw-r--r--passes/techmap/attrmap.cc12
-rw-r--r--passes/techmap/attrmvcp.cc4
-rw-r--r--passes/techmap/deminout.cc36
-rw-r--r--passes/techmap/dff2dffe.cc18
-rw-r--r--passes/techmap/dff2dffs.cc142
-rw-r--r--passes/techmap/dffinit.cc4
-rw-r--r--passes/techmap/dfflibmap.cc8
-rw-r--r--passes/techmap/dffsr2dff.cc4
-rw-r--r--passes/techmap/extract.cc4
-rw-r--r--passes/techmap/extract_counter.cc4
-rw-r--r--passes/techmap/extract_fa.cc4
-rw-r--r--passes/techmap/extract_reduce.cc5
-rw-r--r--passes/techmap/hilomap.cc4
-rw-r--r--passes/techmap/insbuf.cc4
-rw-r--r--passes/techmap/iopadmap.cc61
-rw-r--r--passes/techmap/lut2mux.cc4
-rw-r--r--passes/techmap/maccmap.cc4
-rw-r--r--passes/techmap/muxcover.cc4
-rw-r--r--passes/techmap/nlutmap.cc4
-rw-r--r--passes/techmap/pmuxtree.cc4
-rw-r--r--passes/techmap/shregmap.cc4
-rw-r--r--passes/techmap/simplemap.cc4
-rw-r--r--passes/techmap/techmap.cc12
-rw-r--r--passes/techmap/tribuf.cc4
-rw-r--r--passes/techmap/zinit.cc4
-rw-r--r--passes/tests/test_abcloop.cc4
-rw-r--r--passes/tests/test_autotb.cc4
-rw-r--r--passes/tests/test_cell.cc4
-rwxr-xr-xtechlibs/achronix/Makefile.inc2
-rwxr-xr-xtechlibs/achronix/speedster22i/cells_map.v66
-rwxr-xr-xtechlibs/achronix/speedster22i/cells_sim.v85
-rwxr-xr-xtechlibs/achronix/synth_achronix.cc (renamed from techlibs/achronix/synth_speedster.cc)28
-rw-r--r--techlibs/common/prep.cc30
-rw-r--r--techlibs/common/synth.cc8
-rw-r--r--techlibs/coolrunner2/Makefile.inc1
-rw-r--r--techlibs/coolrunner2/coolrunner2_sop.cc62
-rw-r--r--techlibs/coolrunner2/synth_coolrunner2.cc21
-rw-r--r--techlibs/coolrunner2/tff_extract.v41
-rw-r--r--techlibs/easic/synth_easic.cc8
-rw-r--r--techlibs/ecp5/Makefile.inc8
-rw-r--r--techlibs/ecp5/arith_map.v79
-rw-r--r--techlibs/ecp5/cells_map.v135
-rw-r--r--techlibs/ecp5/cells_sim.v448
-rw-r--r--techlibs/ecp5/dram.txt16
-rw-r--r--techlibs/ecp5/drams_map.v28
-rw-r--r--techlibs/ecp5/synth_ecp5.cc331
-rw-r--r--techlibs/gowin/synth_gowin.cc8
-rw-r--r--techlibs/greenpak4/greenpak4_dffinv.cc4
-rw-r--r--techlibs/greenpak4/synth_greenpak4.cc8
-rw-r--r--techlibs/ice40/cells_map.v2
-rw-r--r--techlibs/ice40/cells_sim.v111
-rw-r--r--techlibs/ice40/ice40_ffinit.cc4
-rw-r--r--techlibs/ice40/ice40_ffssr.cc4
-rw-r--r--techlibs/ice40/ice40_opt.cc38
-rw-r--r--techlibs/ice40/synth_ice40.cc56
-rw-r--r--techlibs/intel/cyclone10/cells_map.v20
-rw-r--r--techlibs/intel/cycloneiv/cells_map.v20
-rw-r--r--techlibs/intel/cycloneive/arith_map.v51
-rw-r--r--techlibs/intel/cycloneive/cells_map.v21
-rw-r--r--techlibs/intel/cyclonev/cells_map.v75
-rw-r--r--techlibs/intel/max10/cells_map.v24
-rw-r--r--techlibs/intel/synth_intel.cc46
-rw-r--r--techlibs/xilinx/cells_map.v2
-rw-r--r--techlibs/xilinx/synth_xilinx.cc41
-rw-r--r--tests/simple/specify.v31
-rwxr-xr-xtests/tools/autotest.sh4
226 files changed, 5434 insertions, 1397 deletions
diff --git a/.github/issue_template.md b/.github/issue_template.md
new file mode 100644
index 000000000..24e91a4e7
--- /dev/null
+++ b/.github/issue_template.md
@@ -0,0 +1,16 @@
+## Steps to reproduce the issue
+
+*Provide instructions for reproducing the issue. Make sure to include
+all neccessary source files. (You can simply drag&drop a .zip file into
+the issue editor.)*
+
+## Expected behavior
+
+*Please describe the behavior you would have expected from the tool.*
+
+## Actual behavior
+
+*Please describe how the behavior you see differs from the expected behavior.*
+
+**Important Note:** Nobody will be able to help you and/or fix the issue if you
+do not provide sufficient information for reproducing the problem.
diff --git a/.gitignore b/.gitignore
index cd624f233..48ce458c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,8 @@
*.d
.*.swp
*.gch
+*.gcda
+*.gcno
/.cproject
/.project
/.settings
@@ -10,6 +12,8 @@
/qtcreator.config
/qtcreator.creator
/qtcreator.creator.user
+/coverage.info
+/coverage_html
/Makefile.conf
/abc
/viz.js
@@ -30,3 +34,4 @@
/libyosys.so
/tests/unit/bintest/
/tests/unit/objtest/
+/tests/ystests
diff --git a/.travis.yml b/.travis.yml
index fbb4018af..321c3325f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,7 +28,6 @@ matrix:
- tcl-dev
- libffi-dev
- git
- - mercurial
- graphviz
- xdot
- pkg-config
@@ -53,7 +52,6 @@ matrix:
- tcl-dev
- libffi-dev
- git
- - mercurial
- graphviz
- xdot
- pkg-config
@@ -78,7 +76,6 @@ matrix:
- tcl-dev
- libffi-dev
- git
- - mercurial
- graphviz
- xdot
- pkg-config
@@ -104,7 +101,6 @@ matrix:
- tcl-dev
- libffi-dev
- git
- - mercurial
- graphviz
- xdot
- pkg-config
@@ -129,7 +125,6 @@ matrix:
- tcl-dev
- libffi-dev
- git
- - mercurial
- graphviz
- xdot
- pkg-config
diff --git a/.travis/setup.sh b/.travis/setup.sh
index 81ff37742..068515786 100755
--- a/.travis/setup.sh
+++ b/.travis/setup.sh
@@ -64,7 +64,7 @@ if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
brew tap Homebrew/bundle
brew bundle
brew install ccache
- brew install gcc
+ brew install gcc@7
echo
echo -en 'travis_fold:end:before_install.brew\\r'
echo
diff --git a/Brewfile b/Brewfile
index d7cd05bf1..0c58ce161 100644
--- a/Brewfile
+++ b/Brewfile
@@ -3,7 +3,6 @@ brew "flex"
brew "gawk"
brew "libffi"
brew "git"
-brew "mercurial"
brew "graphviz"
brew "pkg-config"
brew "python3"
diff --git a/CodingReadme b/CodingReadme
index 5800e30c3..b64e79178 100644
--- a/CodingReadme
+++ b/CodingReadme
@@ -21,7 +21,7 @@ Here is a the C++ code for a "hello_world" Yosys command (hello.cc):
struct HelloWorldPass : public Pass {
HelloWorldPass() : Pass("hello_world") { }
- virtual void execute(vector<string>, Design*) {
+ void execute(vector<string>, Design*) override {
log("Hello World!\n");
}
} HelloWorldPass;
@@ -373,6 +373,7 @@ Finally run all tests with "make config-{clang,gcc,gcc-4.8}":
cd ~yosys
make clean
make test
+ make ystests
make vloghtb
make install
diff --git a/Makefile b/Makefile
index af29ff414..7698047ec 100644
--- a/Makefile
+++ b/Makefile
@@ -5,6 +5,7 @@ CONFIG := clang
# CONFIG := emcc
# CONFIG := mxe
# CONFIG := msys2
+# CONFIG := msys2-64
# features (the more the better)
ENABLE_TCL := 1
@@ -15,13 +16,18 @@ ENABLE_EDITLINE := 0
ENABLE_VERIFIC := 0
ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0
+ENABLE_PROTOBUF := 0
# other configuration flags
+ENABLE_GCOV := 0
ENABLE_GPROF := 0
ENABLE_DEBUG := 0
ENABLE_NDEBUG := 0
LINK_CURSES := 0
LINK_TERMCAP := 0
+LINK_ABC := 0
+# Needed for environments that don't have proper thread support (i.e. emscripten)
+DISABLE_ABC_THREADS := 0
# clang sanitizers
SANITIZER =
@@ -31,6 +37,7 @@ SANITIZER =
# SANITIZER = cfi
+OS := $(shell uname -s)
PREFIX ?= /usr/local
INSTALL_SUDO :=
@@ -66,7 +73,7 @@ SED ?= sed
BISON ?= bison
STRIP ?= strip
-ifeq (Darwin,$(findstring Darwin,$(shell uname)))
+ifeq ($(OS), Darwin)
PLUGIN_LDFLAGS += -undefined dynamic_lookup
# homebrew search paths
@@ -102,9 +109,9 @@ OBJS = kernel/version_$(GIT_REV).o
# 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 = 6e3c24b3308a
+ABCREV = ae6716b
ABCPULL = 1
-ABCURL ?= https://bitbucket.org/alanmi/abc
+ABCURL ?= https://github.com/berkeley-abc/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
# set ABCEXTERNAL = <abc-command> to use an external ABC instance
@@ -125,6 +132,7 @@ ifeq ($(CONFIG),clang)
CXX = clang
LD = clang++
CXXFLAGS += -std=c++11 -Os
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
ifneq ($(SANITIZER),)
$(info [Clang Sanitizer] $(SANITIZER))
@@ -147,16 +155,31 @@ else ifeq ($(CONFIG),gcc)
CXX = gcc
LD = gcc
CXXFLAGS += -std=c++11 -Os
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
+
+else ifeq ($(CONFIG),gcc-static)
+LD = $(CXX)
+LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -static
+LDLIBS := $(filter-out -lrt,$(LDLIBS))
+CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
+CXXFLAGS += -std=c++11 -Os
+ABCMKARGS = CC="$(CC)" CXX="$(CXX)" LD="$(LD)" ABC_USE_LIBSTDCXX=1 LIBS="-lm -lpthread -static" OPTFLAGS="-O" \
+ ARCHFLAGS="-DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING=1 -Wno-unused-but-set-variable $(ARCHFLAGS)" ABC_USE_NO_READLINE=1
+ifeq ($(DISABLE_ABC_THREADS),1)
+ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
+endif
else ifeq ($(CONFIG),gcc-4.8)
CXX = gcc-4.8
LD = gcc-4.8
CXXFLAGS += -std=c++11 -Os
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),emcc)
CXX = emcc
LD = emcc
CXXFLAGS := -std=c++11 $(filter-out -fPIC -ggdb,$(CXXFLAGS))
+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']"
@@ -170,6 +193,11 @@ EXE = .js
TARGETS := $(filter-out yosys-config,$(TARGETS))
EXTRA_TARGETS += yosysjs-$(YOSYS_VER).zip
+ifeq ($(ENABLE_ABC),1)
+LINK_ABC := 1
+DISABLE_ABC_THREADS := 1
+endif
+
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
@@ -185,14 +213,14 @@ yosys.html: misc/yosys.html
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-gcc
-LD = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc
+CXX = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++
+LD = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++
CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_MXE_HACKS -Wno-attributes
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
-ABCMKARGS += ARCHFLAGS="-DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
-ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="$(CXX)" CXX="$(CXX)"
+ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
+ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
EXE = .exe
else ifeq ($(CONFIG),msys2)
@@ -202,12 +230,23 @@ CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
-ABCMKARGS += ARCHFLAGS="-DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
-ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=0 CC="i686-w64-mingw32-gcc" CXX="$(CXX)"
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
+ABCMKARGS += LIBS="-lpthread -s" ABC_USE_NO_READLINE=0 CC="i686-w64-mingw32-gcc" CXX="$(CXX)"
+EXE = .exe
+
+else ifeq ($(CONFIG),msys2-64)
+CXX = x86_64-w64-mingw32-g++
+LD = x86_64-w64-mingw32-g++
+CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
+CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
+LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
+LDLIBS := $(filter-out -lrt,$(LDLIBS))
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
+ABCMKARGS += LIBS="-lpthread -s" ABC_USE_NO_READLINE=0 CC="x86_64-w64-mingw32-gcc" CXX="$(CXX)"
EXE = .exe
else ifneq ($(CONFIG),none)
-$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, gcc-4.8, emcc, mxe, msys2)
+$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, gcc-4.8, emcc, mxe, msys2, msys2-64)
endif
ifeq ($(ENABLE_LIBYOSYS),1)
@@ -216,6 +255,9 @@ endif
ifeq ($(ENABLE_READLINE),1)
CXXFLAGS += -DYOSYS_ENABLE_READLINE
+ifeq ($(OS), FreeBSD)
+CXXFLAGS += -I/usr/local/include
+endif
LDLIBS += -lreadline
ifeq ($(LINK_CURSES),1)
LDLIBS += -lcurses
@@ -232,26 +274,49 @@ else
ifeq ($(ENABLE_EDITLINE),1)
CXXFLAGS += -DYOSYS_ENABLE_EDITLINE
LDLIBS += -ledit -ltinfo -lbsd
+else
+ABCMKARGS += "ABC_USE_NO_READLINE=1"
+endif
endif
+
+ifeq ($(DISABLE_ABC_THREADS),1)
+ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
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) -ldl
+LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi)
+ifneq ($(OS), FreeBSD)
+LDLIBS += -ldl
+endif
endif
ifeq ($(ENABLE_TCL),1)
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
+ifeq ($(OS), FreeBSD)
+TCL_INCLUDE ?= /usr/local/include/$(TCL_VERSION)
+else
TCL_INCLUDE ?= /usr/include/$(TCL_VERSION)
+endif
ifeq ($(CONFIG),mxe)
CXXFLAGS += -DYOSYS_ENABLE_TCL
-LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32
+LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz
else
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
+ifeq ($(OS), FreeBSD)
+# FreeBSD uses tcl8.6, but lib is named "libtcl86"
+LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo -l$(TCL_VERSION) | tr -d '.')
+else
LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo -l$(TCL_VERSION))
endif
endif
+endif
+
+ifeq ($(ENABLE_GCOV),1)
+CXXFLAGS += --coverage
+LDFLAGS += --coverage
+endif
ifeq ($(ENABLE_GPROF),1)
CXXFLAGS += -pg
@@ -272,10 +337,17 @@ endif
ifeq ($(ENABLE_ABC),1)
CXXFLAGS += -DYOSYS_ENABLE_ABC
+ifeq ($(LINK_ABC),1)
+CXXFLAGS += -DYOSYS_LINK_ABC
+ifeq ($(DISABLE_ABC_THREADS),0)
+LDLIBS += -lpthread
+endif
+else
ifeq ($(ABCEXTERNAL),)
TARGETS += yosys-abc$(EXE)
endif
endif
+endif
ifeq ($(ENABLE_VERIFIC),1)
VERIFIC_DIR ?= /usr/local/src/verific_lib_eval
@@ -284,6 +356,10 @@ CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABL
LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VERIFIC_COMPONENTS)) -lz
endif
+ifeq ($(ENABLE_PROTOBUF),1)
+LDLIBS += $(shell pkg-config --cflags --libs protobuf)
+endif
+
ifeq ($(ENABLE_COVER),1)
CXXFLAGS += -DYOSYS_ENABLE_COVER
endif
@@ -395,6 +471,10 @@ include techlibs/common/Makefile.inc
endif
+ifeq ($(LINK_ABC),1)
+OBJS += yosys-libabc.a
+endif
+
top-all: $(TARGETS) $(EXTRA_TARGETS)
@echo ""
@echo " Build successful."
@@ -439,29 +519,36 @@ yosys-config: misc/yosys-config.in
-e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > yosys-config
$(Q) chmod +x yosys-config
-abc/abc-$(ABCREV)$(EXE):
+abc/abc-$(ABCREV)$(EXE) abc/libabc-$(ABCREV).a:
$(P)
ifneq ($(ABCREV),default)
- $(Q) if ( cd abc 2> /dev/null && hg identify; ) | grep -q +; then \
+ $(Q) if test -d abc/.hg; then \
+ echo 'REEBE: NOP qverpgbel vf n ut jbexvat pbcl! Erzbir nop/ naq er-eha "znxr".' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; false; \
+ fi
+ $(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
- $(Q) if test "`cd abc 2> /dev/null && hg identify | cut -f1 -d' '`" != "$(ABCREV)"; 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 || hg clone --insecure $(ABCURL) abc; \
- cd abc && $(MAKE) DEP= clean && hg pull --insecure && hg update -r $(ABCREV); \
+ test -d abc || git clone $(ABCURL) abc; \
+ cd abc && $(MAKE) DEP= clean && git fetch origin master && git checkout $(ABCREV); \
fi
endif
$(Q) rm -f abc/abc-[0-9a-f]*
- $(Q) cd abc && $(MAKE) $(S) $(ABCMKARGS) PROG="abc-$(ABCREV)$(EXE)" MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: "
+ $(Q) cd abc && $(MAKE) $(S) $(ABCMKARGS) $(if $(filter %.a,$@),PROG="abc-$(ABCREV)",PROG="abc-$(ABCREV)$(EXE)") MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: " $(if $(filter %.a,$@),libabc-$(ABCREV).a)
ifeq ($(ABCREV),default)
.PHONY: abc/abc-$(ABCREV)$(EXE)
+.PHONY: abc/libabc-$(ABCREV).a
endif
yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE)
$(P) cp abc/abc-$(ABCREV)$(EXE) yosys-abc$(EXE)
+yosys-libabc.a: abc/libabc-$(ABCREV).a
+ $(P) cp abc/libabc-$(ABCREV).a yosys-libabc.a
+
ifneq ($(SEED),)
SEEDOPT="-S $(SEED)"
else
@@ -498,6 +585,14 @@ vloghtb: $(TARGETS) $(EXTRA_TARGETS)
@echo " Passed \"make vloghtb\"."
@echo ""
+ystests: $(TARGETS) $(EXTRA_TARGETS)
+ rm -rf tests/ystests
+ git clone https://github.com/YosysHQ/yosys-tests.git tests/ystests
+ +PATH="$$PWD:$$PATH" cd tests/ystests && $(MAKE)
+ @echo ""
+ @echo " Finished \"make ystests\"."
+ @echo ""
+
# Unit test
unit-test: libyosys.so
@$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CPPFLAGS="$(CPPFLAGS)" \
@@ -545,7 +640,7 @@ clean:
rm -rf share
if test -d manual; then cd manual && sh clean.sh; fi
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS)
- rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]*
+ rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d
rm -rf tests/asicworld/*.out tests/asicworld/*.log
rm -rf tests/hana/*.out tests/hana/*.log
@@ -558,11 +653,17 @@ clean:
clean-abc:
$(MAKE) -C abc DEP= clean
- rm -f yosys-abc$(EXE) abc/abc-[0-9a-f]*
+ 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:
+ ./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
+
qtcreator:
{ for file in $(basename $(OBJS)); do \
for prefix in cc y l; do if [ -f $${file}.$${prefix} ]; then echo $$file.$${prefix}; fi; done \
@@ -602,6 +703,12 @@ config-clang: clean
config-gcc: clean
echo 'CONFIG := gcc' > Makefile.conf
+config-gcc-static: clean
+ echo 'CONFIG := gcc-static' > Makefile.conf
+ echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
+ echo 'ENABLE_READLINE := 0' >> Makefile.conf
+ echo 'ENABLE_TCL := 0' >> Makefile.conf
+
config-gcc-4.8: clean
echo 'CONFIG := gcc-4.8' > Makefile.conf
@@ -619,6 +726,14 @@ config-mxe: clean
config-msys2: clean
echo 'CONFIG := msys2' > Makefile.conf
+config-msys2-64: clean
+ echo 'CONFIG := msys2-64' > Makefile.conf
+
+config-gcov: clean
+ echo 'CONFIG := gcc' > Makefile.conf
+ echo 'ENABLE_GCOV := 1' >> Makefile.conf
+ echo 'ENABLE_DEBUG := 1' >> Makefile.conf
+
config-gprof: clean
echo 'CONFIG := gcc' > Makefile.conf
echo 'ENABLE_GPROF := 1' >> Makefile.conf
@@ -639,6 +754,6 @@ echo-git-rev:
-include kernel/*.d
-include techlibs/*/*.d
-.PHONY: all top-all abc test install install-abc manual clean mrproper qtcreator
-.PHONY: config-clean config-clang config-gcc config-gcc-4.8 config-gprof config-sudo
+.PHONY: all top-all abc test install install-abc manual clean mrproper qtcreator coverage vcxsrc mxebin
+.PHONY: config-clean config-clang config-gcc config-gcc-static config-gcc-4.8 config-gprof config-sudo
diff --git a/README.md b/README.md
index 514d8e2f7..424d9bbf2 100644
--- a/README.md
+++ b/README.md
@@ -52,14 +52,22 @@ For example on Ubuntu Linux 16.04 LTS the following commands will install all
prerequisites for building yosys:
$ sudo apt-get install build-essential clang bison flex \
- libreadline-dev gawk tcl-dev libffi-dev git mercurial \
+ libreadline-dev gawk tcl-dev libffi-dev git \
graphviz xdot pkg-config python3
Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies:
$ brew tap Homebrew/bundle && brew bundle
$ sudo port install bison flex readline gawk libffi \
- git mercurial graphviz pkgconfig python36
+ git graphviz pkgconfig python36
+
+On FreeBSD use the following command to install all prerequisites:
+
+ # pkg install bison flex readline gawk libffi\
+ git graphviz pkgconfig python3 python36 tcl-wrapper
+
+On FreeBSD system use gmake instead of make. To run tests use:
+ % MAKE=gmake CC=cc gmake test
There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well
as a source distribution for Visual Studio. Visit the Yosys download page for
@@ -381,7 +389,7 @@ Verilog Attributes and non-standard features
Non-standard or SystemVerilog features for formal verification
==============================================================
-- Support for ``assert``, ``assume``, ``restrict``, and ``cover'' is enabled
+- Support for ``assert``, ``assume``, ``restrict``, and ``cover`` is enabled
when ``read_verilog`` is called with ``-formal``.
- The system task ``$initstate`` evaluates to 1 in the initial state and
@@ -402,11 +410,17 @@ Non-standard or SystemVerilog features for formal verification
statements it is sufficient if just one ``$allconst/$allseq`` value triggers
the property (similar to ``$anyconst/$anyseq``).
+- Wires/registers decalred using the ``anyconst/anyseq/allconst/allseq`` attribute
+ (for example ``(* anyconst *) reg [7:0] foobar;``) will behave as if driven
+ by a ``$anyconst/$anyseq/$allconst/$allseq`` function.
+
- The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are
supported in any clocked block.
- The syntax ``@($global_clock)`` can be used to create FFs that have no
- explicit clock input ($ff cells).
+ explicit clock input ($ff cells). The same can be achieved by using
+ ``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>``
+ is marked with the ``(* gclk *)`` Verilog attribute.
Supported features from SystemVerilog
diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc
index 526e50a49..c323691a3 100644
--- a/backends/aiger/aiger.cc
+++ b/backends/aiger/aiger.cc
@@ -657,7 +657,7 @@ struct AigerWriter
struct AigerBackend : public Backend {
AigerBackend() : Backend("aiger", "write design to AIGER file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -690,7 +690,7 @@ struct AigerBackend : public Backend {
log(" like -map, but more verbose\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool ascii_mode = false;
bool zinit_mode = false;
diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc
index f9230a1e6..0db5ff27c 100644
--- a/backends/blif/blif.cc
+++ b/backends/blif/blif.cc
@@ -38,8 +38,10 @@ struct BlifDumperConfig
bool impltf_mode;
bool gates_mode;
bool cname_mode;
+ bool iname_mode;
bool param_mode;
bool attr_mode;
+ bool iattr_mode;
bool blackbox_mode;
bool noalias_mode;
@@ -48,7 +50,8 @@ struct BlifDumperConfig
std::string true_type, true_out, false_type, false_out, undef_type, undef_out;
BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false),
- cname_mode(false), param_mode(false), attr_mode(false), blackbox_mode(false), noalias_mode(false) { }
+ cname_mode(false), iname_mode(false), param_mode(false), attr_mode(false), iattr_mode(false),
+ blackbox_mode(false), noalias_mode(false) { }
};
struct BlifDumper
@@ -240,118 +243,118 @@ struct BlifDumper
if (!config->icells_mode && cell->type == "$_NOT_") {
f << stringf(".names %s %s\n0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_AND_") {
f << stringf(".names %s %s %s\n11 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_OR_") {
f << stringf(".names %s %s %s\n1- 1\n-1 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_XOR_") {
f << stringf(".names %s %s %s\n10 1\n01 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_NAND_") {
f << stringf(".names %s %s %s\n0- 1\n-0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_NOR_") {
f << stringf(".names %s %s %s\n00 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_XNOR_") {
f << stringf(".names %s %s %s\n11 1\n00 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_ANDNOT_") {
f << stringf(".names %s %s %s\n10 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_ORNOT_") {
f << stringf(".names %s %s %s\n1- 1\n-0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_AOI3_") {
f << stringf(".names %s %s %s %s\n-00 1\n0-0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\C")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_OAI3_") {
f << stringf(".names %s %s %s %s\n00- 1\n--0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\C")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
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("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\C")), cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_OAI4_") {
f << stringf(".names %s %s %s %s %s\n00-- 1\n--00 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\C")), cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_MUX_") {
f << stringf(".names %s %s %s %s\n1-0 1\n-11 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_FF_") {
f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr_init(cell->getPort("\\Q")));
- continue;
+ goto internal_cell;
}
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")));
- continue;
+ goto internal_cell;
}
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")));
- continue;
+ goto internal_cell;
}
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")));
- continue;
+ goto internal_cell;
}
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")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$lut") {
@@ -373,7 +376,7 @@ struct BlifDumper
}
f << " 1\n";
}
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$sop") {
@@ -401,7 +404,7 @@ struct BlifDumper
}
f << " 1\n";
}
- continue;
+ goto internal_cell;
}
f << stringf(".%s %s", subckt_or_gate(cell->type.str()), cstr(cell->type));
@@ -421,6 +424,14 @@ struct BlifDumper
dump_params(".attr", cell->attributes);
if (config->param_mode)
dump_params(".param", cell->parameters);
+
+ if (0) {
+ internal_cell:
+ if (config->iname_mode)
+ f << stringf(".cname %s\n", cstr(cell->name));
+ if (config->iattr_mode)
+ dump_params(".attr", cell->attributes);
+ }
}
for (auto &conn : module->connections())
@@ -453,7 +464,7 @@ struct BlifDumper
struct BlifBackend : public Backend {
BlifBackend() : Backend("blif", "write design to BLIF file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -511,6 +522,11 @@ struct BlifBackend : public Backend {
log(" -cname\n");
log(" use the non-standard .cname statement to write cell names\n");
log("\n");
+ log(" -iname, -iattr\n");
+ log(" enable -cname and -attr functionality for .names statements\n");
+ log(" (the .cname and .attr statements will be included in the BLIF\n");
+ log(" output after the truth table for the .names statement)\n");
+ log("\n");
log(" -blackbox\n");
log(" write blackbox cells with .blackbox statement.\n");
log("\n");
@@ -518,7 +534,7 @@ struct BlifBackend : public Backend {
log(" do not write definitions for the $true, $false and $undef wires.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string top_module_name;
std::string buf_type, buf_in, buf_out;
@@ -587,6 +603,14 @@ struct BlifBackend : public Backend {
config.attr_mode = true;
continue;
}
+ if (args[argidx] == "-iname") {
+ config.iname_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-iattr") {
+ config.iattr_mode = true;
+ continue;
+ }
if (args[argidx] == "-blackbox") {
config.blackbox_mode = true;
continue;
diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc
index 61a2f8ba3..58d2a8625 100644
--- a/backends/btor/btor.cc
+++ b/backends/btor/btor.cc
@@ -1076,7 +1076,7 @@ struct BtorWorker
struct BtorBackend : public Backend {
BtorBackend() : Backend("btor", "write design to BTOR file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1091,7 +1091,7 @@ struct BtorBackend : public Backend {
log(" Output only a single bad property for all asserts\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool verbose = false, single_bad = false;
diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc
index a6534b911..5f9ec54fd 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -116,7 +116,7 @@ struct EdifBackend : public Backend {
log("is targeted.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing EDIF backend.\n");
std::string top_module_name;
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc
index 06cbc9b2b..94236d0b1 100644
--- a/backends/firrtl/firrtl.cc
+++ b/backends/firrtl/firrtl.cc
@@ -32,6 +32,27 @@ pool<string> used_names;
dict<IdString, string> namecache;
int autoid_counter;
+typedef unsigned FDirection;
+static const FDirection NODIRECTION = 0x0;
+static const FDirection IN = 0x1;
+static const FDirection OUT = 0x2;
+static const FDirection INOUT = 0x3;
+
+// Get a port direction with respect to a specific module.
+FDirection getPortFDirection(IdString id, Module *module)
+{
+ Wire *wire = module->wires_.at(id);
+ FDirection direction = NODIRECTION;
+ if (wire && wire->port_id)
+ {
+ if (wire->port_input)
+ direction |= IN;
+ if (wire->port_output)
+ direction |= OUT;
+ }
+ return direction;
+}
+
string next_id()
{
string new_id;
@@ -77,6 +98,8 @@ struct FirrtlWorker
dict<SigBit, pair<string, int>> reverse_wire_map;
string unconn_id;
+ RTLIL::Design *design;
+ std::string indent;
void register_reverse_wire_map(string id, SigSpec sig)
{
@@ -84,11 +107,11 @@ struct FirrtlWorker
reverse_wire_map[sig[i]] = make_pair(id, i);
}
- FirrtlWorker(Module *module, std::ostream &f) : module(module), f(f)
+ FirrtlWorker(Module *module, std::ostream &f, RTLIL::Design *theDesign) : module(module), f(f), design(theDesign), indent(" ")
{
}
- string make_expr(SigSpec sig)
+ string make_expr(const SigSpec &sig)
{
string expr;
@@ -135,6 +158,65 @@ struct FirrtlWorker
return expr;
}
+ std::string fid(RTLIL::IdString internal_id)
+ {
+ const char *str = internal_id.c_str();
+ return *str == '\\' ? str + 1 : str;
+ }
+
+
+ std::string cellname(RTLIL::Cell *cell)
+ {
+ return fid(cell->name).c_str();
+ }
+
+ void process_instance(RTLIL::Cell *cell, vector<string> &wire_exprs)
+ {
+ std::string cell_type = fid(cell->type);
+
+ std::string cell_name = cellname(cell);
+ std::string cell_name_comment;
+ if (cell_name != fid(cell->name))
+ cell_name_comment = " /* " + fid(cell->name) + " */ ";
+ else
+ cell_name_comment = "";
+ // Find the module corresponding to this instance.
+ auto instModule = design->module(cell->type);
+ wire_exprs.push_back(stringf("%s" "inst %s%s of %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), cell_type.c_str()));
+
+ for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) {
+ if (it->second.size() > 0) {
+ const SigSpec &secondSig = it->second;
+ const std::string firstName = cell_name + "." + make_id(it->first);
+ const std::string secondName = make_expr(secondSig);
+ // Find the direction for this port.
+ FDirection dir = getPortFDirection(it->first, instModule);
+ std::string source, sink;
+ switch (dir) {
+ case INOUT:
+ log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", log_id(cell_type), log_signal(it->second));
+ case OUT:
+ source = firstName;
+ sink = secondName;
+ break;
+ case NODIRECTION:
+ log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", log_id(cell_type), log_signal(it->second));
+ /* FALL_THROUGH */
+ case IN:
+ source = secondName;
+ sink = firstName;
+ break;
+ default:
+ log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", log_id(cell_type), log_signal(it->second), dir);
+ break;
+ }
+ wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str()));
+ }
+ }
+ wire_exprs.push_back(stringf("\n"));
+
+ }
+
void run()
{
f << stringf(" module %s:\n", make_id(module->name));
@@ -142,21 +224,28 @@ struct FirrtlWorker
for (auto wire : module->wires())
{
+ const auto wireName = make_id(wire->name);
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>\n", wire->port_input ? "input" : "output",
- make_id(wire->name), wire->width));
+ wireName, wire->width));
}
else
{
- wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", make_id(wire->name), wire->width));
+ wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", wireName, wire->width));
}
}
for (auto cell : module->cells())
{
+ // Is this cell is a module instance?
+ if (cell->type[0] != '$')
+ {
+ process_instance(cell, wire_exprs);
+ continue;
+ }
if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor"))
{
string y_id = make_id(cell->name);
@@ -169,7 +258,10 @@ struct FirrtlWorker
a_expr = "asSInt(" + a_expr + ")";
}
- a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
+ // Don't use the results of logical operations (a single bit) to control padding
+ 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);
+ }
string primop;
bool always_uint = false;
@@ -187,9 +279,12 @@ struct FirrtlWorker
a_expr = stringf("xorr(%s)", a_expr.c_str());
}
if (cell->type == "$reduce_bool") {
- primop = "neq";
- a_expr = stringf("%s, UInt(0)", a_expr.c_str());
- }
+ primop = "neq";
+ // Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand.
+ bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool();
+ int a_width = cell->parameters.at("\\A_WIDTH").as_int();
+ a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width);
+ }
string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str());
@@ -215,16 +310,16 @@ struct FirrtlWorker
if (cell->parameters.at("\\A_SIGNED").as_bool()) {
a_expr = "asSInt(" + a_expr + ")";
}
- if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type != "$shr")) {
- b_expr = "asSInt(" + b_expr + ")";
+ // Shift amount is always unsigned, and needn't be padded to result width.
+ if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) {
+ if (cell->parameters.at("\\B_SIGNED").as_bool()) {
+ b_expr = "asSInt(" + b_expr + ")";
+ }
+ b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
}
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
- if ((cell->type != "$shl") && (cell->type != "$sshl")) {
- b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
- }
-
if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) {
a_expr = "asUInt(" + a_expr + ")";
}
@@ -494,14 +589,14 @@ struct FirrtlWorker
if (is_valid) {
if (make_unconn_id) {
wire_decls.push_back(stringf(" wire %s: UInt<1>\n", unconn_id.c_str()));
- cell_exprs.push_back(stringf(" %s is invalid\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\n", make_id(wire->name), expr.c_str()));
} else {
if (make_unconn_id) {
unconn_id.clear();
}
- wire_exprs.push_back(stringf(" %s is invalid\n", make_id(wire->name)));
+ wire_decls.push_back(stringf(" %s is invalid\n", make_id(wire->name)));
}
}
@@ -527,7 +622,7 @@ struct FirrtlWorker
struct FirrtlBackend : public Backend {
FirrtlBackend() : Backend("firrtl", "write design to a FIRRTL file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -536,7 +631,7 @@ struct FirrtlBackend : public Backend {
log("Write a FIRRTL netlist of the current design.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -570,7 +665,7 @@ struct FirrtlBackend : public Backend {
for (auto module : design->modules())
{
- FirrtlWorker worker(module, *f);
+ FirrtlWorker worker(module, *f, design);
worker.run();
}
diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc
index 1f7f12361..4c58ea087 100644
--- a/backends/ilang/ilang_backend.cc
+++ b/backends/ilang/ilang_backend.cc
@@ -382,7 +382,7 @@ PRIVATE_NAMESPACE_BEGIN
struct IlangBackend : public Backend {
IlangBackend() : Backend("ilang", "write design to ilang file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -395,7 +395,7 @@ struct IlangBackend : public Backend {
log(" only write selected parts of the design.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool selected = false;
@@ -422,7 +422,7 @@ struct IlangBackend : public Backend {
struct DumpPass : public Pass {
DumpPass() : Pass("dump", "print parts of the design in ilang format") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -445,7 +445,7 @@ struct DumpPass : public Pass {
log(" like -outfile but append instead of overwrite\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 34cb52fb4..2eb08dbe9 100644
--- a/backends/intersynth/intersynth.cc
+++ b/backends/intersynth/intersynth.cc
@@ -46,7 +46,7 @@ static std::string netname(std::set<std::string> &conntypes_code, std::set<std::
struct IntersynthBackend : public Backend {
IntersynthBackend() : Backend("intersynth", "write design to InterSynth netlist file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -71,7 +71,7 @@ struct IntersynthBackend : public Backend {
log("http://www.clifford.at/intersynth/\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing INTERSYNTH backend.\n");
log_push();
diff --git a/backends/json/json.cc b/backends/json/json.cc
index d3b7077a2..f5c687981 100644
--- a/backends/json/json.cc
+++ b/backends/json/json.cc
@@ -93,8 +93,10 @@ struct JsonWriter
f << get_string(param.second.decode_string());
else if (GetSize(param.second.bits) > 32)
f << get_string(param.second.as_string());
- else
+ else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", param.second.as_int());
+ else
+ f << stringf("%u", param.second.as_int());
first = false;
}
}
@@ -250,7 +252,7 @@ struct JsonWriter
struct JsonBackend : public Backend {
JsonBackend() : Backend("json", "write design to a JSON file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -458,7 +460,7 @@ struct JsonBackend : public Backend {
log("format. A program processing this format must ignore all unknown fields.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool aig_mode = false;
@@ -482,7 +484,7 @@ struct JsonBackend : public Backend {
struct JsonPass : public Pass {
JsonPass() : Pass("json", "write design in JSON format") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -499,7 +501,7 @@ struct JsonPass : public Pass {
log("See 'help write_json' for a description of the JSON format used.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string filename;
bool aig_mode = false;
diff --git a/backends/protobuf/.gitignore b/backends/protobuf/.gitignore
new file mode 100644
index 000000000..849b38d45
--- /dev/null
+++ b/backends/protobuf/.gitignore
@@ -0,0 +1,2 @@
+yosys.pb.cc
+yosys.pb.h
diff --git a/backends/protobuf/Makefile.inc b/backends/protobuf/Makefile.inc
new file mode 100644
index 000000000..834cad42c
--- /dev/null
+++ b/backends/protobuf/Makefile.inc
@@ -0,0 +1,8 @@
+ifeq ($(ENABLE_PROTOBUF),1)
+
+backends/protobuf/yosys.pb.cc backends/protobuf/yosys.pb.h: misc/yosys.proto
+ $(Q) cd misc && protoc --cpp_out "../backends/protobuf" yosys.proto
+
+OBJS += backends/protobuf/protobuf.o backends/protobuf/yosys.pb.o
+
+endif
diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc
new file mode 100644
index 000000000..f56147cef
--- /dev/null
+++ b/backends/protobuf/protobuf.cc
@@ -0,0 +1,370 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <google/protobuf/text_format.h>
+
+#include "kernel/rtlil.h"
+#include "kernel/register.h"
+#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
+#include "kernel/cellaigs.h"
+#include "kernel/log.h"
+#include "yosys.pb.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct ProtobufDesignSerializer
+{
+ bool aig_mode_;
+ bool use_selection_;
+ yosys::pb::Design *pb_;
+
+ Design *design_;
+ Module *module_;
+
+ SigMap sigmap_;
+ int sigidcounter_;
+ dict<SigBit, uint64_t> sigids_;
+ pool<Aig> aig_models_;
+
+
+ ProtobufDesignSerializer(bool use_selection, bool aig_mode) :
+ aig_mode_(aig_mode), use_selection_(use_selection) { }
+
+ string get_name(IdString name)
+ {
+ return RTLIL::unescape_id(name);
+ }
+
+
+ void serialize_parameters(google::protobuf::Map<std::string, yosys::pb::Parameter> *out,
+ const dict<IdString, Const> &parameters)
+ {
+ for (auto &param : parameters) {
+ std::string key = get_name(param.first);
+
+
+ yosys::pb::Parameter pb_param;
+
+ if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) {
+ pb_param.set_str(param.second.decode_string());
+ } else if (GetSize(param.second.bits) > 64) {
+ pb_param.set_str(param.second.as_string());
+ } else {
+ pb_param.set_int_(param.second.as_int());
+ }
+
+ (*out)[key] = pb_param;
+ }
+ }
+
+ void get_bits(yosys::pb::BitVector *out, SigSpec sig)
+ {
+ for (auto bit : sigmap_(sig)) {
+ auto sig = out->add_signal();
+
+ // Constant driver.
+ if (bit.wire == nullptr) {
+ if (bit == State::S0) sig->set_constant(sig->CONSTANT_DRIVER_LOW);
+ else if (bit == State::S1) sig->set_constant(sig->CONSTANT_DRIVER_HIGH);
+ else if (bit == State::Sz) sig->set_constant(sig->CONSTANT_DRIVER_Z);
+ else sig->set_constant(sig->CONSTANT_DRIVER_X);
+ continue;
+ }
+
+ // Signal - give it a unique identifier.
+ if (sigids_.count(bit) == 0) {
+ sigids_[bit] = sigidcounter_++;
+ }
+ sig->set_id(sigids_[bit]);
+ }
+ }
+
+ void serialize_module(yosys::pb::Module* out, Module *module)
+ {
+ module_ = module;
+ log_assert(module_->design == design_);
+ sigmap_.set(module_);
+ sigids_.clear();
+ sigidcounter_ = 0;
+
+ serialize_parameters(out->mutable_attribute(), module_->attributes);
+
+ for (auto n : module_->ports) {
+ Wire *w = module->wire(n);
+ if (use_selection_ && !module_->selected(w))
+ continue;
+
+ yosys::pb::Module::Port pb_port;
+ pb_port.set_direction(w->port_input ? w->port_output ?
+ yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT : yosys::pb::DIRECTION_OUTPUT);
+ get_bits(pb_port.mutable_bits(), w);
+ (*out->mutable_port())[get_name(n)] = pb_port;
+ }
+
+ for (auto c : module_->cells()) {
+ if (use_selection_ && !module_->selected(c))
+ continue;
+
+ yosys::pb::Module::Cell pb_cell;
+ pb_cell.set_hide_name(c->name[0] == '$');
+ pb_cell.set_type(get_name(c->type));
+
+ if (aig_mode_) {
+ Aig aig(c);
+ if (aig.name.empty())
+ continue;
+ pb_cell.set_model(aig.name);
+ aig_models_.insert(aig);
+ }
+ serialize_parameters(pb_cell.mutable_parameter(), c->parameters);
+ serialize_parameters(pb_cell.mutable_attribute(), c->attributes);
+
+ if (c->known()) {
+ for (auto &conn : c->connections()) {
+ yosys::pb::Direction direction = yosys::pb::DIRECTION_OUTPUT;
+ if (c->input(conn.first))
+ direction = c->output(conn.first) ? yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT;
+ (*pb_cell.mutable_port_direction())[get_name(conn.first)] = direction;
+ }
+ }
+ for (auto &conn : c->connections()) {
+ yosys::pb::BitVector vec;
+ get_bits(&vec, conn.second);
+ (*pb_cell.mutable_connection())[get_name(conn.first)] = vec;
+ }
+
+ (*out->mutable_cell())[get_name(c->name)] = pb_cell;
+ }
+
+ for (auto w : module_->wires()) {
+ if (use_selection_ && !module_->selected(w))
+ continue;
+
+ auto netname = out->add_netname();
+ netname->set_hide_name(w->name[0] == '$');
+ get_bits(netname->mutable_bits(), w);
+ serialize_parameters(netname->mutable_attributes(), w->attributes);
+ }
+ }
+
+
+ void serialize_models(google::protobuf::Map<string, yosys::pb::Model> *models)
+ {
+ for (auto &aig : aig_models_) {
+ yosys::pb::Model pb_model;
+ for (auto &node : aig.nodes) {
+ auto pb_node = pb_model.add_node();
+ if (node.portbit >= 0) {
+ if (node.inverter) {
+ pb_node->set_type(pb_node->TYPE_NPORT);
+ } else {
+ pb_node->set_type(pb_node->TYPE_PORT);
+ }
+ auto port = pb_node->mutable_port();
+ port->set_portname(log_id(node.portname));
+ port->set_bitindex(node.portbit);
+ } else if (node.left_parent < 0 && node.right_parent < 0) {
+ if (node.inverter) {
+ pb_node->set_type(pb_node->TYPE_TRUE);
+ } else {
+ pb_node->set_type(pb_node->TYPE_FALSE);
+ }
+ } else {
+ if (node.inverter) {
+ pb_node->set_type(pb_node->TYPE_NAND);
+ } else {
+ pb_node->set_type(pb_node->TYPE_AND);
+ }
+ auto gate = pb_node->mutable_gate();
+ gate->set_left(node.left_parent);
+ gate->set_right(node.right_parent);
+ }
+ for (auto &op : node.outports) {
+ auto pb_op = pb_node->add_out_port();
+ pb_op->set_name(log_id(op.first));
+ pb_op->set_bit_index(op.second);
+ }
+ }
+ (*models)[aig.name] = pb_model;
+ }
+ }
+
+ void serialize_design(yosys::pb::Design *pb, Design *design)
+ {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+ pb_ = pb;
+ pb_->Clear();
+ pb_->set_creator(yosys_version_str);
+
+ design_ = design;
+ design_->sort();
+
+ auto modules = use_selection_ ? design_->selected_modules() : design_->modules();
+ for (auto mod : modules) {
+ yosys::pb::Module pb_mod;
+ serialize_module(&pb_mod, mod);
+ (*pb->mutable_modules())[mod->name.str()] = pb_mod;
+ }
+
+ serialize_models(pb_->mutable_models());
+ }
+};
+
+struct ProtobufBackend : public Backend {
+ ProtobufBackend(): Backend("protobuf", "write design to a Protocol Buffer file") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" write_protobuf [options] [filename]\n");
+ log("\n");
+ log("Write a JSON netlist of the current design.\n");
+ log("\n");
+ log(" -aig\n");
+ log(" include AIG models for the different gate types\n");
+ log("\n");
+ log(" -text\n");
+ log(" output protobuf in Text/ASCII representation\n");
+ log("\n");
+ log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
+ log("Yosys source code distribution.\n");
+ log("\n");
+ }
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ bool aig_mode = false;
+ bool text_mode = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-aig") {
+ aig_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-text") {
+ text_mode = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(f, filename, args, argidx);
+
+ log_header(design, "Executing Protobuf backend.\n");
+
+ yosys::pb::Design pb;
+ ProtobufDesignSerializer serializer(false, aig_mode);
+ serializer.serialize_design(&pb, design);
+
+ if (text_mode) {
+ string out;
+ google::protobuf::TextFormat::PrintToString(pb, &out);
+ *f << out;
+ } else {
+ pb.SerializeToOstream(f);
+ }
+ }
+} ProtobufBackend;
+
+struct ProtobufPass : public Pass {
+ ProtobufPass() : Pass("protobuf", "write design in Protobuf format") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" protobuf [options] [selection]\n");
+ log("\n");
+ log("Write a JSON netlist of all selected objects.\n");
+ log("\n");
+ log(" -o <filename>\n");
+ log(" write to the specified file.\n");
+ log("\n");
+ log(" -aig\n");
+ log(" include AIG models for the different gate types\n");
+ log("\n");
+ log(" -text\n");
+ log(" output protobuf in Text/ASCII representation\n");
+ log("\n");
+ log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
+ log("Yosys source code distribution.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ std::string filename;
+ bool aig_mode = false;
+ bool text_mode = false;
+
+ 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] == "-aig") {
+ aig_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-text") {
+ text_mode = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ std::ostream *f;
+ std::stringstream buf;
+
+ if (!filename.empty()) {
+ std::ofstream *ff = new std::ofstream;
+ ff->open(filename.c_str(), std::ofstream::trunc);
+ if (ff->fail()) {
+ delete ff;
+ log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
+ }
+ f = ff;
+ } else {
+ f = &buf;
+ }
+
+ yosys::pb::Design pb;
+ ProtobufDesignSerializer serializer(true, aig_mode);
+ serializer.serialize_design(&pb, design);
+
+ if (text_mode) {
+ string out;
+ google::protobuf::TextFormat::PrintToString(pb, &out);
+ *f << out;
+ } else {
+ pb.SerializeToOstream(f);
+ }
+
+ if (!filename.empty()) {
+ delete f;
+ } else {
+ log("%s", buf.str().c_str());
+ }
+ }
+} ProtobufPass;
+
+PRIVATE_NAMESPACE_END;
diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc
index c9656caff..349bc5a6d 100644
--- a/backends/simplec/simplec.cc
+++ b/backends/simplec/simplec.cc
@@ -742,7 +742,7 @@ struct SimplecWorker
struct SimplecBackend : public Backend {
SimplecBackend() : Backend("simplec", "convert design to simple C code") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -761,7 +761,7 @@ struct SimplecBackend : public Backend {
log("THIS COMMAND IS UNDER CONSTRUCTION\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
reserved_cids.clear();
id2cid.clear();
diff --git a/backends/smt2/Makefile.inc b/backends/smt2/Makefile.inc
index eacda2734..dce82f01a 100644
--- a/backends/smt2/Makefile.inc
+++ b/backends/smt2/Makefile.inc
@@ -6,7 +6,7 @@ ifneq ($(CONFIG),emcc)
TARGETS += yosys-smtbmc
yosys-smtbmc: backends/smt2/smtbmc.py
- $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(__file__) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new
+ $(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 $@
diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc
index 47c993d05..e2777ae04 100644
--- a/backends/smt2/smt2.cc
+++ b/backends/smt2/smt2.cc
@@ -135,6 +135,24 @@ 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("$mem") && conn.first.in("\\RD_CLK", "\\WR_CLK"))
+ {
+ SigSpec clk = sigmap(conn.second);
+ for (int i = 0; i < GetSize(clk); i++)
+ {
+ if (clk[i].wire == nullptr)
+ continue;
+
+ if (cell->getParam(conn.first == "\\RD_CLK" ? "\\RD_CLK_ENABLE" : "\\WR_CLK_ENABLE")[i] != State::S1)
+ continue;
+
+ 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("$dff", "$_DFF_P_", "$_DFF_N_") && conn.first.in("\\CLK", "\\C"))
{
bool posedge = (cell->type == "$_DFF_N_") || (cell->type == "$dff" && cell->getParam("\\CLK_POLARITY").as_bool());
@@ -748,7 +766,7 @@ struct Smt2Worker
if (statebv)
makebits(stringf("%s_h %s", get_id(module), get_id(cell->name)), mod_stbv_width.at(cell->type));
- if (statedt)
+ else if (statedt)
dtmembers.push_back(stringf(" (|%s_h %s| |%s_s|)\n",
get_id(module), get_id(cell->name), get_id(cell->type)));
else
@@ -1233,7 +1251,7 @@ struct Smt2Worker
struct Smt2Backend : public Backend {
Smt2Backend() : Backend("smt2", "write design to SMT-LIBv2 file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1389,7 +1407,7 @@ struct Smt2Backend : public Backend {
log("from non-zero to zero in the test design.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::ifstream template_f;
bool bvmode = true, memmode = true, wiresmode = false, verbose = false, statebv = false, statedt = false;
diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py
index 1d5c89d8e..3fc823e3e 100644
--- a/backends/smt2/smtio.py
+++ b/backends/smt2/smtio.py
@@ -17,7 +17,9 @@
#
import sys, re, os, signal
-import resource, subprocess
+import subprocess
+if os.name == "posix":
+ import resource
from copy import deepcopy
from select import select
from time import time
@@ -27,12 +29,13 @@ from threading import Thread
# This is needed so that the recursive SMT2 S-expression parser
# does not run out of stack frames when parsing large expressions
-smtio_reclimit = 64 * 1024
-smtio_stacksize = 128 * 1024 * 1024
-if sys.getrecursionlimit() < smtio_reclimit:
- sys.setrecursionlimit(smtio_reclimit)
-if resource.getrlimit(resource.RLIMIT_STACK)[0] < smtio_stacksize:
- resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, -1))
+if os.name == "posix":
+ smtio_reclimit = 64 * 1024
+ smtio_stacksize = 128 * 1024 * 1024
+ if sys.getrecursionlimit() < smtio_reclimit:
+ sys.setrecursionlimit(smtio_reclimit)
+ if resource.getrlimit(resource.RLIMIT_STACK)[0] < smtio_stacksize:
+ resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, -1))
# currently running solvers (so we can kill them)
@@ -51,8 +54,9 @@ def force_shutdown(signum, frame):
os.kill(p.pid, signal.SIGTERM)
sys.exit(1)
+if os.name == "posix":
+ signal.signal(signal.SIGHUP, force_shutdown)
signal.signal(signal.SIGINT, force_shutdown)
-signal.signal(signal.SIGHUP, force_shutdown)
signal.signal(signal.SIGTERM, force_shutdown)
def except_hook(exctype, value, traceback):
@@ -218,7 +222,7 @@ class SmtIo:
def timestamp(self):
secs = int(time() - self.start_time)
- return "## %6d %3d:%02d:%02d " % (secs, secs // (60*60), (secs // 60) % 60, secs % 60)
+ return "## %3d:%02d:%02d " % (secs // (60*60), (secs // 60) % 60, secs % 60)
def replace_in_stmt(self, stmt, pat, repl):
if stmt == pat:
@@ -294,20 +298,21 @@ class SmtIo:
def p_read(self):
assert self.p is not None
- assert self.p_running
if self.p_next is not None:
data = self.p_next
self.p_next = None
return data
+ if not self.p_running:
+ return ""
return self.p_queue.get()
- def p_poll(self):
+ def p_poll(self, timeout=0.1):
assert self.p is not None
assert self.p_running
if self.p_next is not None:
return False
try:
- self.p_next = self.p_queue.get(True, 0.1)
+ self.p_next = self.p_queue.get(True, timeout)
return False
except Empty:
return True
@@ -580,12 +585,12 @@ class SmtIo:
if count_brackets == 0:
break
if self.solver != "dummy" and self.p.poll():
- print("SMT Solver terminated unexpectedly: %s" % "".join(stmt), flush=True)
+ print("%s Solver terminated unexpectedly: %s" % (self.timestamp(), "".join(stmt)), flush=True)
sys.exit(1)
stmt = "".join(stmt)
if stmt.startswith("(error"):
- print("SMT Solver Error: %s" % stmt, file=sys.stderr, flush=True)
+ print("%s Solver Error: %s" % (self.timestamp(), stmt), flush=True)
if self.solver != "dummy":
self.p_close()
sys.exit(1)
@@ -645,13 +650,43 @@ class SmtIo:
print("\b \b" * num_bs, end="", file=sys.stderr)
sys.stderr.flush()
+ else:
+ count = 0
+ while self.p_poll(60):
+ count += 1
+ msg = None
+
+ if count == 1:
+ msg = "1 minute"
+
+ elif count in [5, 10, 15, 30]:
+ msg = "%d minutes" % count
+
+ elif count == 60:
+ msg = "1 hour"
+
+ elif count % 60 == 0:
+ msg = "%d hours" % (count // 60)
+
+ if msg is not None:
+ print("%s waiting for solver (%s)" % (self.timestamp(), msg), flush=True)
+
result = self.read()
- assert result in ["sat", "unsat"]
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"]:
+ if result == "":
+ print("%s Unexpected EOF response from solver." % (self.timestamp()), flush=True)
+ else:
+ print("%s Unexpected response from solver: %s" % (self.timestamp(), result), flush=True)
+ if self.solver != "dummy":
+ self.p_close()
+ sys.exit(1)
+
return result
def parse(self, stmt):
@@ -706,6 +741,9 @@ class SmtIo:
return h
def bv2bin(self, v):
+ if type(v) is list and len(v) == 3 and v[0] == "_" and v[1].startswith("bv"):
+ x, n = int(v[1][2:]), int(v[2])
+ return "".join("1" if (x & (1 << i)) else "0" for i in range(n-1, -1, -1))
if v == "true": return "1"
if v == "false": return "0"
if v.startswith("#b"):
@@ -981,7 +1019,7 @@ class MkVcd:
for i in range(len(uipath)):
uipath[i] = re.sub(r"\[([^\]]*)\]", r"<\1>", uipath[i])
- while uipath[:len(scope)] != scope[:-1]:
+ while uipath[:len(scope)] != scope:
print("$upscope $end", file=self.f)
scope = scope[:-1]
@@ -1019,4 +1057,3 @@ class MkVcd:
print("b0 %s" % self.nets[path][0], file=self.f)
else:
print("b1 %s" % self.nets[path][0], file=self.f)
-
diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc
index 768969e6b..b8383412b 100644
--- a/backends/smv/smv.cc
+++ b/backends/smv/smv.cc
@@ -675,7 +675,7 @@ struct SmvWorker
struct SmvBackend : public Backend {
SmvBackend() : Backend("smv", "write design to SMV file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -693,7 +693,7 @@ struct SmvBackend : public Backend {
log("THIS COMMAND IS UNDER CONSTRUCTION\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::ifstream template_f;
bool verbose = false;
diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc
index 4101cbf98..b6a3f1e77 100644
--- a/backends/spice/spice.cc
+++ b/backends/spice/spice.cc
@@ -132,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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -161,7 +161,7 @@ struct SpiceBackend : public Backend {
log(" set the specified module as design top module\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string top_module_name;
RTLIL::Module *top_module = NULL;
diff --git a/backends/table/table.cc b/backends/table/table.cc
index 27b7edfff..979273dd3 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> 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 bdf705056..d3262ec47 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -779,6 +779,19 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
+ if (cell->type == "$lut")
+ {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, cell->getPort("\\Y"));
+ f << stringf(" = ");
+ dump_const(f, cell->parameters.at("\\LUT"));
+ f << stringf(" >> ");
+ dump_attributes(f, "", cell->attributes, ' ');
+ dump_sigspec(f, cell->getPort("\\A"));
+ f << stringf(";\n");
+ return true;
+ }
+
if (cell->type == "$dffsr")
{
SigSpec sig_clk = cell->getPort("\\CLK");
@@ -897,6 +910,42 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
+ if (cell->type == "$dlatch")
+ {
+ RTLIL::SigSpec sig_en;
+ bool pol_en = false;
+
+ 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("\\Q"), reg_name);
+
+ if (!out_is_reg_wire) {
+ 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 @*\n", indent.c_str());
+
+ f << stringf("%s" " if (%s", indent.c_str(), pol_en ? "" : "!");
+ dump_sigspec(f, sig_en);
+ f << stringf(")\n");
+
+ f << stringf("%s" " %s = ", indent.c_str(), reg_name.c_str());
+ dump_cell_expr_port(f, cell, "D", false);
+ f << stringf(";\n");
+
+ if (!out_is_reg_wire) {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, cell->getPort("\\Q"));
+ f << stringf(" = %s;\n", reg_name.c_str());
+ }
+
+ return true;
+ }
+
if (cell->type == "$mem")
{
RTLIL::IdString memid = cell->parameters["\\MEMID"].decode_string();
@@ -1446,7 +1495,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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1514,7 +1563,7 @@ struct VerilogBackend : public Backend {
log("this command is called on a design with RTLIL processes.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing Verilog backend.\n");
@@ -1537,6 +1586,8 @@ struct VerilogBackend : public Backend {
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_");
diff --git a/examples/basys3/example.xdc b/examples/basys3/example.xdc
index c1fd0e925..8cdaa1996 100644
--- a/examples/basys3/example.xdc
+++ b/examples/basys3/example.xdc
@@ -19,3 +19,6 @@ set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN L1 } [get_ports {LD[15]}]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports CLK]
+set_property CONFIG_VOLTAGE 3.3 [current_design]
+set_property CFGBVS VCCO [current_design]
+
diff --git a/examples/basys3/run_prog.tcl b/examples/basys3/run_prog.tcl
index d711af840..b078ad511 100644
--- a/examples/basys3/run_prog.tcl
+++ b/examples/basys3/run_prog.tcl
@@ -1,3 +1,4 @@
+open_hw
connect_hw_server
open_hw_target [lindex [get_hw_targets] 0]
set_property PROGRAM.FILE example.bit [lindex [get_hw_devices] 0]
diff --git a/examples/cmos/counter.ys b/examples/cmos/counter.ys
index a784f3465..d0b093667 100644
--- a/examples/cmos/counter.ys
+++ b/examples/cmos/counter.ys
@@ -1,11 +1,12 @@
-
read_verilog counter.v
read_verilog -lib cmos_cells.v
-proc;; memory;; techmap;;
-
+synth
dfflibmap -liberty cmos_cells.lib
-abc -liberty cmos_cells.lib;;
+abc -liberty cmos_cells.lib
+opt_clean
+
+stat -liberty cmos_cells.lib
# http://vlsiarch.ecen.okstate.edu/flows/MOSIS_SCMOS/latest/cadence/lib/tsmc025/signalstorm/osu025_stdcells.lib
# dfflibmap -liberty osu025_stdcells.lib
@@ -13,4 +14,3 @@ abc -liberty cmos_cells.lib;;
write_verilog synth.v
write_spice synth.sp
-
diff --git a/examples/cxx-api/evaldemo.cc b/examples/cxx-api/evaldemo.cc
index e5cc8d8e7..34373487d 100644
--- a/examples/cxx-api/evaldemo.cc
+++ b/examples/cxx-api/evaldemo.cc
@@ -22,7 +22,7 @@ struct EvalDemoPass : public Pass
{
EvalDemoPass() : Pass("evaldemo") { }
- virtual void execute(vector<string>, Design *design)
+ void execute(vector<string>, Design *design) YS_OVERRIDE
{
Module *module = design->top_module();
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index b8f25e53e..e79be953a 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -44,7 +44,7 @@ namespace AST {
// instanciate global variables (private API)
namespace AST_INTERNAL {
- bool flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
+ bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
AstNode *current_ast, *current_ast_mod;
std::map<std::string, AstNode*> current_scope;
@@ -171,8 +171,8 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
AstNode *attr = attributes.at(id);
if (attr->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- id.c_str(), attr->filename.c_str(), attr->linenum);
+ log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n",
+ id.c_str());
return attr->integer != 0;
}
@@ -267,10 +267,12 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
std::string type_name = type2str(type);
fprintf(f, "%s%s <%s:%d>", indent.c_str(), type_name.c_str(), filename.c_str(), linenum);
- if (id2ast)
- fprintf(f, " [%p -> %p]", this, id2ast);
- else
- fprintf(f, " [%p]", this);
+ if (!flag_no_dump_ptr) {
+ if (id2ast)
+ fprintf(f, " [%p -> %p]", this, id2ast);
+ else
+ fprintf(f, " [%p]", this);
+ }
if (!str.empty())
fprintf(f, " str='%s'", str.c_str());
@@ -961,8 +963,8 @@ static AstModule* process_module(AstNode *ast, bool defer)
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), ast->filename.c_str(), ast->linenum);
+ 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++) {
@@ -1008,12 +1010,13 @@ static AstModule* process_module(AstNode *ast, bool defer)
}
// create AstModule instances for all modules in the AST tree and add them to 'design'
-void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool dump_rtlil,
- bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer, bool autowire)
+void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog, bool dump_rtlil,
+ bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire)
{
current_ast = ast;
flag_dump_ast1 = dump_ast1;
flag_dump_ast2 = dump_ast2;
+ flag_no_dump_ptr = no_dump_ptr;
flag_dump_vlog = dump_vlog;
flag_dump_rtlil = dump_rtlil;
flag_nolatches = nolatches;
@@ -1048,12 +1051,20 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
(*it)->str = "$abstract" + (*it)->str;
if (design->has((*it)->str)) {
- if (!ignore_redef)
- log_error("Re-definition of module `%s' at %s:%d!\n",
+ RTLIL::Module *existing_mod = design->module((*it)->str);
+ if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
+ log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n",
+ (*it)->str.c_str());
+ } else if (nooverwrite) {
+ log("Ignoring re-definition of module `%s' at %s:%d.\n",
(*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
- log("Ignoring re-definition of module `%s' at %s:%d!\n",
- (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
- continue;
+ continue;
+ } else {
+ 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));
@@ -1195,4 +1206,3 @@ void AST::use_internal_line_num()
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 8a640b1cc..7e97bdb3b 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
@@ -274,17 +274,17 @@ namespace AST
};
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
- void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool dump_rtlil, bool nolatches, bool nomeminit,
- bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer, bool autowire);
+ void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog, bool dump_rtlil, bool nolatches, bool nomeminit,
+ bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire);
// parametric modules are supported directly by the AST library
// therefore we need our own derivate of RTLIL::Module with overloaded virtual functions
struct AstModule : RTLIL::Module {
AstNode *ast;
bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire;
- virtual ~AstModule();
- virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail);
- virtual RTLIL::Module *clone() const;
+ ~AstModule() YS_OVERRIDE;
+ RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE;
+ RTLIL::Module *clone() const YS_OVERRIDE;
};
// this must be set by the language frontend before parsing the sources
@@ -305,7 +305,7 @@ namespace AST
namespace AST_INTERNAL
{
// internal state variables
- extern bool flag_dump_ast1, flag_dump_ast2, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
+ extern bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
extern AST::AstNode *current_ast, *current_ast_mod;
extern std::map<std::string, AST::AstNode*> current_scope;
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 57ba9668d..0f7e910f3 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -55,8 +55,8 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi
if (gen_attributes)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ 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();
}
@@ -89,8 +89,8 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
if (that != NULL)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ 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();
}
@@ -117,8 +117,8 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ 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();
}
@@ -152,8 +152,8 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ 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();
}
@@ -207,8 +207,8 @@ struct AST_INTERNAL::ProcessGenerator
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_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), always->filename.c_str(), always->linenum);
+ 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();
}
current_module->processes[proc->name] = proc;
@@ -223,16 +223,22 @@ struct AST_INTERNAL::ProcessGenerator
bool found_global_syncs = false;
bool found_anyedge_syncs = false;
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("\\gclk")) {
+ found_global_syncs = true;
+ }
if (child->type == AST_EDGE) {
if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->str == "\\$global_clock")
found_global_syncs = true;
else
found_anyedge_syncs = true;
}
+ }
if (found_anyedge_syncs) {
if (found_global_syncs)
- log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum);
+ 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");
@@ -242,14 +248,17 @@ struct AST_INTERNAL::ProcessGenerator
bool found_clocked_sync = false;
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("\\gclk"))
+ continue;
found_clocked_sync = true;
if (found_global_syncs || found_anyedge_syncs)
- log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum);
+ 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_error("Found posedge/negedge event on a signal that is not 1 bit wide at %s:%d!\n", always->filename.c_str(), always->linenum);
+ 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);
}
@@ -471,8 +480,8 @@ struct AST_INTERNAL::ProcessGenerator
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), ast->filename.c_str(), ast->linenum);
+ 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();
}
@@ -540,12 +549,12 @@ struct AST_INTERNAL::ProcessGenerator
break;
case AST_WIRE:
- log_error("Found wire declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n");
break;
case AST_PARAMETER:
case AST_LOCALPARAM:
- log_error("Found parameter declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Found parameter declaration in block without label!\n");
break;
case AST_NONE:
@@ -593,7 +602,7 @@ 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_error("Failed to resolve identifier %s for width detection at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ 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;
@@ -603,7 +612,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_error("Failed to detect width for parameter %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ 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) {
@@ -615,7 +624,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
// log("---\n");
// id_ast->dumpAst(NULL, "decl> ");
// dumpAst(NULL, "ref> ");
- log_error("Failed to detect width of signal access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ 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;
@@ -626,10 +635,10 @@ 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_error("Failed to detect width of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ 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;
} else
- log_error("Failed to detect width for identifier %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ 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;
@@ -639,8 +648,8 @@ 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_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+ str.c_str());
this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
delete left_at_zero_ast;
delete right_at_zero_ast;
@@ -656,7 +665,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_error("Left operand of tobits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ 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;
@@ -684,7 +693,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_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ 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;
@@ -758,7 +767,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_error("Failed to detect width of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ 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;
@@ -768,8 +777,8 @@ 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_error("System function %s called with non-const argument at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ 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)));
}
break;
@@ -790,8 +799,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
default:
for (auto f : log_files)
current_ast->dumpAst(f, "verilog-ast> ");
- log_error("Don't know how to detect sign and width for %s node at %s:%d!\n",
- type2str(type).c_str(), filename.c_str(), linenum);
+ 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)
@@ -854,11 +863,11 @@ 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_error("Re-definition of signal `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Re-definition of signal `%s'!\n",
+ str.c_str());
if (!range_valid)
- log_error("Signal `%s' with non-constant width at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n",
+ str.c_str());
log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
@@ -872,8 +881,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
wire->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -882,16 +891,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Memory for an AST_MEMORY node
case AST_MEMORY: {
if (current_module->memories.count(str) != 0)
- log_error("Re-definition of memory `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ 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_error("Memory `%s' with non-constant width or size at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ 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["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -908,8 +917,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
memory->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -928,8 +937,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_REALVALUE:
{
RTLIL::SigSpec sig = realAsConst(width_hint);
- log_warning("converting real value %e to binary %s at %s:%d.\n",
- realvalue, log_signal(sig), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
+ realvalue, log_signal(sig));
return sig;
}
@@ -949,25 +958,25 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
wire->name = str;
if (flag_autowire)
- log_warning("Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "Identifier `%s' is implicitly declared.\n", str.c_str());
else
- log_error("Identifier `%s' is implicitly declared at %s:%d and `default_nettype is set to none.\n", str.c_str(), filename.c_str(), linenum);
+ 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) {
if (id2ast->children[0]->type != AST_CONSTANT)
- log_error("Parameter %s does not evaluate to constant value at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ 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 || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE &&
id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0)
- log_error("Identifier `%s' doesn't map to any signal at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n",
+ str.c_str());
if (id2ast->type == AST_MEMORY)
- log_error("Identifier `%s' does map to an unexpanded memory at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n",
+ str.c_str());
wire = current_module->wires_[str];
chunk.wire = wire;
@@ -985,8 +994,8 @@ 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_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+ str.c_str());
int width = 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());
@@ -1014,11 +1023,11 @@ 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_warning("Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
+ str.c_str());
else
- log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n",
- str.c_str(), filename.c_str(), linenum, chunk.width);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n",
+ str.c_str(), chunk.width);
chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
} else {
if (chunk.width + chunk.offset > source_width) {
@@ -1031,11 +1040,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
chunk.offset += add_undef_bits_lsb;
}
if (add_undef_bits_lsb)
- log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n",
- str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
+ str.c_str(), add_undef_bits_lsb);
if (add_undef_bits_msb)
- log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n",
- str.c_str(), filename.c_str(), linenum, add_undef_bits_msb);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
+ str.c_str(), add_undef_bits_msb);
}
}
}
@@ -1074,7 +1083,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_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ 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++)
@@ -1291,6 +1300,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
+ if (!sign_hint)
+ is_signed = false;
+
return RTLIL::SigSpec(wire);
}
@@ -1310,7 +1322,7 @@ 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_error("Memory init with non-constant word count at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Memory init with non-constant word count!\n");
num_words = int(children[2]->asInt(false));
cell->parameters["\\WORDS"] = RTLIL::Const(num_words);
}
@@ -1367,8 +1379,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -1389,10 +1401,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
new_left.append(left[i]);
new_right.append(right[i]);
}
- log_warning("Ignoring assignment to constant bits at %s:%d:\n"
- " old assignment: %s = %s\n new assignment: %s = %s.\n",
- filename.c_str(), linenum, log_signal(left), log_signal(right),
- log_signal(new_left), log_signal(new_right));
+ 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));
left = new_left;
right = new_right;
}
@@ -1406,8 +1418,7 @@ 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_error("Re-definition of cell `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Re-definition of cell `%s'!\n", str.c_str());
RTLIL::Cell *cell = current_module->addCell(str, "");
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -1423,16 +1434,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (child->type == AST_PARASET) {
IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
if (child->children[0]->type == AST_REALVALUE) {
- log_warning("Replacing floating point parameter %s.%s = %f with string at %s:%d.\n",
- log_id(cell), log_id(paraname), child->children[0]->realvalue,
- filename.c_str(), linenum);
+ 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);
auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue));
strnode->cloneInto(child->children[0]);
delete strnode;
}
if (child->children[0]->type != AST_CONSTANT)
- log_error("Parameter %s.%s with non-constant value at %s:%d!\n",
- log_id(cell), log_id(paraname), filename.c_str(), linenum);
+ 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();
continue;
}
@@ -1453,8 +1463,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -1481,19 +1491,19 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
int width = width_hint;
if (GetSize(children) > 1)
- log_error("System function %s got %d arguments, expected 1 or 0 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), GetSize(children), filename.c_str(), linenum);
+ 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_error("System function %s called with non-const argument at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ 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_error("Failed to detect width of %s at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ 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["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -1502,7 +1512,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (attributes.count("\\reg")) {
auto &attr = attributes.at("\\reg");
if (attr->type != AST_CONSTANT)
- log_error("Attribute `reg' with non-constant value at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `reg' with non-constant value!\n");
cell->attributes["\\reg"] = attr->asAttrConst();
}
@@ -1520,8 +1530,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto f : log_files)
current_ast->dumpAst(f, "verilog-ast> ");
type_name = type2str(type);
- log_error("Don't know how to generate RTLIL code for %s node at %s:%d!\n",
- type_name.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n",
+ type_name.c_str());
}
return RTLIL::SigSpec();
@@ -1551,4 +1561,3 @@ RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const dict<RTLIL::SigBit, RTLIL
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index ae46e4bc9..e741bd92a 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -177,13 +177,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_warning("Ignoring call to system %s %s at %s:%d.\n", type == AST_FCALL ? "function" : "task", str.c_str(), filename.c_str(), linenum);
+ 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_warning("System task `%s' outside initial block is unsupported at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str());
delete_children();
str = std::string();
}
@@ -195,14 +195,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
int nargs = GetSize(children);
if (nargs < 1)
- log_error("System task `%s' got %d arguments, expected >= 1 at %s:%d.\n",
- str.c_str(), int(children.size()), filename.c_str(), linenum);
+ 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_error("Failed to evaluate system task `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ 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();
// Other arguments are placeholders. Process the string as we go through it
@@ -215,7 +215,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
// If there's no next character, that's a problem
if (i+1 >= sformat.length())
- log_error("System task `%s' called with `%%' at end of string at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' called with `%%' at end of string.\n", str.c_str());
char cformat = sformat[++i];
@@ -239,13 +239,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
case 'x':
case 'X':
if (next_arg >= GetSize(children))
- log_error("Missing argument for %%%c format specifier in system task `%s' at %s:%d.\n",
- cformat, str.c_str(), filename.c_str(), linenum);
+ 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_error("Failed to evaluate system task `%s' with non-constant argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant argument.\n", str.c_str());
break;
case 'm':
@@ -253,7 +253,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
break;
default:
- log_error("System task `%s' called with invalid/unsupported format specifier at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str());
break;
}
@@ -378,7 +378,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
continue;
wires_are_incompatible:
if (stage > 1)
- log_error("Incompatible re-declaration of wire %s at %s:%d.\n", node->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", node->str.c_str());
continue;
}
this_wire_scope[node->str] = node;
@@ -406,7 +406,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_error("Invalid nesting of always blocks and/or initializations at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Invalid nesting of always blocks and/or initializations.\n");
current_always = this;
current_always_clocked = false;
@@ -465,7 +465,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_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
+ 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;
@@ -709,7 +709,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_error("Module name in defparam at %s:%d contains non-constant expressions!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Module name in defparam contains non-constant expressions!\n");
string modname, paramname = children[0]->str;
@@ -726,13 +726,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (pos == std::string::npos)
- log_error("Can't find object for defparam `%s` at %s:%d!\n", RTLIL::unescape_id(paramname).c_str(), filename.c_str(), linenum);
+ 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_error("Defparam argument `%s . %s` does not match a cell at %s:%d!\n",
- RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str(), filename.c_str(), linenum);
+ 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);
paraset->str = paramname;
@@ -746,7 +746,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_PREFIX) {
if (children[0]->type != AST_CONSTANT) {
// dumpAst(NULL, "> ");
- log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename.c_str(), linenum);
+ 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);
@@ -762,9 +762,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_error("Left operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left operand of to_bits expression is not constant!\n");
if (children[1]->type != AST_CONSTANT)
- log_error("Right operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ 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;
@@ -828,7 +828,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_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum);
+ 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();
@@ -846,7 +846,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_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str), filename.c_str(), linenum);
+ 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();
@@ -875,12 +875,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
if (children.size() > 1 && children[1]->type == AST_RANGE) {
if (!children[1]->range_valid)
- log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
+ 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_warning("converting real value %e to binary %s at %s:%d.\n",
- children[0]->realvalue, log_signal(constvalue), filename.c_str(), linenum);
+ 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);
did_something = true;
@@ -938,7 +938,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_error("Invalid bit-select on memory access at %s:%d!\n", filename.c_str(), linenum);
+ 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);
@@ -988,10 +988,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (type == AST_WHILE)
- log_error("While loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n");
if (type == AST_REPEAT)
- log_error("Repeat loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Repeat loops are only allowed in constant functions!\n");
// unroll for loops and generate-for blocks
if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0)
@@ -1006,31 +1006,31 @@ 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_error("Unsupported 1st expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported 1st expression of generate for-loop!\n");
if (next_ast->type != AST_ASSIGN_EQ)
- log_error("Unsupported 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
+ 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_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
+ 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_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
+ 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_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
+ 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_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
+ 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_error("Incompatible left-hand sides in 1st and 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
+ 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();
while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
if (varbuf->type != AST_CONSTANT)
- log_error("Right hand side of 1st expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
+ 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;
@@ -1052,7 +1052,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (buf->type != AST_CONSTANT)
- log_error("2nd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n");
if (buf->integer == 0) {
delete buf;
@@ -1093,7 +1093,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (buf->simplify(true, false, false, stage, 32, true, false)) { }
if (buf->type != AST_CONSTANT)
- log_error("Right hand side of 3rd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
+ 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;
@@ -1110,8 +1110,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)
- log_error("Local declaration in unnamed block at %s:%d is an unsupported SystemVerilog feature!\n",
- children[i]->filename.c_str(), children[i]->linenum);
+ log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
}
// transform block with name
@@ -1159,7 +1158,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_error("Condition for generate if at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Condition for generate if is not constant!\n");
}
if (buf->asBool() != 0) {
delete buf;
@@ -1200,7 +1199,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_error("Condition for generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Condition for generate case is not constant!\n");
}
bool ref_signed = buf->is_signed;
@@ -1234,7 +1233,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_error("Expression in generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
+ 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();
@@ -1275,7 +1274,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_error("Non-constant array range on cell array at %s:%d.\n", filename.c_str(), linenum);
+ 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;
@@ -1286,7 +1285,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_error("Cell arrays of primitives are currently not supported at %s:%d.\n", filename.c_str(), linenum);
+ 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());
@@ -1300,8 +1299,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_PRIMITIVE)
{
if (children.size() < 2)
- log_error("Insufficient number of arguments for primitive `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n",
+ str.c_str());
std::vector<AstNode*> children_list;
for (auto child : children) {
@@ -1316,8 +1315,8 @@ 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_error("Invalid number of arguments for primitive `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n",
+ str.c_str());
std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
@@ -1404,8 +1403,8 @@ 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_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ 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;
}
did_something = true;
@@ -1679,7 +1678,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_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
@@ -1775,19 +1774,19 @@ skip_dynamic_range_lvalue_expansion:;
int num_steps = 1;
if (GetSize(children) != 1 && GetSize(children) != 2)
- log_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ 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_error("System function %s is only allowed in clocked blocks at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ 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)
{
AstNode *buf = children[1]->clone();
while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (buf->type != AST_CONSTANT)
- log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ 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;
@@ -1844,12 +1843,12 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell")
{
if (GetSize(children) != 1)
- log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ 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_error("System function %s is only allowed in clocked blocks at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ 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();
AstNode *past = clone();
@@ -1879,13 +1878,13 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$clog2")
{
if (children.size() != 1)
- log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ 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_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ 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())
@@ -1904,12 +1903,12 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$size" || str == "\\$bits")
{
if (str == "\\$bits" && children.size() != 1)
- log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ 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_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ 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;
if (str == "\\$size" && children.size() == 2) {
@@ -1932,7 +1931,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_error("Failed to resolve identifier %s for width detection at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ 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
@@ -1940,15 +1939,15 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$bits") {
if (mem_range->type == AST_RANGE) {
if (!mem_range->range_valid)
- log_error("Failed to detect width of memory access `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ 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_error("Unknown memory depth AST type in `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ 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_error("Failed to detect width of memory access `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ 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;
@@ -1959,9 +1958,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_error("Dimension %d out of range in `%s', as it only has dimensions 1..%d at %s:%d!\n", dim, buf->str.c_str(), dims+1, filename.c_str(), linenum);
+ 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_error("Unknown memory depth AST type in `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
}
}
}
@@ -1982,19 +1981,19 @@ skip_dynamic_range_lvalue_expansion:;
if (func_with_two_arguments) {
if (children.size() != 2)
- log_error("System function %s got %d arguments, expected 2 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ 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_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ 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_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ 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;
children[0]->detectSignWidth(child_width_hint, child_sign_hint);
@@ -2004,8 +2003,8 @@ 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_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ 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;
children[1]->detectSignWidth(child_width_hint, child_sign_hint);
@@ -2057,14 +2056,14 @@ skip_dynamic_range_lvalue_expansion:;
for (int i = 2; i < GetSize(dpi_decl->children); i++)
{
if (i-2 >= GetSize(children))
- log_error("Insufficient number of arguments in DPI function call at %s:%d.\n", filename.c_str(), linenum);
+ 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_error("Failed to evaluate DPI function with non-constant argument at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate DPI function with non-constant argument.\n");
}
newNode = dpi_call(rtype, fname, argtypes, args);
@@ -2076,7 +2075,7 @@ skip_dynamic_range_lvalue_expansion:;
}
if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION)
- log_error("Can't resolve function name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Can't resolve function name `%s'.\n", str.c_str());
}
if (type == AST_TCALL)
@@ -2084,26 +2083,26 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "$finish" || str == "$stop")
{
if (!current_always || current_always->type != AST_INITIAL)
- log_error("System task `%s' outside initial block is unsupported at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str());
- log_error("System task `%s' executed at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ 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_error("System function %s got %d arguments, expected 2-4 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ 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_error("Failed to evaluate system function `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ 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_error("Failed to evaluate system function `%s' with non-memory 2nd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ 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;
@@ -2111,7 +2110,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_error("Failed to evaluate system function `%s' with non-constant 3rd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ 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));
}
@@ -2119,7 +2118,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_error("Failed to evaluate system function `%s' with non-constant 4th argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ 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));
}
@@ -2145,7 +2144,7 @@ skip_dynamic_range_lvalue_expansion:;
}
if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK)
- log_error("Can't resolve task name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Can't resolve task name `%s'.\n", str.c_str());
}
AstNode *decl = current_scope[str];
@@ -2173,9 +2172,9 @@ skip_dynamic_range_lvalue_expansion:;
}
if (in_param)
- log_error("Non-constant function call in constant expression at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Non-constant function call in constant expression.\n");
if (require_const_eval)
- log_error("Function %s can only be called with constant arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Function %s can only be called with constant arguments.\n", str.c_str());
}
size_t arg_count = 0;
@@ -2295,7 +2294,7 @@ skip_dynamic_range_lvalue_expansion:;
goto tcall_incompatible_wires;
} else {
tcall_incompatible_wires:
- log_error("Incompatible re-declaration of wire %s at %s:%d.\n", child->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", child->str.c_str());
}
}
}
@@ -2684,7 +2683,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
yosys_input_files.insert(mem_filename);
if (f.fail())
- log_error("Can not open file `%s` for %s at %s:%d.\n", mem_filename.c_str(), str.c_str(), filename.c_str(), linenum);
+ 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;
@@ -2730,7 +2729,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
char *endptr;
cursor = strtol(nptr, &endptr, 16);
if (!*nptr || *endptr)
- log_error("Can not parse address `%s` for %s at %s:%d.\n", nptr, str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Can not parse address `%s` for %s.\n", nptr, str.c_str());
continue;
}
@@ -2987,7 +2986,7 @@ bool AstNode::mem2reg_check(pool<AstNode*> &mem2reg_set)
return false;
if (children.empty() || children[0]->type != AST_RANGE || GetSize(children[0]->children) != 1)
- log_error("Invalid array access at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Invalid array access.\n");
return true;
}
@@ -3256,13 +3255,13 @@ void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &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_error("Memory access in constant function is not supported in %s:%d (called from %s:%d).\n",
- filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum);
+ 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_error("Non-constant range in %s:%d (called from %s:%d).\n",
- filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum);
+ 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);
}
@@ -3301,8 +3300,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
{
while (child->simplify(true, false, false, 1, -1, false, true)) { }
if (!child->range_valid)
- log_error("Can't determine size of variable %s in %s:%d (called from %s:%d).\n",
- child->str.c_str(), child->filename.c_str(), child->linenum, fcall->filename.c_str(), fcall->linenum);
+ 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;
@@ -3345,24 +3344,24 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue;
if (stmt->children.at(1)->type != AST_CONSTANT)
- log_error("Non-constant expression in constant function at %s:%d (called from %s:%d). X\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ 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_error("Unsupported composite left hand side in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ 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_error("Assignment to non-local variable in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ 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_error("Non-constant range in %s:%d (called from %s:%d).\n",
- range->filename.c_str(), range->linenum, fcall->filename.c_str(), fcall->linenum);
+ 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];
@@ -3393,8 +3392,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (cond->simplify(true, false, false, 1, -1, false, true)) { }
if (cond->type != AST_CONSTANT)
- log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ 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());
@@ -3414,8 +3413,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (num->simplify(true, false, false, 1, -1, false, true)) { }
if (num->type != AST_CONSTANT)
- log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ 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++)
@@ -3452,8 +3451,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (cond->simplify(true, false, false, 1, -1, false, true)) { }
if (cond->type != AST_CONSTANT)
- log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ 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;
@@ -3482,8 +3481,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue;
}
- log_error("Unsupported language construct in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ 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();
}
@@ -3500,4 +3499,3 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc
index e6bb99954..034b3e70c 100644
--- a/frontends/blif/blifparse.cc
+++ b/frontends/blif/blifparse.cc
@@ -83,7 +83,9 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
RTLIL::Module *module = nullptr;
RTLIL::Const *lutptr = NULL;
RTLIL::Cell *sopcell = NULL;
+ RTLIL::Cell *lastcell = nullptr;
RTLIL::State lut_default_state = RTLIL::State::Sx;
+ std::string err_reason;
int blif_maxnum = 0, sopmode = -1;
auto blif_wire = [&](const std::string &wire_name) -> Wire*
@@ -159,6 +161,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
if (module != nullptr)
goto error;
module = new RTLIL::Module;
+ lastcell = nullptr;
module->name = RTLIL::escape_id(strtok(NULL, " \t\r\n"));
obj_attributes = &module->attributes;
obj_parameters = nullptr;
@@ -232,6 +235,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
}
module = nullptr;
+ lastcell = nullptr;
obj_attributes = nullptr;
obj_parameters = nullptr;
continue;
@@ -264,6 +268,22 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
continue;
}
+ if (!strcmp(cmd, ".cname"))
+ {
+ char *p = strtok(NULL, " \t\r\n");
+ if (p == NULL)
+ goto error;
+
+ if(lastcell == nullptr || module == nullptr)
+ {
+ err_reason = stringf("No primative object to attach .cname %s.", p);
+ goto error_with_reason;
+ }
+
+ module->rename(lastcell, p);
+ continue;
+ }
+
if (!strcmp(cmd, ".attr") || !strcmp(cmd, ".param")) {
char *n = strtok(NULL, " \t\r\n");
char *v = strtok(NULL, "\r\n");
@@ -281,12 +301,16 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
const_v.bits[i] = v[n-i-1] != '0' ? State::S1 : State::S0;
}
if (!strcmp(cmd, ".attr")) {
- if (obj_attributes == nullptr)
- goto error;
+ if (obj_attributes == nullptr) {
+ err_reason = stringf("No object to attach .attr too.");
+ goto error_with_reason;
+ }
(*obj_attributes)[id_n] = const_v;
} else {
- if (obj_parameters == nullptr)
- goto error;
+ if (obj_parameters == nullptr) {
+ err_reason = stringf("No object to attach .param too.");
+ goto error_with_reason;
+ }
(*obj_parameters)[id_n] = const_v;
}
continue;
@@ -331,6 +355,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
}
}
+ lastcell = cell;
obj_attributes = &cell->attributes;
obj_parameters = &cell->parameters;
continue;
@@ -383,6 +408,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
cell->setPort(it.first, sig);
}
+ lastcell = cell;
obj_attributes = &cell->attributes;
obj_parameters = &cell->parameters;
continue;
@@ -391,7 +417,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
obj_attributes = nullptr;
obj_parameters = nullptr;
- if (!strcmp(cmd, ".barbuf"))
+ if (!strcmp(cmd, ".barbuf") || !strcmp(cmd, ".conn"))
{
char *p = strtok(NULL, " \t\r\n");
if (p == NULL)
@@ -459,6 +485,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
sopcell->setPort("\\A", input_sig);
sopcell->setPort("\\Y", output_sig);
sopmode = -1;
+ lastcell = sopcell;
}
else
{
@@ -469,6 +496,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
cell->setPort("\\Y", output_sig);
lutptr = &cell->parameters.at("\\LUT");
lut_default_state = RTLIL::State::Sx;
+ lastcell = cell;
}
continue;
}
@@ -546,11 +574,13 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
error:
log_error("Syntax error in line %d!\n", line_count);
+error_with_reason:
+ log_error("Syntax error in line %d: %s\n", line_count, err_reason.c_str());
}
struct BlifFrontend : public Frontend {
BlifFrontend() : Frontend("blif", "read BLIF file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -566,7 +596,7 @@ struct BlifFrontend : public Frontend {
log(" multi-bit port 'name'.\n");
log("\n");
}
- virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool sop_mode = false;
bool wideports = false;
diff --git a/frontends/ilang/.gitignore b/frontends/ilang/.gitignore
index 43106a814..f586b33c7 100644
--- a/frontends/ilang/.gitignore
+++ b/frontends/ilang/.gitignore
@@ -1,4 +1,4 @@
ilang_lexer.cc
ilang_parser.output
ilang_parser.tab.cc
-ilang_parser.tab.h
+ilang_parser.tab.hh
diff --git a/frontends/ilang/Makefile.inc b/frontends/ilang/Makefile.inc
index e2a476c93..6f1f0e8fc 100644
--- a/frontends/ilang/Makefile.inc
+++ b/frontends/ilang/Makefile.inc
@@ -1,15 +1,14 @@
GENFILES += frontends/ilang/ilang_parser.tab.cc
-GENFILES += frontends/ilang/ilang_parser.tab.h
+GENFILES += frontends/ilang/ilang_parser.tab.hh
GENFILES += frontends/ilang/ilang_parser.output
GENFILES += frontends/ilang/ilang_lexer.cc
frontends/ilang/ilang_parser.tab.cc: frontends/ilang/ilang_parser.y
$(Q) mkdir -p $(dir $@)
- $(P) $(BISON) -d -r all -b frontends/ilang/ilang_parser $<
- $(Q) mv frontends/ilang/ilang_parser.tab.c frontends/ilang/ilang_parser.tab.cc
+ $(P) $(BISON) -o $@ -d -r all -b frontends/ilang/ilang_parser $<
-frontends/ilang/ilang_parser.tab.h: frontends/ilang/ilang_parser.tab.cc
+frontends/ilang/ilang_parser.tab.hh: frontends/ilang/ilang_parser.tab.cc
frontends/ilang/ilang_lexer.cc: frontends/ilang/ilang_lexer.l
$(Q) mkdir -p $(dir $@)
diff --git a/frontends/ilang/ilang_frontend.cc b/frontends/ilang/ilang_frontend.cc
index ed6789987..d8783ac1d 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -45,7 +45,7 @@ struct IlangFrontend : public Frontend {
log("representation of a design in yosys's internal format.)\n");
log("\n");
}
- virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ILANG frontend.\n");
extra_args(f, filename, args, 1);
diff --git a/frontends/ilang/ilang_lexer.l b/frontends/ilang/ilang_lexer.l
index 842388548..d8e01ae4d 100644
--- a/frontends/ilang/ilang_lexer.l
+++ b/frontends/ilang/ilang_lexer.l
@@ -30,7 +30,7 @@
#endif
#include "frontends/ilang/ilang_frontend.h"
-#include "ilang_parser.tab.h"
+#include "ilang_parser.tab.hh"
USING_YOSYS_NAMESPACE
diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc
index 629578c61..82361ea9b 100644
--- a/frontends/json/jsonparse.cc
+++ b/frontends/json/jsonparse.cc
@@ -494,7 +494,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
struct JsonFrontend : public Frontend {
JsonFrontend() : Frontend("json", "read JSON file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -504,7 +504,7 @@ struct JsonFrontend : public Frontend {
log("for a description of the file format.\n");
log("\n");
}
- virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing JSON frontend.\n");
diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc
index af80c2921..0a5bd84de 100644
--- a/frontends/liberty/liberty.cc
+++ b/frontends/liberty/liberty.cc
@@ -148,7 +148,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
}
if (0 <= top && stack[top].type == 2) {
- if (next_token.type == '*' || next_token.type == '&' || next_token.type == 0 || next_token.type == '(')
+ if (next_token.type == '*' || next_token.type == '&' || next_token.type == 0 || next_token.type == '(' || next_token.type == '!')
return false;
stack[top].type = 3;
return true;
@@ -188,7 +188,7 @@ static RTLIL::SigSpec parse_func_expr(RTLIL::Module *module, const char *expr)
}
token_t next_token(0);
- if (*expr == '(' || *expr == ')' || *expr == '\'' || *expr == '!' || *expr == '^' || *expr == '*' || *expr == '+' || *expr == '|')
+ if (*expr == '(' || *expr == ')' || *expr == '\'' || *expr == '!' || *expr == '^' || *expr == '*' || *expr == '+' || *expr == '|' || *expr == '&')
next_token = token_t(*(expr++));
else
next_token = token_t(0, parse_func_identifier(module, expr));
@@ -452,7 +452,7 @@ void parse_type_map(std::map<std::string, std::tuple<int, int, bool>> &type_map,
struct LibertyFrontend : public Frontend {
LibertyFrontend() : Frontend("liberty", "read cells from liberty file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -463,9 +463,13 @@ struct LibertyFrontend : public Frontend {
log(" -lib\n");
log(" only create empty blackbox modules\n");
log("\n");
- log(" -ignore_redef\n");
+ log(" -nooverwrite\n");
log(" ignore re-definitions of modules. (the default behavior is to\n");
- log(" create an error message.)\n");
+ log(" create an error message if the existing module is not a blackbox\n");
+ log(" module, and overwrite the existing module if it is a blackbox module.)\n");
+ log("\n");
+ log(" -overwrite\n");
+ log(" overwrite existing modules with the same name\n");
log("\n");
log(" -ignore_miss_func\n");
log(" ignore cells with missing function specification of outputs\n");
@@ -481,10 +485,11 @@ struct LibertyFrontend : public Frontend {
log(" set the specified attribute (to the value 1) on all loaded modules\n");
log("\n");
}
- virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool flag_lib = false;
- bool flag_ignore_redef = false;
+ bool flag_nooverwrite = false;
+ bool flag_overwrite = false;
bool flag_ignore_miss_func = false;
bool flag_ignore_miss_dir = false;
bool flag_ignore_miss_data_latch = false;
@@ -499,8 +504,14 @@ struct LibertyFrontend : public Frontend {
flag_lib = true;
continue;
}
- if (arg == "-ignore_redef") {
- flag_ignore_redef = true;
+ if (arg == "-ignore_redef" || arg == "-nooverwrite") {
+ flag_nooverwrite = true;
+ flag_overwrite = false;
+ continue;
+ }
+ if (arg == "-overwrite") {
+ flag_nooverwrite = false;
+ flag_overwrite = true;
continue;
}
if (arg == "-ignore_miss_func") {
@@ -537,9 +548,16 @@ struct LibertyFrontend : public Frontend {
std::string cell_name = RTLIL::escape_id(cell->args.at(0));
if (design->has(cell_name)) {
- if (flag_ignore_redef)
+ Module *existing_mod = design->module(cell_name);
+ if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
+ log_error("Re-definition of 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;
- log_error("Duplicate definition of cell/module %s.\n", RTLIL::unescape_id(cell_name).c_str());
+ } else {
+ log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "", log_id(cell_name));
+ design->remove(existing_mod);
+ }
}
// log("Processing cell type %s.\n", RTLIL::unescape_id(cell_name).c_str());
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index 7b5dac309..c5fa58313 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -62,7 +62,11 @@ using namespace Verific;
YOSYS_NAMESPACE_BEGIN
int verific_verbose;
+bool verific_import_pending;
string verific_error_msg;
+int verific_sva_fsm_limit;
+
+vector<string> verific_incdirs, verific_libdirs;
void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefile, const char *msg, va_list args)
{
@@ -99,9 +103,9 @@ string get_full_netlist_name(Netlist *nl)
// ==================================================================
-VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific) :
+VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover) :
mode_gates(mode_gates), mode_keep(mode_keep), mode_nosva(mode_nosva),
- mode_names(mode_names), mode_verific(mode_verific)
+ mode_names(mode_names), mode_verific(mode_verific), mode_autocover(mode_autocover)
{
}
@@ -123,8 +127,11 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
attributes["\\src"] = stringf("%s:%d", LineFile::GetFileName(obj->Linefile()), LineFile::GetLineNo(obj->Linefile()));
// FIXME: Parse numeric attributes
- FOREACH_ATTRIBUTE(obj, mi, attr)
+ FOREACH_ATTRIBUTE(obj, mi, attr) {
+ if (attr->Key()[0] == ' ' || attr->Value() == nullptr)
+ continue;
attributes[RTLIL::escape_id(attr->Key())] = RTLIL::Const(std::string(attr->Value()));
+ }
}
RTLIL::SigSpec VerificImporter::operatorInput(Instance *inst)
@@ -186,12 +193,12 @@ RTLIL::SigSpec VerificImporter::operatorInport(Instance *inst, const char *portn
}
}
-RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst)
+RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst, const pool<Net*, hash_ptr_ops> *any_all_nets)
{
RTLIL::SigSpec sig;
RTLIL::Wire *dummy_wire = NULL;
for (int i = int(inst->OutputSize())-1; i >= 0; i--)
- if (inst->GetOutputBit(i)) {
+ if (inst->GetOutputBit(i) && (!any_all_nets || !any_all_nets->count(inst->GetOutputBit(i)))) {
sig.append(net_map_at(inst->GetOutputBit(i)));
dummy_wire = NULL;
} else {
@@ -241,7 +248,9 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
}
if (inst->Type() == PRIM_BUF) {
- module->addBufGate(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ auto outnet = inst->GetOutput();
+ if (!any_all_nets.count(outnet))
+ module->addBufGate(inst_name, net_map_at(inst->GetInput()), net_map_at(outnet));
return true;
}
@@ -391,6 +400,7 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
#define IN1 operatorInput1(inst)
#define IN2 operatorInput2(inst)
#define OUT operatorOutput(inst)
+ #define FILTERED_OUT operatorOutput(inst, &any_all_nets)
#define SIGNED inst->View()->IsSigned()
if (inst->Type() == OPER_ADDER) {
@@ -522,7 +532,7 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
}
if (inst->Type() == OPER_WIDE_BUF) {
- module->addPos(inst_name, IN, OUT, SIGNED);
+ module->addPos(inst_name, IN, FILTERED_OUT, SIGNED);
return true;
}
@@ -786,8 +796,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
module->fixup_ports();
dict<Net*, char, hash_ptr_ops> init_nets;
- pool<Net*, hash_ptr_ops> anyconst_nets;
- pool<Net*, hash_ptr_ops> anyseq_nets;
+ pool<Net*, hash_ptr_ops> anyconst_nets, anyseq_nets;
+ pool<Net*, hash_ptr_ops> allconst_nets, allseq_nets;
+ any_all_nets.clear();
FOREACH_NET_OF_NETLIST(nl, mi, net)
{
@@ -862,11 +873,36 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
const char *rand_const_attr = net->GetAttValue(" rand_const");
const char *rand_attr = net->GetAttValue(" rand");
- if (rand_const_attr != nullptr && !strcmp(rand_const_attr, "1"))
- anyconst_nets.insert(net);
+ const char *anyconst_attr = net->GetAttValue("anyconst");
+ const char *anyseq_attr = net->GetAttValue("anyseq");
+
+ const char *allconst_attr = net->GetAttValue("allconst");
+ const char *allseq_attr = net->GetAttValue("allseq");
- else if (rand_attr != nullptr && !strcmp(rand_attr, "1"))
+ if (rand_const_attr != nullptr && (!strcmp(rand_const_attr, "1") || !strcmp(rand_const_attr, "'1'"))) {
+ anyconst_nets.insert(net);
+ any_all_nets.insert(net);
+ }
+ else if (rand_attr != nullptr && (!strcmp(rand_attr, "1") || !strcmp(rand_attr, "'1'"))) {
+ anyseq_nets.insert(net);
+ any_all_nets.insert(net);
+ }
+ else if (anyconst_attr != nullptr && (!strcmp(anyconst_attr, "1") || !strcmp(anyconst_attr, "'1'"))) {
+ anyconst_nets.insert(net);
+ any_all_nets.insert(net);
+ }
+ else if (anyseq_attr != nullptr && (!strcmp(anyseq_attr, "1") || !strcmp(anyseq_attr, "'1'"))) {
anyseq_nets.insert(net);
+ any_all_nets.insert(net);
+ }
+ else if (allconst_attr != nullptr && (!strcmp(allconst_attr, "1") || !strcmp(allconst_attr, "'1'"))) {
+ allconst_nets.insert(net);
+ any_all_nets.insert(net);
+ }
+ else if (allseq_attr != nullptr && (!strcmp(allseq_attr, "1") || !strcmp(allseq_attr, "'1'"))) {
+ allseq_nets.insert(net);
+ any_all_nets.insert(net);
+ }
if (net_map.count(net)) {
if (verific_verbose)
@@ -951,6 +987,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
SigSpec anyconst_sig;
SigSpec anyseq_sig;
+ SigSpec allconst_sig;
+ SigSpec allseq_sig;
for (int i = netbus->RightIndex();; i += netbus->IsUp() ? -1 : +1) {
net = netbus->ElementAtIndex(i);
@@ -962,6 +1000,14 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
anyseq_sig.append(net_map_at(net));
anyseq_nets.erase(net);
}
+ if (net != nullptr && allconst_nets.count(net)) {
+ allconst_sig.append(net_map_at(net));
+ allconst_nets.erase(net);
+ }
+ if (net != nullptr && allseq_nets.count(net)) {
+ allseq_sig.append(net_map_at(net));
+ allseq_nets.erase(net);
+ }
if (i == netbus->LeftIndex())
break;
}
@@ -971,6 +1017,12 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
if (GetSize(anyseq_sig))
module->connect(anyseq_sig, module->Anyseq(NEW_ID, GetSize(anyseq_sig)));
+
+ if (GetSize(allconst_sig))
+ module->connect(allconst_sig, module->Allconst(NEW_ID, GetSize(allconst_sig)));
+
+ if (GetSize(allseq_sig))
+ module->connect(allseq_sig, module->Allseq(NEW_ID, GetSize(allseq_sig)));
}
for (auto it : init_nets)
@@ -1027,7 +1079,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
}
if (inst->Type() == PRIM_BUF) {
- module->addBufGate(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ auto outnet = inst->GetOutput();
+ if (!any_all_nets.count(outnet))
+ module->addBufGate(inst_name, net_map_at(inst->GetInput()), net_map_at(outnet));
continue;
}
@@ -1044,23 +1098,30 @@ 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()));
- if (memory->width != int(inst->OutputSize()))
- log_error("Import of asymetric memories from Verific is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name());
+ int numchunks = int(inst->OutputSize()) / memory->width;
+ int chunksbits = ceil_log2(numchunks);
- RTLIL::SigSpec addr = operatorInput1(inst);
- RTLIL::SigSpec data = operatorOutput(inst);
+ 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());
- RTLIL::Cell *cell = module->addCell(inst_name, "$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);
+ 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)), "$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;
}
@@ -1068,7 +1129,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
{
RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetOutput()->Name()));
if (memory->width != int(inst->Input2Size()))
- log_error("Import of asymetric memories from Verific is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name());
+ log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name());
RTLIL::SigSpec addr = operatorInput1(inst);
RTLIL::SigSpec data = operatorInput2(inst);
@@ -1214,11 +1275,27 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
continue;
}
- if (inst->IsPrimitive())
+ if (inst->Type() == PRIM_HDL_ASSERTION)
{
- if (inst->Type() == PRIM_HDL_ASSERTION)
- continue;
+ SigBit cond = net_map_at(inst->GetInput());
+
+ if (verific_verbose)
+ log(" assert condition %s.\n", log_signal(cond));
+
+ const char *assume_attr = nullptr; // inst->GetAttValue("assume");
+
+ Cell *cell = nullptr;
+ if (assume_attr != nullptr && !strcmp(assume_attr, "1"))
+ cell = module->addAssume(NEW_ID, cond, State::S1);
+ else
+ cell = module->addAssert(NEW_ID, cond, State::S1);
+
+ import_attributes(cell->attributes, inst);
+ continue;
+ }
+ if (inst->IsPrimitive())
+ {
if (!mode_keep)
log_error("Unsupported Verific primitive %s of type %s\n", inst->Name(), inst->View()->Owner()->Name());
@@ -1272,8 +1349,11 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
if (!mode_nosva)
{
- for (auto inst : sva_asserts)
+ for (auto inst : sva_asserts) {
+ if (mode_autocover)
+ verific_import_sva_cover(this, inst);
verific_import_sva_assert(this, inst);
+ }
for (auto inst : sva_assumes)
verific_import_sva_assume(this, inst);
@@ -1290,7 +1370,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
// ==================================================================
-VerificClocking::VerificClocking(VerificImporter *importer, Net *net)
+VerificClocking::VerificClocking(VerificImporter *importer, Net *net, bool sva_at_only)
{
module = importer->module;
@@ -1313,8 +1393,14 @@ VerificClocking::VerificClocking(VerificImporter *importer, Net *net)
body_net = body_inst->GetInput2();
}
}
+ else
+ {
+ if (sva_at_only)
+ return;
+ }
- if (inst != nullptr && inst->Type() == PRIM_SVA_POSEDGE)
+ // Use while() instead of if() to work around VIPER #13453
+ while (inst != nullptr && inst->Type() == PRIM_SVA_POSEDGE)
{
net = inst->GetInput();
inst = net->Driver();;
@@ -1388,6 +1474,10 @@ VerificClocking::VerificClocking(VerificImporter *importer, Net *net)
clock_net = net;
clock_sig = importer->net_map_at(clock_net);
+
+ const char *gclk_attr = clock_net->GetAttValue("gclk");
+ if (gclk_attr != nullptr && (!strcmp(gclk_attr, "1") || !strcmp(gclk_attr, "'1'")))
+ gclk = true;
}
Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const init_value)
@@ -1410,15 +1500,20 @@ Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const
sig_d = module->Mux(NEW_ID, sig_q, sig_d, enable_sig);
if (disable_sig != State::S0) {
+ log_assert(gclk == false);
log_assert(GetSize(sig_q) == GetSize(init_value));
return module->addAdff(name, clock_sig, disable_sig, sig_d, sig_q, init_value, posedge);
}
+ if (gclk)
+ return module->addFf(name, sig_d, sig_q);
+
return module->addDff(name, clock_sig, sig_d, sig_q, posedge);
}
Cell *VerificClocking::addAdff(IdString name, RTLIL::SigSpec sig_arst, SigSpec sig_d, SigSpec sig_q, Const arst_value)
{
+ log_assert(gclk == false);
log_assert(disable_sig == State::S0);
if (enable_sig != State::S1)
@@ -1429,6 +1524,7 @@ Cell *VerificClocking::addAdff(IdString name, RTLIL::SigSpec sig_arst, SigSpec s
Cell *VerificClocking::addDffsr(IdString name, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, SigSpec sig_d, SigSpec sig_q)
{
+ log_assert(gclk == false);
log_assert(disable_sig == State::S0);
if (enable_sig != State::S1)
@@ -1521,14 +1617,78 @@ struct VerificExtNets
}
};
+void verific_import(Design *design, std::string top)
+{
+ verific_sva_fsm_limit = 16;
+
+ std::set<Netlist*> nl_todo, nl_done;
+
+ {
+ VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1);
+ VeriLibrary *veri_lib = veri_file::GetLibrary("work", 1);
+
+ Array veri_libs, vhdl_libs;
+ if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
+ if (veri_lib) veri_libs.InsertLast(veri_lib);
+
+ Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs);
+ Netlist *nl;
+ int i;
+
+ FOREACH_ARRAY_ITEM(netlists, i, nl) {
+ if (top.empty() || nl->Owner()->Name() == top)
+ nl_todo.insert(nl);
+ }
+
+ delete netlists;
+ }
+
+ if (!verific_error_msg.empty())
+ log_error("%s\n", verific_error_msg.c_str());
+
+ VerificExtNets worker;
+ for (auto nl : nl_todo)
+ worker.run(nl);
+
+ while (!nl_todo.empty()) {
+ Netlist *nl = *nl_todo.begin();
+ if (nl_done.count(nl) == 0) {
+ VerificImporter importer(false, false, false, false, false, false);
+ importer.import_netlist(design, nl, nl_todo);
+ }
+ nl_todo.erase(nl);
+ nl_done.insert(nl);
+ }
+
+ veri_file::Reset();
+ vhdl_file::Reset();
+ Libset::Reset();
+ verific_incdirs.clear();
+ verific_libdirs.clear();
+ verific_import_pending = false;
+
+ if (!verific_error_msg.empty())
+ log_error("%s\n", verific_error_msg.c_str());
+}
+
YOSYS_NAMESPACE_END
#endif /* YOSYS_ENABLE_VERIFIC */
PRIVATE_NAMESPACE_BEGIN
+bool check_noverific_env()
+{
+ const char *e = getenv("YOSYS_NOVERIFIC");
+ if (e == nullptr)
+ return false;
+ if (atoi(e) == 0)
+ return false;
+ return true;
+}
+
struct VerificPass : public Pass {
VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1536,12 +1696,31 @@ struct VerificPass : public Pass {
log("\n");
log("Load the specified Verilog/SystemVerilog files into Verific.\n");
log("\n");
+ log("All files specified in one call to this command are one compilation unit.\n");
+ log("Files passed to different calls to this command are treated as belonging to\n");
+ log("different compilation units.\n");
+ log("\n");
+ log("Additional -D<macro>[=<value>] options may be added after the option indicating\n");
+ log("the language version (and before file names) to set additional verilog defines.\n");
+ log("The macros SYNTHESIS and VERIFIC are defined implicitly.\n");
+ log("\n");
+ log("\n");
+ log(" verific -formal <verilog-file>..\n");
+ log("\n");
+ log("Like -sv, but define FORMAL instead of SYNTHESIS.\n");
+ log("\n");
log("\n");
log(" verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
log("\n");
log("Load the specified VHDL files into Verific.\n");
log("\n");
log("\n");
+ log(" verific -work <libname> {-sv|-vhdl|...} <hdl-file>\n");
+ log("\n");
+ log("Load the specified Verilog/SystemVerilog/VHDL file into the specified library.\n");
+ log("(default library when -work is not present: \"work\")\n");
+ log("\n");
+ log("\n");
log(" verific -vlog-incdir <directory>..\n");
log("\n");
log("Add Verilog include directories.\n");
@@ -1555,7 +1734,21 @@ struct VerificPass : public Pass {
log("\n");
log(" verific -vlog-define <macro>[=<value>]..\n");
log("\n");
- log("Add Verilog defines. (The macros SYNTHESIS and VERIFIC are defined implicitly.)\n");
+ log("Add Verilog defines.\n");
+ log("\n");
+ log("\n");
+ log(" verific -vlog-undef <macro>..\n");
+ log("\n");
+ log("Remove Verilog defines previously set with -vlog-define.\n");
+ log("\n");
+ log("\n");
+ log(" verific -set-error <msg_id>..\n");
+ log(" verific -set-warning <msg_id>..\n");
+ log(" verific -set-info <msg_id>..\n");
+ log(" verific -set-ignore <msg_id>..\n");
+ log("\n");
+ log("Set message severity. <msg_id> is the string in square brackets when a message\n");
+ log("is printed, such as VERI-1209.\n");
log("\n");
log("\n");
log(" verific -import [options] <top-module>..\n");
@@ -1578,6 +1771,9 @@ struct VerificPass : public Pass {
log(" -extnets\n");
log(" Resolve references to external nets by adding module ports as needed.\n");
log("\n");
+ log(" -autocover\n");
+ log(" Generate automatic cover statements for all asserts\n");
+ log("\n");
log(" -v, -vv\n");
log(" Verbose log messages. (-vv is even more verbose than -v.)\n");
log("\n");
@@ -1596,6 +1792,9 @@ struct VerificPass : public Pass {
log(" -nosva\n");
log(" Ignore SVA properties, do not infer checker logic.\n");
log("\n");
+ log(" -L <int>\n");
+ log(" Maximum number of ctrl bits for SVA checker FSMs (default=16).\n");
+ log("\n");
log(" -n\n");
log(" Keep all Verific names on instances and nets. By default only\n");
log(" user-declared names are preserved.\n");
@@ -1607,19 +1806,37 @@ struct VerificPass : public Pass {
log("\n");
}
#ifdef YOSYS_ENABLE_VERIFIC
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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");
+
log_header(design, "Executing VERIFIC (loading SystemVerilog and VHDL designs using Verific).\n");
- Message::SetConsoleOutput(0);
- Message::RegisterCallBackMsg(msg_func);
- RuntimeFlags::SetVar("db_preserve_user_nets", 1);
- RuntimeFlags::SetVar("db_allow_external_nets", 1);
- RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0);
- veri_file::DefineCmdLineMacro("VERIFIC");
- veri_file::DefineCmdLineMacro("SYNTHESIS");
+ if (set_verific_global_flags)
+ {
+ Message::SetConsoleOutput(0);
+ Message::RegisterCallBackMsg(msg_func);
+ RuntimeFlags::SetVar("db_preserve_user_nets", 1);
+ RuntimeFlags::SetVar("db_allow_external_nets", 1);
+ RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0);
+ RuntimeFlags::SetVar("veri_extract_dualport_rams", 0);
+ RuntimeFlags::SetVar("veri_extract_multiport_rams", 1);
+ RuntimeFlags::SetVar("db_infer_wide_operators", 1);
+
+ // Workaround for VIPER #13851
+ RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1);
+
+ // WARNING: instantiating unknown module 'XYZ' (VERI-1063)
+ Message::SetMessageType("VERI-1063", VERIFIC_ERROR);
+
+ set_verific_global_flags = false;
+ }
verific_verbose = 0;
+ verific_sva_fsm_limit = 16;
const char *release_str = Message::ReleaseString();
time_t release_time = Message::ReleaseDate();
@@ -1634,16 +1851,39 @@ struct VerificPass : public Pass {
log("Built with Verific %s, released at %s.\n", release_str, release_tmstr);
int argidx = 1;
+ std::string work = "work";
+
+ if (GetSize(args) > argidx && (args[argidx] == "-set-error" || args[argidx] == "-set-warning" ||
+ args[argidx] == "-set-info" || args[argidx] == "-set-ignore"))
+ {
+ msg_type_t new_type;
+
+ if (args[argidx] == "-set-error")
+ new_type = VERIFIC_ERROR;
+ else if (args[argidx] == "-set-warning")
+ new_type = VERIFIC_WARNING;
+ else if (args[argidx] == "-set-info")
+ new_type = VERIFIC_INFO;
+ else if (args[argidx] == "-set-ignore")
+ new_type = VERIFIC_IGNORE;
+ else
+ log_abort();
+
+ for (argidx++; argidx < GetSize(args); argidx++)
+ Message::SetMessageType(args[argidx].c_str(), new_type);
+
+ goto check_error;
+ }
if (GetSize(args) > argidx && args[argidx] == "-vlog-incdir") {
for (argidx++; argidx < GetSize(args); argidx++)
- veri_file::AddIncludeDir(args[argidx].c_str());
+ verific_incdirs.push_back(args[argidx]);
goto check_error;
}
if (GetSize(args) > argidx && args[argidx] == "-vlog-libdir") {
for (argidx++; argidx < GetSize(args); argidx++)
- veri_file::AddYDir(args[argidx].c_str());
+ verific_libdirs.push_back(args[argidx]);
goto check_error;
}
@@ -1662,70 +1902,110 @@ struct VerificPass : public Pass {
goto check_error;
}
- if (GetSize(args) > argidx && args[argidx] == "-vlog95") {
- for (argidx++; argidx < GetSize(args); argidx++)
- if (!veri_file::Analyze(args[argidx].c_str(), veri_file::VERILOG_95))
- log_cmd_error("Reading `%s' in VERILOG_95 mode failed.\n", args[argidx].c_str());
+ if (GetSize(args) > argidx && args[argidx] == "-vlog-undef") {
+ for (argidx++; argidx < GetSize(args); argidx++) {
+ string name = args[argidx];
+ veri_file::UndefineMacro(name.c_str());
+ }
goto check_error;
}
- if (GetSize(args) > argidx && args[argidx] == "-vlog2k") {
- for (argidx++; argidx < GetSize(args); argidx++)
- if (!veri_file::Analyze(args[argidx].c_str(), veri_file::VERILOG_2K))
- log_cmd_error("Reading `%s' in VERILOG_2K mode failed.\n", args[argidx].c_str());
- goto check_error;
+ for (; argidx < GetSize(args); argidx++)
+ {
+ if (args[argidx] == "-work" && argidx+1 < GetSize(args)) {
+ work = args[++argidx];
+ continue;
+ }
+ break;
}
- if (GetSize(args) > argidx && args[argidx] == "-sv2005") {
- for (argidx++; argidx < GetSize(args); argidx++)
- if (!veri_file::Analyze(args[argidx].c_str(), veri_file::SYSTEM_VERILOG_2005))
- log_cmd_error("Reading `%s' in SYSTEM_VERILOG_2005 mode failed.\n", args[argidx].c_str());
- goto check_error;
- }
+ if (GetSize(args) > argidx && (args[argidx] == "-vlog95" || args[argidx] == "-vlog2k" || args[argidx] == "-sv2005" ||
+ args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal"))
+ {
+ Array file_names;
+ unsigned verilog_mode;
+
+ if (args[argidx] == "-vlog95")
+ verilog_mode = veri_file::VERILOG_95;
+ else if (args[argidx] == "-vlog2k")
+ verilog_mode = veri_file::VERILOG_2K;
+ else if (args[argidx] == "-sv2005")
+ verilog_mode = veri_file::SYSTEM_VERILOG_2005;
+ else if (args[argidx] == "-sv2009")
+ verilog_mode = veri_file::SYSTEM_VERILOG_2009;
+ else if (args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal")
+ verilog_mode = veri_file::SYSTEM_VERILOG;
+ else
+ log_abort();
- if (GetSize(args) > argidx && args[argidx] == "-sv2009") {
- for (argidx++; argidx < GetSize(args); argidx++)
- if (!veri_file::Analyze(args[argidx].c_str(), veri_file::SYSTEM_VERILOG_2009))
- log_cmd_error("Reading `%s' in SYSTEM_VERILOG_2009 mode failed.\n", args[argidx].c_str());
- goto check_error;
- }
+ veri_file::DefineMacro("VERIFIC");
+ veri_file::DefineMacro(args[argidx] == "-formal" ? "FORMAL" : "SYNTHESIS");
- if (GetSize(args) > argidx && (args[argidx] == "-sv2012" || args[argidx] == "-sv")) {
- for (argidx++; argidx < GetSize(args); argidx++)
- if (!veri_file::Analyze(args[argidx].c_str(), veri_file::SYSTEM_VERILOG))
- log_cmd_error("Reading `%s' in SYSTEM_VERILOG mode failed.\n", args[argidx].c_str());
+ for (argidx++; argidx < GetSize(args) && GetSize(args[argidx]) >= 2 && args[argidx].substr(0, 2) == "-D"; argidx++) {
+ std::string name = args[argidx].substr(2);
+ if (args[argidx] == "-D") {
+ if (++argidx >= GetSize(args))
+ break;
+ name = args[argidx];
+ }
+ size_t equal = name.find('=');
+ if (equal != std::string::npos) {
+ string value = name.substr(equal+1);
+ name = name.substr(0, equal);
+ veri_file::DefineMacro(name.c_str(), value.c_str());
+ } else {
+ veri_file::DefineMacro(name.c_str());
+ }
+ }
+
+ for (auto &dir : verific_incdirs)
+ veri_file::AddIncludeDir(dir.c_str());
+ for (auto &dir : verific_libdirs)
+ veri_file::AddYDir(dir.c_str());
+
+ while (argidx < GetSize(args))
+ file_names.Insert(args[argidx++].c_str());
+
+ if (!veri_file::AnalyzeMultipleFiles(&file_names, verilog_mode, work.c_str(), veri_file::MFCU))
+ log_cmd_error("Reading Verilog/SystemVerilog sources failed.\n");
+
+ verific_import_pending = true;
goto check_error;
}
if (GetSize(args) > argidx && args[argidx] == "-vhdl87") {
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1987").c_str());
for (argidx++; argidx < GetSize(args); argidx++)
- if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_87))
+ if (!vhdl_file::Analyze(args[argidx].c_str(), work.c_str(), vhdl_file::VHDL_87))
log_cmd_error("Reading `%s' in VHDL_87 mode failed.\n", args[argidx].c_str());
+ verific_import_pending = true;
goto check_error;
}
if (GetSize(args) > argidx && args[argidx] == "-vhdl93") {
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1993").c_str());
for (argidx++; argidx < GetSize(args); argidx++)
- if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_93))
+ if (!vhdl_file::Analyze(args[argidx].c_str(), work.c_str(), vhdl_file::VHDL_93))
log_cmd_error("Reading `%s' in VHDL_93 mode failed.\n", args[argidx].c_str());
+ verific_import_pending = true;
goto check_error;
}
if (GetSize(args) > argidx && args[argidx] == "-vhdl2k") {
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1993").c_str());
for (argidx++; argidx < GetSize(args); argidx++)
- if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_2K))
+ if (!vhdl_file::Analyze(args[argidx].c_str(), work.c_str(), vhdl_file::VHDL_2K))
log_cmd_error("Reading `%s' in VHDL_2K mode failed.\n", args[argidx].c_str());
+ verific_import_pending = true;
goto check_error;
}
if (GetSize(args) > argidx && (args[argidx] == "-vhdl2008" || args[argidx] == "-vhdl")) {
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_2008").c_str());
for (argidx++; argidx < GetSize(args); argidx++)
- if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_2008))
+ if (!vhdl_file::Analyze(args[argidx].c_str(), work.c_str(), vhdl_file::VHDL_2008))
log_cmd_error("Reading `%s' in VHDL_2008 mode failed.\n", args[argidx].c_str());
+ verific_import_pending = true;
goto check_error;
}
@@ -1734,6 +2014,7 @@ struct VerificPass : public Pass {
std::set<Netlist*> nl_todo, nl_done;
bool mode_all = false, mode_gates = false, mode_keep = false;
bool mode_nosva = false, mode_names = false, mode_verific = false;
+ bool mode_autocover = false;
bool flatten = false, extnets = false;
string dumpfile;
@@ -1762,10 +2043,18 @@ struct VerificPass : public Pass {
mode_nosva = true;
continue;
}
+ if (args[argidx] == "-L" && argidx+1 < GetSize(args)) {
+ verific_sva_fsm_limit = atoi(args[++argidx].c_str());
+ continue;
+ }
if (args[argidx] == "-n") {
mode_names = true;
continue;
}
+ if (args[argidx] == "-autocover") {
+ mode_autocover = true;
+ continue;
+ }
if (args[argidx] == "-V") {
mode_verific = true;
continue;
@@ -1828,8 +2117,8 @@ struct VerificPass : public Pass {
#else
log("Running hier_tree::ElaborateAll().\n");
- VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1);
- VeriLibrary *veri_lib = veri_file::GetLibrary("work", 1);
+ VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
+ VeriLibrary *veri_lib = veri_file::GetLibrary(work.c_str(), 1);
Array veri_libs, vhdl_libs;
if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
@@ -1876,7 +2165,7 @@ struct VerificPass : public Pass {
continue;
}
- VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1);
+ VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
VhdlDesignUnit *vhdl_unit = vhdl_lib->GetPrimUnit(name);
if (vhdl_unit) {
log("Adding VHDL unit '%s' to elaboration queue.\n", name);
@@ -1898,6 +2187,9 @@ struct VerificPass : public Pass {
#endif
}
+ if (!verific_error_msg.empty())
+ goto check_error;
+
if (flatten) {
for (auto nl : nl_todo)
nl->Flatten();
@@ -1918,7 +2210,7 @@ struct VerificPass : public Pass {
Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0) {
VerificImporter importer(mode_gates, mode_keep, mode_nosva,
- mode_names, mode_verific);
+ mode_names, mode_verific, mode_autocover);
importer.import_netlist(design, nl, nl_todo);
}
nl_todo.erase(nl);
@@ -1928,6 +2220,9 @@ struct VerificPass : public Pass {
veri_file::Reset();
vhdl_file::Reset();
Libset::Reset();
+ verific_incdirs.clear();
+ verific_libdirs.clear();
+ verific_import_pending = false;
goto check_error;
}
@@ -1939,11 +2234,139 @@ struct VerificPass : public Pass {
}
#else /* YOSYS_ENABLE_VERIFIC */
- virtual void execute(std::vector<std::string>, RTLIL::Design *) {
+ void execute(std::vector<std::string>, RTLIL::Design *) YS_OVERRIDE {
log_cmd_error("This version of Yosys is built without Verific support.\n");
}
#endif
} VerificPass;
-PRIVATE_NAMESPACE_END
+struct ReadPass : public Pass {
+ ReadPass() : Pass("read", "load HDL designs") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" read {-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv|-formal} <verilog-file>..\n");
+ log("\n");
+ log("Load the specified Verilog/SystemVerilog files. (Full SystemVerilog support\n");
+ log("is only available via Verific.)\n");
+ log("\n");
+ log("Additional -D<macro>[=<value>] options may be added after the option indicating\n");
+ log("the language version (and before file names) to set additional verilog defines.\n");
+ log("\n");
+ log("\n");
+ log(" read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
+ log("\n");
+ log("Load the specified VHDL files. (Requires Verific.)\n");
+ log("\n");
+ log("\n");
+ log(" read -define <macro>[=<value>]..\n");
+ log("\n");
+ log("Set global Verilog/SystemVerilog defines.\n");
+ log("\n");
+ log("\n");
+ log(" read -undef <macro>..\n");
+ log("\n");
+ log("Unset global Verilog/SystemVerilog defines.\n");
+ log("\n");
+ log("\n");
+ log(" read -incdir <directory>\n");
+ log("\n");
+ log("Add directory to global Verilog/SystemVerilog include directories.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ if (args.size() < 2)
+ log_cmd_error("Missing mode parameter.\n");
+
+ if (args.size() < 3)
+ log_cmd_error("Missing file name parameter.\n");
+
+#ifdef YOSYS_ENABLE_VERIFIC
+ bool use_verific = !check_noverific_env();
+#else
+ bool use_verific = false;
+#endif
+ if (args[1] == "-vlog95" || args[1] == "-vlog2k") {
+ if (use_verific) {
+ args[0] = "verific";
+ } else {
+ args[0] = "read_verilog";
+ args.erase(args.begin()+1, args.begin()+2);
+ }
+ Pass::call(design, args);
+ return;
+ }
+
+ if (args[1] == "-sv2005" || args[1] == "-sv2009" || args[1] == "-sv2012" || args[1] == "-sv" || args[1] == "-formal") {
+ if (use_verific) {
+ args[0] = "verific";
+ } else {
+ args[0] = "read_verilog";
+ if (args[1] == "-formal")
+ args.insert(args.begin()+1, std::string());
+ args[1] = "-sv";
+ }
+ Pass::call(design, args);
+ return;
+ }
+
+ if (args[1] == "-vhdl87" || args[1] == "-vhdl93" || args[1] == "-vhdl2k" || args[1] == "-vhdl2008" || args[1] == "-vhdl") {
+ if (use_verific) {
+ args[0] = "verific";
+ Pass::call(design, args);
+ } else {
+ log_cmd_error("This version of Yosys is built without Verific support.\n");
+ }
+ return;
+ }
+
+ if (args[1] == "-define") {
+ if (use_verific) {
+ args[0] = "verific";
+ args[1] = "-vlog-define";
+ Pass::call(design, args);
+ }
+ args[0] = "verilog_defines";
+ args.erase(args.begin()+1, args.begin()+2);
+ for (int i = 1; i < GetSize(args); i++)
+ args[i] = "-D" + args[i];
+ Pass::call(design, args);
+ return;
+ }
+
+ if (args[1] == "-undef") {
+ if (use_verific) {
+ args[0] = "verific";
+ args[1] = "-vlog-undef";
+ Pass::call(design, args);
+ }
+ args[0] = "verilog_defines";
+ args.erase(args.begin()+1, args.begin()+2);
+ for (int i = 1; i < GetSize(args); i++)
+ args[i] = "-U" + args[i];
+ Pass::call(design, args);
+ return;
+ }
+
+ if (args[1] == "-incdir") {
+ if (use_verific) {
+ args[0] = "verific";
+ args[1] = "-vlog-incdir";
+ Pass::call(design, args);
+ }
+ args[0] = "verilog_defaults";
+ args[1] = "-add";
+ for (int i = 2; i < GetSize(args); i++)
+ args[i] = "-I" + args[i];
+ Pass::call(design, args);
+ return;
+ }
+
+ log_cmd_error("Missing or unsupported mode parameter.\n");
+ }
+} ReadPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h
index 877d79057..334a436af 100644
--- a/frontends/verific/verific.h
+++ b/frontends/verific/verific.h
@@ -25,6 +25,9 @@ YOSYS_NAMESPACE_BEGIN
extern int verific_verbose;
+extern bool verific_import_pending;
+extern void verific_import(Design *design, std::string top = std::string());
+
extern pool<int> verific_sva_prims;
struct VerificImporter;
@@ -40,9 +43,10 @@ struct VerificClocking {
SigBit enable_sig = State::S1;
SigBit disable_sig = State::S0;
bool posedge = true;
+ bool gclk = false;
VerificClocking() { }
- VerificClocking(VerificImporter *importer, Verific::Net *net);
+ VerificClocking(VerificImporter *importer, Verific::Net *net, bool sva_at_only = false);
RTLIL::Cell *addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const init_value = Const());
RTLIL::Cell *addAdff(IdString name, RTLIL::SigSpec sig_arst, SigSpec sig_d, SigSpec sig_q, Const arst_value);
RTLIL::Cell *addDffsr(IdString name, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, SigSpec sig_d, SigSpec sig_q);
@@ -65,10 +69,12 @@ struct VerificImporter
std::map<Verific::Net*, RTLIL::SigBit> net_map;
std::map<Verific::Net*, Verific::Net*> sva_posedge_map;
+ pool<Verific::Net*, hash_ptr_ops> any_all_nets;
bool mode_gates, mode_keep, mode_nosva, mode_names, mode_verific;
+ bool mode_autocover;
- VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific);
+ VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover);
RTLIL::SigBit net_map_at(Verific::Net *net);
@@ -78,7 +84,7 @@ struct VerificImporter
RTLIL::SigSpec operatorInput1(Verific::Instance *inst);
RTLIL::SigSpec operatorInput2(Verific::Instance *inst);
RTLIL::SigSpec operatorInport(Verific::Instance *inst, const char *portname);
- RTLIL::SigSpec operatorOutput(Verific::Instance *inst);
+ RTLIL::SigSpec operatorOutput(Verific::Instance *inst, const pool<Verific::Net*, hash_ptr_ops> *any_all_nets = nullptr);
bool import_netlist_instance_gates(Verific::Instance *inst, RTLIL::IdString inst_name);
bool import_netlist_instance_cells(Verific::Instance *inst, RTLIL::IdString inst_name);
@@ -95,6 +101,8 @@ void verific_import_sva_cover(VerificImporter *importer, Verific::Instance *inst
void verific_import_sva_trigger(VerificImporter *importer, Verific::Instance *inst);
bool verific_is_sva_net(VerificImporter *importer, Verific::Net *net);
+extern int verific_sva_fsm_limit;
+
YOSYS_NAMESPACE_END
#endif
diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc
index 5abe0eb35..cdc9ece8c 100644
--- a/frontends/verific/verificsva.cc
+++ b/frontends/verific/verificsva.cc
@@ -21,14 +21,52 @@
// Currently supported SVA sequence and property syntax:
// http://symbiyosys.readthedocs.io/en/latest/verific.html
//
-// Todos:
-// property and property
-// sequence |-> always sequence
-// sequence |-> eventually sequence
-// sequence implies sequence
-// sequence iff sequence
-// accept_on (expr) prop
-// reject_on (expr) prop
+// Next gen property syntax:
+// basic_property
+// [antecedent_condition] property
+// [antecedent_condition] always.. property
+// [antecedent_condition] eventually.. basic_property
+// [antecedent_condition] property until.. expression
+// [antecedent_condition] basic_property until.. basic_property (assert/assume only)
+//
+// antecedent_condition:
+// sequence |->
+// sequence |=>
+//
+// basic_property:
+// sequence
+// not basic_property
+// sequence #-# basic_property
+// sequence #=# basic_property
+// basic_property or basic_property (cover only)
+// basic_property and basic_property (assert/assume only)
+// basic_property implies basic_property
+// basic_property iff basic_property
+//
+// sequence:
+// expression
+// sequence ##N sequence
+// sequence ##[*] sequence
+// sequence ##[+] sequence
+// sequence ##[N:M] sequence
+// sequence ##[N:$] sequence
+// expression [*]
+// expression [+]
+// expression [*N]
+// expression [*N:M]
+// expression [*N:$]
+// sequence or sequence
+// sequence and sequence
+// expression throughout sequence
+// sequence intersect sequence
+// sequence within sequence
+// first_match( sequence )
+// expression [=N]
+// expression [=N:M]
+// expression [=N:$]
+// expression [->N]
+// expression [->N:M]
+// expression [->N:$]
#include "kernel/yosys.h"
@@ -428,13 +466,14 @@ struct SvaFsm
dnode.ctrl.sort_and_unify();
- if (GetSize(dnode.ctrl) > 16) {
+ if (GetSize(dnode.ctrl) > verific_sva_fsm_limit) {
if (verific_verbose >= 2) {
log(" detected state explosion in DFSM generation:\n");
dump();
log(" ctrl signal: %s\n", log_signal(dnode.ctrl));
}
- log_error("SVA DFSM state ctrl signal has %d (>16) bits. Stopping to prevent exponential design size explosion.\n", GetSize(dnode.ctrl));
+ log_error("SVA DFSM state ctrl signal has %d (>%d) bits. Stopping to prevent exponential design size explosion.\n",
+ GetSize(dnode.ctrl), verific_sva_fsm_limit);
}
for (int i = 0; i < (1 << GetSize(dnode.ctrl)); i++)
@@ -942,7 +981,6 @@ struct VerificSvaImporter
bool mode_assume = false;
bool mode_cover = false;
bool mode_trigger = false;
- bool eventually = false;
Instance *net_to_ast_driver(Net *n)
{
@@ -1100,6 +1138,97 @@ struct VerificSvaImporter
log_abort();
}
+ bool check_zero_consecutive_repeat(Net *net)
+ {
+ Instance *inst = net_to_ast_driver(net);
+
+ if (inst == nullptr)
+ return false;
+
+ if (inst->Type() != PRIM_SVA_CONSECUTIVE_REPEAT)
+ return false;
+
+ const char *sva_low_s = inst->GetAttValue("sva:low");
+ int sva_low = atoi(sva_low_s);
+
+ return sva_low == 0;
+ }
+
+ int parse_consecutive_repeat(SvaFsm &fsm, int start_node, Net *net, bool add_pre_delay, bool add_post_delay)
+ {
+ Instance *inst = net_to_ast_driver(net);
+
+ log_assert(inst->Type() == PRIM_SVA_CONSECUTIVE_REPEAT);
+
+ const char *sva_low_s = inst->GetAttValue("sva:low");
+ const char *sva_high_s = inst->GetAttValue("sva:high");
+
+ int sva_low = atoi(sva_low_s);
+ int sva_high = atoi(sva_high_s);
+ bool sva_inf = !strcmp(sva_high_s, "$");
+
+ Net *body_net = inst->GetInput();
+
+ if (add_pre_delay || add_post_delay)
+ log_assert(sva_low == 0);
+
+ if (sva_low == 0) {
+ if (!add_pre_delay && !add_post_delay)
+ parser_error("Possibly zero-length consecutive repeat must follow or precede a delay of at least one cycle", inst);
+ sva_low++;
+ }
+
+ int node = fsm.createNode(start_node);
+ start_node = node;
+
+ if (add_pre_delay) {
+ node = fsm.createNode(start_node);
+ fsm.createEdge(start_node, node);
+ }
+
+ int prev_node = node;
+ node = parse_sequence(fsm, node, body_net);
+
+ for (int i = 1; i < sva_low; i++)
+ {
+ int next_node = fsm.createNode();
+ fsm.createEdge(node, next_node);
+
+ prev_node = node;
+ node = parse_sequence(fsm, next_node, body_net);
+ }
+
+ if (sva_inf)
+ {
+ log_assert(prev_node >= 0);
+ fsm.createEdge(node, prev_node);
+ }
+ else
+ {
+ for (int i = sva_low; i < sva_high; i++)
+ {
+ int next_node = fsm.createNode();
+ fsm.createEdge(node, next_node);
+
+ prev_node = node;
+ node = parse_sequence(fsm, next_node, body_net);
+
+ fsm.createLink(prev_node, node);
+ }
+ }
+
+ if (add_post_delay) {
+ int next_node = fsm.createNode();
+ fsm.createEdge(node, next_node);
+ node = next_node;
+ }
+
+ if (add_pre_delay || add_post_delay)
+ fsm.createLink(start_node, node);
+
+ return node;
+ }
+
int parse_sequence(SvaFsm &fsm, int start_node, Net *net)
{
if (check_expression(net)) {
@@ -1144,7 +1273,20 @@ struct VerificSvaImporter
int sva_high = atoi(sva_high_s);
bool sva_inf = !strcmp(sva_high_s, "$");
- int node = parse_sequence(fsm, start_node, inst->GetInput1());
+ int node = -1;
+ bool past_add_delay = false;
+
+ if (check_zero_consecutive_repeat(inst->GetInput1()) && sva_low > 0) {
+ node = parse_consecutive_repeat(fsm, start_node, inst->GetInput1(), false, true);
+ sva_low--, sva_high--;
+ } else {
+ node = parse_sequence(fsm, start_node, inst->GetInput1());
+ }
+
+ if (check_zero_consecutive_repeat(inst->GetInput2()) && sva_low > 0) {
+ past_add_delay = true;
+ sva_low--, sva_high--;
+ }
for (int i = 0; i < sva_low; i++) {
int next_node = fsm.createNode();
@@ -1167,62 +1309,17 @@ struct VerificSvaImporter
}
}
- node = parse_sequence(fsm, node, inst->GetInput2());
+ if (past_add_delay)
+ node = parse_consecutive_repeat(fsm, node, inst->GetInput2(), true, false);
+ else
+ node = parse_sequence(fsm, node, inst->GetInput2());
return node;
}
if (inst->Type() == PRIM_SVA_CONSECUTIVE_REPEAT)
{
- const char *sva_low_s = inst->GetAttValue("sva:low");
- const char *sva_high_s = inst->GetAttValue("sva:high");
-
- int sva_low = atoi(sva_low_s);
- int sva_high = atoi(sva_high_s);
- bool sva_inf = !strcmp(sva_high_s, "$");
-
- Net *body_net = inst->GetInput();
- int node = fsm.createNode(start_node);
-
- for (int i = 0; i < sva_low; i++)
- {
- int next_node = fsm.createNode();
-
- if (i == 0)
- fsm.createLink(node, next_node);
- else
- fsm.createEdge(node, next_node);
-
- node = parse_sequence(fsm, next_node, body_net);
- }
-
- if (sva_inf)
- {
- int next_node = fsm.createNode();
- fsm.createEdge(node, next_node);
-
- next_node = parse_sequence(fsm, next_node, body_net);
- fsm.createLink(next_node, node);
- }
- else
- {
- for (int i = sva_low; i < sva_high; i++)
- {
- int next_node = fsm.createNode();
-
- if (i == 0)
- fsm.createLink(node, next_node);
- else
- fsm.createEdge(node, next_node);
-
- next_node = parse_sequence(fsm, next_node, body_net);
-
- fsm.createLink(node, next_node);
- node = next_node;
- }
- }
-
- return node;
+ return parse_consecutive_repeat(fsm, start_node, net, false, false);
}
if (inst->Type() == PRIM_SVA_NON_CONSECUTIVE_REPEAT || inst->Type() == PRIM_SVA_GOTO_REPEAT)
@@ -1390,6 +1487,72 @@ struct VerificSvaImporter
fsm.getFirstAcceptReject(accept_p, reject_p);
}
+ bool eventually_property(Net *&net, SigBit &trig)
+ {
+ Instance *inst = net_to_ast_driver(net);
+
+ if (inst == nullptr)
+ return false;
+
+ if (clocking.cond_net != nullptr)
+ trig = importer->net_map_at(clocking.cond_net);
+ else
+ trig = State::S1;
+
+ if (inst->Type() == PRIM_SVA_S_EVENTUALLY || inst->Type() == PRIM_SVA_EVENTUALLY)
+ {
+ if (mode_cover || mode_trigger)
+ parser_error(inst);
+
+ net = inst->GetInput();
+ clocking.cond_net = nullptr;
+
+ return true;
+ }
+
+ if (inst->Type() == PRIM_SVA_OVERLAPPED_IMPLICATION ||
+ inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION)
+ {
+ Net *antecedent_net = inst->GetInput1();
+ Net *consequent_net = inst->GetInput2();
+
+ Instance *consequent_inst = net_to_ast_driver(consequent_net);
+
+ if (consequent_inst == nullptr)
+ return false;
+
+ if (consequent_inst->Type() != PRIM_SVA_S_EVENTUALLY && consequent_inst->Type() != PRIM_SVA_EVENTUALLY)
+ return false;
+
+ if (mode_cover || mode_trigger)
+ parser_error(consequent_inst);
+
+ int node;
+
+ SvaFsm antecedent_fsm(clocking, trig);
+ node = parse_sequence(antecedent_fsm, antecedent_fsm.createStartNode(), antecedent_net);
+ if (inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION) {
+ int next_node = antecedent_fsm.createNode();
+ antecedent_fsm.createEdge(node, next_node);
+ node = next_node;
+ }
+ antecedent_fsm.createLink(node, antecedent_fsm.acceptNode);
+
+ trig = antecedent_fsm.getAccept();
+ net = consequent_inst->GetInput();
+ clocking.cond_net = nullptr;
+
+ if (verific_verbose) {
+ log(" Eventually Antecedent FSM:\n");
+ antecedent_fsm.dump();
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
void parse_property(Net *net, SigBit *accept_p, SigBit *reject_p)
{
Instance *inst = net_to_ast_driver(net);
@@ -1505,20 +1668,65 @@ struct VerificSvaImporter
RTLIL::IdString root_name = module->uniquify(importer->mode_names || root->IsUserDeclared() ? RTLIL::escape_id(root->Name()) : NEW_ID);
- clocking = VerificClocking(importer, root->GetInput());
+ // parse SVA sequence into trigger signal
+
+ clocking = VerificClocking(importer, root->GetInput(), true);
+ SigBit accept_bit = State::S0, reject_bit = State::S0;
if (clocking.body_net == nullptr)
- parser_error(stringf("Failed to parse SVA clocking"), root);
+ {
+ if (clocking.clock_net != nullptr || clocking.enable_net != nullptr || clocking.disable_net != nullptr || clocking.cond_net != nullptr)
+ parser_error(stringf("Failed to parse SVA clocking"), root);
- // parse SVA sequence into trigger signal
+ if (mode_assert || mode_assume) {
+ reject_bit = module->Not(NEW_ID, parse_expression(root->GetInput()));
+ } else {
+ accept_bit = parse_expression(root->GetInput());
+ }
+ }
+ else
+ {
+ Net *net = clocking.body_net;
+ SigBit trig;
- Net *net = clocking.body_net;
- SigBit accept_bit = State::S0, reject_bit = State::S0;
+ if (eventually_property(net, trig))
+ {
+ SigBit sig_a, sig_en = trig;
+ parse_property(net, &sig_a, nullptr);
- if (mode_assert || mode_assume) {
- parse_property(net, nullptr, &reject_bit);
- } else {
- parse_property(net, &accept_bit, nullptr);
+ // add final FF stage
+
+ SigBit sig_a_q, sig_en_q;
+
+ if (clocking.body_net == nullptr) {
+ sig_a_q = sig_a;
+ sig_en_q = sig_en;
+ } else {
+ sig_a_q = module->addWire(NEW_ID);
+ sig_en_q = module->addWire(NEW_ID);
+ clocking.addDff(NEW_ID, sig_a, sig_a_q, State::S0);
+ clocking.addDff(NEW_ID, sig_en, sig_en_q, State::S0);
+ }
+
+ // generate fair/live cell
+
+ RTLIL::Cell *c = nullptr;
+
+ if (mode_assert) c = module->addLive(root_name, sig_a_q, sig_en_q);
+ if (mode_assume) c = module->addFair(root_name, sig_a_q, sig_en_q);
+
+ importer->import_attributes(c->attributes, root);
+
+ return;
+ }
+ else
+ {
+ if (mode_assert || mode_assume) {
+ parse_property(net, nullptr, &reject_bit);
+ } else {
+ parse_property(net, &accept_bit, nullptr);
+ }
+ }
}
if (mode_trigger)
@@ -1532,10 +1740,17 @@ struct VerificSvaImporter
// add final FF stage
- SigBit sig_a_q = module->addWire(NEW_ID);
- SigBit sig_en_q = module->addWire(NEW_ID);
- clocking.addDff(NEW_ID, sig_a, sig_a_q, State::S0);
- clocking.addDff(NEW_ID, sig_en, sig_en_q, State::S0);
+ SigBit sig_a_q, sig_en_q;
+
+ if (clocking.body_net == nullptr) {
+ sig_a_q = sig_a;
+ sig_en_q = sig_en;
+ } else {
+ sig_a_q = module->addWire(NEW_ID);
+ sig_en_q = module->addWire(NEW_ID);
+ clocking.addDff(NEW_ID, sig_a, sig_a_q, State::S0);
+ clocking.addDff(NEW_ID, sig_en, sig_en_q, State::S0);
+ }
// generate assert/assume/cover cell
diff --git a/frontends/verilog/.gitignore b/frontends/verilog/.gitignore
index 1d4ae9e5c..aadbcdcdd 100644
--- a/frontends/verilog/.gitignore
+++ b/frontends/verilog/.gitignore
@@ -1,4 +1,4 @@
verilog_lexer.cc
verilog_parser.output
verilog_parser.tab.cc
-verilog_parser.tab.h
+verilog_parser.tab.hh
diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc
index a06c1d5ab..dbaace585 100644
--- a/frontends/verilog/Makefile.inc
+++ b/frontends/verilog/Makefile.inc
@@ -1,15 +1,14 @@
GENFILES += frontends/verilog/verilog_parser.tab.cc
-GENFILES += frontends/verilog/verilog_parser.tab.h
+GENFILES += frontends/verilog/verilog_parser.tab.hh
GENFILES += frontends/verilog/verilog_parser.output
GENFILES += frontends/verilog/verilog_lexer.cc
frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y
$(Q) mkdir -p $(dir $@)
- $(P) $(BISON) -d -r all -b frontends/verilog/verilog_parser $<
- $(Q) mv frontends/verilog/verilog_parser.tab.c frontends/verilog/verilog_parser.tab.cc
+ $(P) $(BISON) -o $@ -d -r all -b frontends/verilog/verilog_parser $<
-frontends/verilog/verilog_parser.tab.h: frontends/verilog/verilog_parser.tab.cc
+frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc
frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l
$(Q) mkdir -p $(dir $@)
diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc
index 4a58357bf..7848c626d 100644
--- a/frontends/verilog/const2ast.cc
+++ b/frontends/verilog/const2ast.cc
@@ -49,8 +49,7 @@ static int my_decimal_div_by_two(std::vector<uint8_t> &digits)
int carry = 0;
for (size_t i = 0; i < digits.size(); i++) {
if (digits[i] >= 10)
- log_error("Invalid use of [a-fxz?] in decimal constant at %s:%d.\n",
- current_filename.c_str(), get_line_num());
+ log_file_error(current_filename, get_line_num(), "Invalid use of [a-fxz?] in decimal constant.\n");
digits[i] += carry * 10;
carry = digits[i] % 2;
digits[i] /= 2;
@@ -105,8 +104,8 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
int bits_per_digit = my_ilog2(base-1);
for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) {
if (*it > (base-1) && *it < 0xf0)
- log_error("Digit larger than %d used in in base-%d constant at %s:%d.\n",
- base-1, base, current_filename.c_str(), get_line_num());
+ log_file_error(current_filename, get_line_num(), "Digit larger than %d used in in base-%d constant.\n",
+ base-1, base);
for (int i = 0; i < bits_per_digit; i++) {
int bitmask = 1 << i;
if (*it == 0xf0)
@@ -238,4 +237,3 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc
index c43ff4e3a..dea22ee8a 100644
--- a/frontends/verilog/preproc.cc
+++ b/frontends/verilog/preproc.cc
@@ -183,8 +183,9 @@ static std::string next_token(bool pass_newline = false)
const char *ok = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789";
if (ch == '`' || strchr(ok, ch) != NULL)
{
+ char first = ch;
ch = next_char();
- if (ch == '"') {
+ if (first == '`' && (ch == '"' || ch == '`')) {
token += ch;
} else do {
if (strchr(ok, ch) == NULL) {
@@ -244,6 +245,7 @@ static bool try_expand_macro(std::set<std::string> &defines_with_args,
args.push_back(std::string());
while (1)
{
+ skip_spaces();
tok = next_token(true);
if (tok == ")" || tok == "}" || tok == "]")
level--;
@@ -264,6 +266,9 @@ static bool try_expand_macro(std::set<std::string> &defines_with_args,
}
insert_input(defines_map[name]);
return true;
+ } else if (tok == "``") {
+ // Swallow `` in macro expansion
+ return true;
} else return false;
}
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index e5917b97e..8dcc7c5aa 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -42,14 +42,14 @@ static std::list<std::vector<std::string>> verilog_defaults_stack;
static void error_on_dpi_function(AST::AstNode *node)
{
if (node->type == AST::AST_DPI_FUNCTION)
- log_error("Found DPI function %s at %s:%d.\n", node->str.c_str(), node->filename.c_str(), node->linenum);
+ 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);
}
struct VerilogFrontend : public Frontend {
VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -78,6 +78,9 @@ struct VerilogFrontend : public Frontend {
log(" -dump_ast2\n");
log(" dump abstract syntax tree (after simplification)\n");
log("\n");
+ log(" -no_dump_ptr\n");
+ log(" do not include hex memory addresses in dump (easier to diff dumps)\n");
+ log("\n");
log(" -dump_vlog\n");
log(" dump ast as Verilog code (after simplification)\n");
log("\n");
@@ -137,9 +140,13 @@ struct VerilogFrontend : public Frontend {
log(" -icells\n");
log(" interpret cell types starting with '$' as internal cell types\n");
log("\n");
- log(" -ignore_redef\n");
+ log(" -nooverwrite\n");
log(" ignore re-definitions of modules. (the default behavior is to\n");
- log(" create an error message.)\n");
+ log(" create an error message if the existing module is not a black box\n");
+ log(" module, and overwrite the existing module otherwise.)\n");
+ log("\n");
+ log(" -overwrite\n");
+ log(" overwrite existing modules with the same name\n");
log("\n");
log(" -defer\n");
log(" only read the abstract syntax tree and defer actual compilation\n");
@@ -176,10 +183,11 @@ struct VerilogFrontend : public Frontend {
log("supported by the Yosys Verilog front-end.\n");
log("\n");
}
- virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool flag_dump_ast1 = false;
bool flag_dump_ast2 = false;
+ bool flag_no_dump_ptr = false;
bool flag_dump_vlog = false;
bool flag_dump_rtlil = false;
bool flag_nolatches = false;
@@ -191,7 +199,8 @@ struct VerilogFrontend : public Frontend {
bool flag_nodpi = false;
bool flag_noopt = false;
bool flag_icells = false;
- bool flag_ignore_redef = false;
+ bool flag_nooverwrite = false;
+ bool flag_overwrite = false;
bool flag_defer = false;
std::map<std::string, std::string> defines_map;
std::list<std::string> include_dirs;
@@ -236,6 +245,10 @@ struct VerilogFrontend : public Frontend {
flag_dump_ast2 = true;
continue;
}
+ if (arg == "-no_dump_ptr") {
+ flag_no_dump_ptr = true;
+ continue;
+ }
if (arg == "-dump_vlog") {
flag_dump_vlog = true;
continue;
@@ -289,8 +302,14 @@ struct VerilogFrontend : public Frontend {
flag_icells = true;
continue;
}
- if (arg == "-ignore_redef") {
- flag_ignore_redef = true;
+ if (arg == "-ignore_redef" || arg == "-nooverwrite") {
+ flag_nooverwrite = true;
+ flag_overwrite = false;
+ continue;
+ }
+ if (arg == "-overwrite") {
+ flag_nooverwrite = false;
+ flag_overwrite = true;
continue;
}
if (arg == "-defer") {
@@ -370,7 +389,7 @@ struct VerilogFrontend : public Frontend {
if (flag_nodpi)
error_on_dpi_function(current_ast);
- AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, lib_mode, flag_noopt, flag_icells, flag_ignore_redef, flag_defer, default_nettype_wire);
+ AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, lib_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
if (!flag_nopp)
delete lexin;
@@ -384,7 +403,7 @@ struct VerilogFrontend : public Frontend {
struct VerilogDefaults : public Pass {
VerilogDefaults() : Pass("verilog_defaults", "set default options for read_verilog") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -405,7 +424,7 @@ struct VerilogDefaults : public Pass {
log("not imply -clear.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design*)
+ void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
{
if (args.size() < 2)
cmd_error(args, 1, "Missing argument.");
@@ -442,7 +461,7 @@ struct VerilogDefaults : public Pass {
struct VerilogDefines : public Pass {
VerilogDefines() : Pass("verilog_defines", "define and undefine verilog defines") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -458,7 +477,7 @@ struct VerilogDefines : public Pass {
log(" undefine the preprocessor symbol 'name'\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
@@ -508,13 +527,11 @@ void frontend_verilog_yyerror(char const *fmt, ...)
va_list ap;
char buffer[1024];
char *p = buffer;
- p += snprintf(p, buffer + sizeof(buffer) - p, "Parser error in line %s:%d: ",
- YOSYS_NAMESPACE_PREFIX AST::current_filename.c_str(), frontend_verilog_yyget_lineno());
va_start(ap, fmt);
p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
va_end(ap);
p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
- YOSYS_NAMESPACE_PREFIX log_error("%s", buffer);
+ YOSYS_NAMESPACE_PREFIX log_file_error(YOSYS_NAMESPACE_PREFIX AST::current_filename, frontend_verilog_yyget_lineno(),
+ "%s", buffer);
exit(1);
}
-
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index 8aa123e1e..83921bf0b 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -42,7 +42,7 @@
#include "kernel/log.h"
#include "frontends/verilog/verilog_frontend.h"
#include "frontends/ast/ast.h"
-#include "verilog_parser.tab.h"
+#include "verilog_parser.tab.hh"
USING_YOSYS_NAMESPACE
using namespace AST;
@@ -145,6 +145,9 @@ YOSYS_NAMESPACE_END
"endfunction" { return TOK_ENDFUNCTION; }
"task" { return TOK_TASK; }
"endtask" { return TOK_ENDTASK; }
+"specify" { return TOK_SPECIFY; }
+"endspecify" { return TOK_ENDSPECIFY; }
+"specparam" { return TOK_SPECPARAM; }
"package" { SV_KEYWORD(TOK_PACKAGE); }
"endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); }
"parameter" { return TOK_PARAMETER; }
@@ -238,10 +241,18 @@ YOSYS_NAMESPACE_END
while (yystr[i]) {
if (yystr[i] == '\\' && yystr[i + 1]) {
i++;
- if (yystr[i] == 'n')
+ if (yystr[i] == 'a')
+ yystr[i] = '\a';
+ else if (yystr[i] == 'f')
+ yystr[i] = '\f';
+ else if (yystr[i] == 'n')
yystr[i] = '\n';
+ else if (yystr[i] == 'r')
+ yystr[i] = '\r';
else if (yystr[i] == 't')
yystr[i] = '\t';
+ else if (yystr[i] == 'v')
+ yystr[i] = '\v';
else if ('0' <= yystr[i] && yystr[i] <= '7') {
yystr[i] = yystr[i] - '0';
if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') {
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index dfdeabbdb..2389d7d31 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -110,7 +110,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%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
+%token TOK_FUNCTION TOK_ENDFUNCTION TOK_TASK TOK_ENDTASK TOK_SPECIFY TOK_ENDSPECIFY TOK_SPECPARAM
%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
@@ -376,9 +376,10 @@ wire_type:
};
wire_type_token_list:
- wire_type_token | wire_type_token_list wire_type_token;
+ wire_type_token | wire_type_token_list wire_type_token |
+ wire_type_token_io ;
-wire_type_token:
+wire_type_token_io:
TOK_INPUT {
astbuf3->is_input = true;
} |
@@ -388,7 +389,9 @@ wire_type_token:
TOK_INOUT {
astbuf3->is_input = true;
astbuf3->is_output = true;
- } |
+ };
+
+wire_type_token:
TOK_WIRE {
} |
TOK_REG {
@@ -479,7 +482,7 @@ module_body:
/* empty */;
module_body_stmt:
- task_func_decl | param_decl | localparam_decl | defparam_decl | wire_decl | assign_stmt | cell_stmt |
+ task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl;
checker_decl:
@@ -638,6 +641,194 @@ task_func_body:
task_func_body behavioral_stmt |
/* empty */;
+specify_block:
+ TOK_SPECIFY specify_item_opt TOK_ENDSPECIFY |
+ TOK_SPECIFY TOK_ENDSPECIFY ;
+
+specify_item_opt:
+ specify_item_opt specify_item |
+ specify_item ;
+
+specify_item:
+ specparam_declaration
+ // | pulsestyle_declaration
+ // | showcancelled_declaration
+ | path_declaration
+ | system_timing_declaration
+ ;
+
+specparam_declaration:
+ TOK_SPECPARAM list_of_specparam_assignments ';' |
+ TOK_SPECPARAM specparam_range list_of_specparam_assignments ';' ;
+
+// IEEE 1364-2005 calls this sinmply 'range' but the current 'range' rule allows empty match
+// and the 'non_opt_range' rule allows index ranges not allowed by 1364-2005
+// exxxxtending this for SV specparam would change this anyhow
+specparam_range:
+ '[' constant_expression ':' constant_expression ']' ;
+
+list_of_specparam_assignments:
+ specparam_assignment | list_of_specparam_assignments ',' specparam_assignment;
+
+specparam_assignment:
+ TOK_ID '=' constant_mintypmax_expression ;
+
+/*
+pulsestyle_declaration :
+ ;
+
+showcancelled_declaration :
+ ;
+*/
+
+path_declaration :
+ simple_path_declaration ';'
+ // | edge_sensitive_path_declaration
+ // | state_dependent_path_declaration
+ ;
+
+simple_path_declaration :
+ parallel_path_description '=' path_delay_value |
+ full_path_description '=' path_delay_value
+ ;
+
+path_delay_value :
+ '(' 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 :
+/*
+ t_path_delay_expression
+ | trise_path_delay_expression ',' tfall_path_delay_expression
+ | trise_path_delay_expression ',' tfall_path_delay_expression ',' tz_path_delay_expression
+ | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ','
+ tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression
+ | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ','
+ tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression ','
+ t0x_path_delay_expression ',' tx1_path_delay_expression ',' t1x_path_delay_expression ','
+ tx0_path_delay_expression ',' txz_path_delay_expression ',' tzx_path_delay_expression
+*/
+ ',' path_delay_expression
+ | ',' path_delay_expression ',' path_delay_expression
+ | ',' path_delay_expression ',' path_delay_expression ','
+ path_delay_expression ',' path_delay_expression ',' path_delay_expression
+ | ',' path_delay_expression ',' path_delay_expression ','
+ path_delay_expression ',' path_delay_expression ',' path_delay_expression ','
+ path_delay_expression ',' path_delay_expression ',' path_delay_expression ','
+ path_delay_expression ',' path_delay_expression ',' path_delay_expression
+ ;
+
+parallel_path_description :
+ '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' ;
+
+full_path_description :
+ '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' ;
+
+// This was broken into 2 rules to solve shift/reduce conflicts
+list_of_path_inputs :
+ specify_input_terminal_descriptor opt_polarity_operator |
+ specify_input_terminal_descriptor more_path_inputs opt_polarity_operator ;
+
+more_path_inputs :
+ ',' specify_input_terminal_descriptor |
+ more_path_inputs ',' specify_input_terminal_descriptor ;
+
+list_of_path_outputs :
+ specify_output_terminal_descriptor |
+ list_of_path_outputs ',' specify_output_terminal_descriptor ;
+
+opt_polarity_operator :
+ '+'
+ | '-'
+ | ;
+
+// Good enough for the time being
+specify_input_terminal_descriptor :
+ TOK_ID ;
+
+// Good enough for the time being
+specify_output_terminal_descriptor :
+ TOK_ID ;
+
+system_timing_declaration :
+ TOK_ID '(' system_timing_args ')' ';' ;
+
+system_timing_arg :
+ TOK_POSEDGE TOK_ID |
+ TOK_NEGEDGE TOK_ID |
+ expr ;
+
+system_timing_args :
+ system_timing_arg |
+ system_timing_args ',' system_timing_arg ;
+
+/*
+t_path_delay_expression :
+ path_delay_expression;
+
+trise_path_delay_expression :
+ path_delay_expression;
+
+tfall_path_delay_expression :
+ path_delay_expression;
+
+tz_path_delay_expression :
+ path_delay_expression;
+
+t01_path_delay_expression :
+ path_delay_expression;
+
+t10_path_delay_expression :
+ path_delay_expression;
+
+t0z_path_delay_expression :
+ path_delay_expression;
+
+tz1_path_delay_expression :
+ path_delay_expression;
+
+t1z_path_delay_expression :
+ path_delay_expression;
+
+tz0_path_delay_expression :
+ path_delay_expression;
+
+t0x_path_delay_expression :
+ path_delay_expression;
+
+tx1_path_delay_expression :
+ path_delay_expression;
+
+t1x_path_delay_expression :
+ path_delay_expression;
+
+tx0_path_delay_expression :
+ path_delay_expression;
+
+txz_path_delay_expression :
+ path_delay_expression;
+
+tzx_path_delay_expression :
+ path_delay_expression;
+*/
+
+path_delay_expression :
+ constant_expression;
+
+constant_mintypmax_expression :
+ constant_expression
+ | constant_expression ':' constant_expression ':' 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'
+// (such as param assignment), so we may leave this as-is, perhaps assing runtime checks for constant-ness
+constant_expression:
+ expr ;
+
param_signed:
TOK_SIGNED {
astbuf1->is_signed = true;
@@ -772,11 +963,43 @@ wire_name_list:
wire_name_and_opt_assign:
wire_name {
- if (current_wire_rand) {
+ bool attr_anyconst = false;
+ bool attr_anyseq = false;
+ bool attr_allconst = false;
+ bool attr_allseq = false;
+ 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("\\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("\\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("\\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) {
AstNode *wire = new AstNode(AST_IDENTIFIER);
AstNode *fcall = new AstNode(AST_FCALL);
wire->str = ast_stack.back()->children.back()->str;
fcall->str = current_wire_const ? "\\$anyconst" : "\\$anyseq";
+ if (attr_anyconst)
+ fcall->str = "\\$anyconst";
+ if (attr_anyseq)
+ fcall->str = "\\$anyseq";
+ if (attr_allconst)
+ fcall->str = "\\$allconst";
+ if (attr_allseq)
+ fcall->str = "\\$allseq";
fcall->attributes["\\reg"] = AstNode::mkconst_str(RTLIL::unescape_id(wire->str));
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, fcall));
}
@@ -1044,39 +1267,45 @@ opt_label:
$$ = NULL;
};
+opt_property:
+ TOK_PROPERTY | /* empty */;
+
+opt_stmt_label:
+ TOK_ID ':' | /* empty */;
+
assert:
- TOK_ASSERT '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $3));
+ opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
} |
- TOK_ASSUME '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $3));
+ opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
} |
- TOK_ASSERT '(' TOK_EVENTUALLY expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $4));
+ opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
} |
- TOK_ASSUME '(' TOK_EVENTUALLY expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $4));
+ opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
} |
- TOK_COVER '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_COVER, $3));
+ opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
} |
- TOK_COVER '(' ')' ';' {
+ opt_stmt_label TOK_COVER opt_property '(' ')' ';' {
ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
} |
- TOK_COVER ';' {
+ opt_stmt_label TOK_COVER ';' {
ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
} |
- TOK_RESTRICT '(' expr ')' ';' {
+ opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' {
if (norestrict_mode)
- delete $3;
+ delete $5;
else
- ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $3));
+ ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
} |
- TOK_RESTRICT '(' TOK_EVENTUALLY expr ')' ';' {
+ opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
if (norestrict_mode)
- delete $4;
+ delete $6;
else
- ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $4));
+ ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
};
assert_property:
diff --git a/kernel/celledges.h b/kernel/celledges.h
index 6aab9ed43..2cc297cb2 100644
--- a/kernel/celledges.h
+++ b/kernel/celledges.h
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
@@ -38,7 +38,7 @@ struct FwdCellEdgesDatabase : AbstractCellEdgesDatabase
dict<SigBit, pool<SigBit>> db;
FwdCellEdgesDatabase(SigMap &sigmap) : sigmap(sigmap) { }
- virtual 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<SigBit, pool<SigBit>> db;
RevCellEdgesDatabase(SigMap &sigmap) : sigmap(sigmap) { }
- virtual 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/driver.cc b/kernel/driver.cc
index 97a78cd16..178641101 100644
--- a/kernel/driver.cc
+++ b/kernel/driver.cc
@@ -34,11 +34,17 @@
#include <limits.h>
#include <errno.h>
-#ifdef __linux__
+#if defined (__linux__) || defined(__FreeBSD__)
+# include <sys/resource.h>
# include <sys/types.h>
# include <unistd.h>
#endif
+#ifdef __FreeBSD__
+# include <sys/sysctl.h>
+# include <sys/user.h>
+#endif
+
#if !defined(_WIN32) || defined(__MINGW32__)
# include <unistd.h>
#else
@@ -79,20 +85,37 @@ USING_YOSYS_NAMESPACE
#ifdef EMSCRIPTEN
# include <sys/stat.h>
# include <sys/types.h>
+# include <emscripten.h>
extern "C" int main(int, char**);
extern "C" void run(const char*);
extern "C" const char *errmsg();
extern "C" const char *prompt();
-int main(int, char**)
+int main(int argc, char **argv)
{
+ EM_ASM(
+ if (ENVIRONMENT_IS_NODE)
+ {
+ FS.mkdir('/hostcwd');
+ FS.mount(NODEFS, { root: '.' }, '/hostcwd');
+ FS.mkdir('/hostfs');
+ FS.mount(NODEFS, { root: '/' }, '/hostfs');
+ }
+ );
+
mkdir("/work", 0777);
chdir("/work");
log_files.push_back(stdout);
log_error_stderr = true;
yosys_banner();
yosys_setup();
+
+ if (argc == 2)
+ {
+ // Run the first argument as a script file
+ run_frontend(argv[1], "script", 0, 0, 0);
+ }
}
void run(const char *command)
@@ -254,9 +277,13 @@ int main(int argc, char **argv)
printf(" print a warning for all log messages matching the regex.\n");
printf("\n");
printf(" -w regex\n");
- printf(" if a warning message matches the regex, it is printes as regular\n");
+ printf(" if a warning message matches the regex, it is printed as regular\n");
printf(" message instead.\n");
printf("\n");
+ printf(" -e regex\n");
+ printf(" if a warning message matches the regex, it is printed as error\n");
+ printf(" message instead and the tool terminates with a nonzero return code.\n");
+ printf("\n");
printf(" -E <depsfile>\n");
printf(" write a Makefile dependencies file with in- and output file names\n");
printf("\n");
@@ -280,7 +307,7 @@ int main(int argc, char **argv)
}
int opt;
- while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:D:E:")) != -1)
+ while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:E:")) != -1)
{
switch (opt)
{
@@ -374,6 +401,12 @@ int main(int argc, char **argv)
std::regex_constants::optimize |
std::regex_constants::egrep));
break;
+ case 'e':
+ log_werror_regexes.push_back(std::regex(optarg,
+ std::regex_constants::nosubs |
+ std::regex_constants::optimize |
+ std::regex_constants::egrep));
+ break;
case 'D':
{
auto args = split_tokens(optarg, ":");
@@ -416,6 +449,18 @@ int main(int argc, char **argv)
if (print_stats)
log_hasher = new SHA1;
+#if defined(__linux__)
+ // set stack size to >= 128 MB
+ {
+ struct rlimit rl;
+ const rlim_t stack_size = 128L * 1024L * 1024L;
+ if (getrlimit(RLIMIT_STACK, &rl) == 0 && rl.rlim_cur < stack_size) {
+ rl.rlim_cur = stack_size;
+ setrlimit(RLIMIT_STACK, &rl);
+ }
+ }
+#endif
+
yosys_setup();
log_error_atexit = yosys_atexit;
@@ -487,7 +532,7 @@ int main(int argc, char **argv)
#else
std::string meminfo;
std::string stats_divider = ", ";
-# ifdef __linux__
+# if defined(__linux__)
std::ifstream statm;
statm.open(stringf("/proc/%lld/statm", (long long)getpid()));
if (statm.is_open()) {
@@ -498,6 +543,19 @@ int main(int argc, char **argv)
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;
@@ -541,7 +599,7 @@ int main(int argc, char **argv)
}
}
-#if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
+#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
if (getenv("YOSYS_COVER_DIR") || getenv("YOSYS_COVER_FILE"))
{
string filename;
diff --git a/kernel/log.cc b/kernel/log.cc
index de564cb36..0ee2170a0 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -25,7 +25,7 @@
# include <sys/time.h>
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
# include <dlfcn.h>
#endif
@@ -41,7 +41,7 @@ YOSYS_NAMESPACE_BEGIN
std::vector<FILE*> log_files;
std::vector<std::ostream*> log_streams;
std::map<std::string, std::set<std::string>> log_hdump;
-std::vector<std::regex> log_warn_regexes, log_nowarn_regexes;
+std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
std::set<std::string> log_warnings;
int log_warnings_count = 0;
bool log_hdump_all = false;
@@ -203,7 +203,8 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap)
log_files.pop_back();
}
-void logv_warning(const char *format, va_list ap)
+static void logv_warning_with_prefix(const char *prefix,
+ const char *format, va_list ap)
{
std::string message = vstringf(format, ap);
bool suppressed = false;
@@ -214,13 +215,17 @@ void logv_warning(const char *format, va_list ap)
if (suppressed)
{
- log("Suppressed warning: %s", message.c_str());
+ log("Suppressed %s%s", prefix, message.c_str());
}
else
{
+ for (auto &re : log_werror_regexes)
+ if (std::regex_search(message, re))
+ log_error("%s", message.c_str());
+
if (log_warnings.count(message))
{
- log("Warning: %s", message.c_str());
+ log("%s%s", prefix, message.c_str());
log_flush();
}
else
@@ -228,7 +233,7 @@ void logv_warning(const char *format, va_list ap)
if (log_errfile != NULL && !log_quiet_warnings)
log_files.push_back(log_errfile);
- log("Warning: %s", message.c_str());
+ log("%s%s", prefix, message.c_str());
log_flush();
if (log_errfile != NULL && !log_quiet_warnings)
@@ -241,45 +246,30 @@ void logv_warning(const char *format, va_list ap)
}
}
-void logv_warning_noprefix(const char *format, va_list ap)
+void logv_warning(const char *format, va_list ap)
{
- std::string message = vstringf(format, ap);
- bool suppressed = false;
-
- for (auto &re : log_nowarn_regexes)
- if (std::regex_search(message, re))
- suppressed = true;
-
- if (suppressed)
- {
- log("%s", message.c_str());
- }
- else
- {
- if (log_warnings.count(message))
- {
- log("%s", message.c_str());
- log_flush();
- }
- else
- {
- if (log_errfile != NULL && !log_quiet_warnings)
- log_files.push_back(log_errfile);
-
- log("%s", message.c_str());
- log_flush();
-
- if (log_errfile != NULL && !log_quiet_warnings)
- log_files.pop_back();
+ logv_warning_with_prefix("Warning: ", format, ap);
+}
- log_warnings.insert(message);
- }
+void logv_warning_noprefix(const char *format, va_list ap)
+{
+ logv_warning_with_prefix("", format, ap);
+}
- log_warnings_count++;
- }
+void log_file_warning(const std::string &filename, int lineno,
+ const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ std::string prefix = stringf("%s:%d: Warning: ",
+ filename.c_str(), lineno);
+ logv_warning_with_prefix(prefix.c_str(), format, ap);
+ va_end(ap);
}
-void logv_error(const char *format, va_list ap)
+YS_ATTRIBUTE(noreturn)
+static void logv_error_with_prefix(const char *prefix,
+ const char *format, va_list ap)
{
#ifdef EMSCRIPTEN
auto backup_log_files = log_files;
@@ -294,7 +284,7 @@ void logv_error(const char *format, va_list ap)
f = stderr;
log_last_error = vstringf(format, ap);
- log("ERROR: %s", log_last_error.c_str());
+ log("%s%s", prefix, log_last_error.c_str());
log_flush();
if (log_error_atexit)
@@ -310,6 +300,21 @@ void logv_error(const char *format, va_list ap)
#endif
}
+void logv_error(const char *format, va_list ap)
+{
+ logv_error_with_prefix("ERROR: ", format, ap);
+}
+
+void log_file_error(const string &filename, int lineno,
+ const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ std::string prefix = stringf("%s:%d: ERROR: ",
+ filename.c_str(), lineno);
+ logv_error_with_prefix(prefix.c_str(), format, ap);
+}
+
void log(const char *format, ...)
{
va_list ap;
@@ -384,7 +389,7 @@ void log_pop()
log_flush();
}
-#if defined(__linux__) && defined(YOSYS_ENABLE_PLUGINS)
+#if (defined(__linux__) || defined(__FreeBSD__)) && defined(YOSYS_ENABLE_PLUGINS)
void log_backtrace(const char *prefix, int levels)
{
if (levels <= 0) return;
@@ -579,7 +584,7 @@ void log_wire(RTLIL::Wire *wire, std::string indent)
// ---------------------------------------------------
// This is the magic behind the code coverage counters
// ---------------------------------------------------
-#if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
+#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
dict<std::string, std::pair<std::string, int>> extra_coverage_data;
@@ -628,4 +633,3 @@ dict<std::string, std::pair<std::string, int>> get_coverage_data()
#endif
YOSYS_NAMESPACE_END
-
diff --git a/kernel/log.h b/kernel/log.h
index 90a12df36..0b4905c3a 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -49,7 +49,7 @@ struct log_cmd_error_exception { };
extern std::vector<FILE*> log_files;
extern std::vector<std::ostream*> log_streams;
extern std::map<std::string, std::set<std::string>> log_hdump;
-extern std::vector<std::regex> log_warn_regexes, log_nowarn_regexes;
+extern std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
extern std::set<std::string> log_warnings;
extern int log_warnings_count;
extern bool log_hdump_all;
@@ -73,8 +73,13 @@ YS_NORETURN void logv_error(const char *format, va_list ap) YS_ATTRIBUTE(noretur
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));
+
+// 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_warning_noprefix(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);
void log_spacer();
@@ -114,7 +119,7 @@ static inline void log_assert_worker(bool cond, const char *expr, const char *fi
// This is the magic behind the code coverage counters
// ---------------------------------------------------
-#if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
+#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
#define cover(_id) do { \
static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1), used)) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \
diff --git a/kernel/modtools.h b/kernel/modtools.h
index ffcb48d44..409562eb9 100644
--- a/kernel/modtools.h
+++ b/kernel/modtools.h
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
@@ -158,7 +158,7 @@ struct ModIndex : public RTLIL::Monitor
#endif
}
- virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_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);
}
- virtual void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const RTLIL::SigSig &sigsig) YS_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
}
}
- virtual void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const std::vector<RTLIL::SigSig>&) YS_OVERRIDE
+ void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const std::vector<RTLIL::SigSig>&) YS_OVERRIDE
{
log_assert(module == mod);
auto_reload_module = true;
}
- virtual void notify_blackout(RTLIL::Module *mod YS_ATTRIBUTE(unused)) YS_OVERRIDE
+ void notify_blackout(RTLIL::Module *mod YS_ATTRIBUTE(unused)) YS_OVERRIDE
{
log_assert(module == mod);
auto_reload_module = true;
diff --git a/kernel/register.cc b/kernel/register.cc
index e30414f44..402a5b3ea 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -615,7 +615,7 @@ static struct CellHelpMessages {
struct HelpPass : public Pass {
HelpPass() : Pass("help", "display help messages") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
log("\n");
log(" help ................ list all commands\n");
@@ -684,7 +684,7 @@ struct HelpPass : public Pass {
fclose(f);
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design*)
+ void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
{
if (args.size() == 1) {
log("\n");
@@ -768,7 +768,7 @@ struct HelpPass : public Pass {
struct EchoPass : public Pass {
EchoPass() : Pass("echo", "turning echoing back of commands on and off") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
log("\n");
log(" echo on\n");
@@ -781,7 +781,7 @@ struct EchoPass : public Pass {
log("Do not print all commands to log before executing them. (default)\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design*)
+ void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
{
if (args.size() > 2)
cmd_error(args, 2, "Unexpected argument.");
@@ -806,10 +806,9 @@ struct MinisatSatSolver : public SatSolver {
MinisatSatSolver() : SatSolver("minisat") {
yosys_satsolver = this;
}
- virtual ezSAT *create() YS_OVERRIDE {
+ ezSAT *create() YS_OVERRIDE {
return new ezMiniSAT();
}
} MinisatSatSolver;
YOSYS_NAMESPACE_END
-
diff --git a/kernel/register.h b/kernel/register.h
index 8024c56a0..c74029823 100644
--- a/kernel/register.h
+++ b/kernel/register.h
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
@@ -88,9 +88,9 @@ struct Frontend : Pass
std::string frontend_name;
Frontend(std::string name, std::string short_help = "** document me **");
- virtual void run_register() YS_OVERRIDE;
- virtual ~Frontend();
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL;
+ void run_register() YS_OVERRIDE;
+ ~Frontend() YS_OVERRIDE;
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL;
virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
static std::vector<std::string> next_args;
@@ -104,9 +104,9 @@ struct Backend : Pass
{
std::string backend_name;
Backend(std::string name, std::string short_help = "** document me **");
- virtual void run_register() YS_OVERRIDE;
- virtual ~Backend();
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL;
+ void run_register() YS_OVERRIDE;
+ ~Backend() YS_OVERRIDE;
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL;
virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
void extra_args(std::ostream *&f, std::string &filename, std::vector<std::string> args, size_t argidx);
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 54d0b8c22..027faf416 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
diff --git a/kernel/satgen.h b/kernel/satgen.h
index 8d760fff7..210cca3f3 100644
--- a/kernel/satgen.h
+++ b/kernel/satgen.h
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index cade09048..264b1f63d 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -46,10 +46,15 @@
# include <unistd.h>
# include <dirent.h>
# include <sys/types.h>
+# include <sys/wait.h>
# include <sys/stat.h>
# include <glob.h>
#endif
+#ifdef __FreeBSD__
+# include <sys/sysctl.h>
+#endif
+
#include <limits.h>
#include <errno.h>
@@ -72,7 +77,7 @@ std::vector<void*> memhasher_store;
void memhasher_on()
{
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
memhasher_rng += time(NULL) << 16 ^ getpid();
#endif
memhasher_store.resize(0x10000);
@@ -598,6 +603,8 @@ static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *a
std::string tcl_command_name = it.first;
if (tcl_command_name == "proc")
tcl_command_name = "procs";
+ else if (tcl_command_name == "rename")
+ tcl_command_name = "renames";
Tcl_CmdInfo info;
if (Tcl_GetCommandInfo(interp, tcl_command_name.c_str(), &info) != 0) {
log("[TCL: yosys -import] Command name collision: found pre-existing command `%s' -> skip.\n", it.first.c_str());
@@ -629,7 +636,7 @@ extern Tcl_Interp *yosys_get_tcl_interp()
struct TclPass : public Pass {
TclPass() : Pass("tcl", "execute a TCL script file") { }
- virtual void help() {
+ void help() YS_OVERRIDE {
log("\n");
log(" tcl <filename>\n");
log("\n");
@@ -637,12 +644,12 @@ struct TclPass : public Pass {
log("Use 'yosys cmd' to run the yosys command 'cmd' from tcl.\n");
log("\n");
log("The tcl command 'yosys -import' can be used to import all yosys\n");
- log("commands directly as tcl commands to the tcl shell. The yosys\n");
- log("command 'proc' is wrapped using the tcl command 'procs' in order\n");
- log("to avoid a name collision with the tcl builtin command 'proc'.\n");
+ log("commands directly as tcl commands to the tcl shell. Yosys commands\n");
+ log("'proc' and 'rename' are wrapped to tcl commands 'procs' and 'renames'\n");
+ log("in order to avoid a name collision with the built in commands.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
if (args.size() < 2)
log_cmd_error("Missing script file.\n");
if (args.size() > 2)
@@ -665,6 +672,26 @@ std::string proc_self_dirname()
buflen--;
return std::string(path, buflen);
}
+#elif defined(__FreeBSD__)
+std::string proc_self_dirname()
+{
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
+ size_t buflen;
+ char *buffer;
+ std::string path;
+ if (sysctl(mib, 4, NULL, &buflen, NULL, 0) != 0)
+ log_error("sysctl failed: %s\n", strerror(errno));
+ buffer = (char*)malloc(buflen);
+ if (buffer == NULL)
+ log_error("malloc failed: %s\n", strerror(errno));
+ if (sysctl(mib, 4, buffer, &buflen, NULL, 0) != 0)
+ log_error("sysctl failed: %s\n", strerror(errno));
+ while (buflen > 0 && buffer[buflen-1] != '/')
+ buflen--;
+ path.assign(buffer, buflen);
+ free(buffer);
+ return path;
+}
#elif defined(__APPLE__)
std::string proc_self_dirname()
{
@@ -712,7 +739,7 @@ std::string proc_self_dirname()
#ifdef EMSCRIPTEN
std::string proc_share_dirname()
{
- return "/share";
+ return "/share/";
}
#else
std::string proc_share_dirname()
@@ -798,6 +825,8 @@ void run_frontend(std::string filename, std::string command, std::string *backen
command = "vhdl";
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".blif")
command = "blif";
+ else if (filename.size() > 5 && filename.substr(filename.size()-6) == ".eblif")
+ command = "blif";
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".json")
command = "json";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
@@ -1084,7 +1113,7 @@ void shell(RTLIL::Design *design)
struct ShellPass : public Pass {
ShellPass() : Pass("shell", "enter interactive command mode") { }
- virtual void help() {
+ void help() YS_OVERRIDE {
log("\n");
log(" shell\n");
log("\n");
@@ -1116,7 +1145,7 @@ struct ShellPass : public Pass {
log("Press Ctrl-D or type 'exit' to leave the interactive shell.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
extra_args(args, 1, design, false);
shell(design);
}
@@ -1125,7 +1154,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") { }
- virtual void help() {
+ void help() YS_OVERRIDE {
log("\n");
log(" history\n");
log("\n");
@@ -1134,7 +1163,7 @@ struct HistoryPass : public Pass {
log("from executed scripts.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ void execute(std::vector<std::string> 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++)
@@ -1149,7 +1178,7 @@ struct HistoryPass : public Pass {
struct ScriptCmdPass : public Pass {
ScriptCmdPass() : Pass("script", "execute commands from script file") { }
- virtual void help() {
+ void help() YS_OVERRIDE {
log("\n");
log(" script <filename> [<from_label>:<to_label>]\n");
log("\n");
@@ -1164,7 +1193,7 @@ struct ScriptCmdPass : public Pass {
log("marked with that label (until the next label) is executed.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
if (args.size() < 2)
log_cmd_error("Missing script file.\n");
else if (args.size() == 2)
diff --git a/kernel/yosys.h b/kernel/yosys.h
index 14cbcd610..c9f973318 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
diff --git a/manual/CHAPTER_Prog/stubnets.cc b/manual/CHAPTER_Prog/stubnets.cc
index eb77bd404..8123e63db 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") { }
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
// variables to mirror information from passed options
bool report_bits = 0;
diff --git a/manual/PRESENTATION_Prog/my_cmd.cc b/manual/PRESENTATION_Prog/my_cmd.cc
index d99bfe1e8..5d9a7e13b 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") { }
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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") { }
- virtual void execute(std::vector<std::string>, RTLIL::Design *design)
+ void execute(std::vector<std::string>, 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") { }
- virtual void execute(std::vector<std::string>, RTLIL::Design *design)
+ void execute(std::vector<std::string>, 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/misc/yosys.proto b/misc/yosys.proto
new file mode 100644
index 000000000..2870176cb
--- /dev/null
+++ b/misc/yosys.proto
@@ -0,0 +1,175 @@
+//
+// yosys -- Yosys Open SYnthesis Suite
+//
+// Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+
+/// Protobuf definition of Yosys RTLIL dump/restore format for RTL designs.
+
+syntax = "proto3";
+
+package yosys.pb;
+
+// Port direction.
+enum Direction {
+ DIRECTION_INVALID = 0;
+ DIRECTION_INPUT = 1;
+ DIRECTION_OUTPUT = 2;
+ DIRECTION_INOUT = 3;
+}
+
+// A freeform parameter/attribute value.
+message Parameter {
+ oneof value {
+ int64 int = 1;
+ string str = 2;
+ }
+}
+
+// A signal in the design - either a unique identifier for one, or a constant
+// driver (low or high).
+message Signal {
+ // A constant signal driver in the design.
+ enum ConstantDriver {
+ CONSTANT_DRIVER_INVALID = 0;
+ CONSTANT_DRIVER_LOW = 1;
+ CONSTANT_DRIVER_HIGH = 2;
+ CONSTANT_DRIVER_Z = 3;
+ CONSTANT_DRIVER_X = 4;
+ }
+ oneof type {
+ // Signal uniquely identified by ID number.
+ int64 id = 1;
+ // Constant driver.
+ ConstantDriver constant = 2;
+ }
+}
+
+// A vector of signals.
+message BitVector {
+ repeated Signal signal = 1;
+}
+
+// A netlist module.
+message Module {
+ // Freeform attributes.
+ map<string, Parameter> attribute = 1;
+
+ // Named ports in this module.
+ message Port {
+ Direction direction = 1;
+ BitVector bits = 2;
+ }
+ map<string, Port> port = 2;
+
+ // Named cells in this module.
+ message Cell {
+ // Set to true when the name of this cell is automatically created and
+ // likely not of interest for a regular user.
+ bool hide_name = 1;
+ string type = 2;
+ // Set if this module has an AIG model available.
+ string model = 3;
+ // Freeform parameters.
+ map<string, Parameter> parameter = 4;
+ // Freeform attributes.
+ map<string, Parameter> attribute = 5;
+
+ /// Ports of the cell.
+ // Direction of the port, if interface is known.
+ map<string, Direction> port_direction = 6;
+ // Connection of named port to signal(s).
+ map<string, BitVector> connection = 7;
+ }
+ map<string, Cell> cell = 3;
+
+ // Nets in this module.
+ message Netname {
+ // Set to true when the name of this net is automatically created and
+ // likely not of interest for a regular user.
+ bool hide_name = 1;
+ // Signal(s) that make up this net.
+ BitVector bits = 2;
+ // Freeform attributes.
+ map<string, Parameter> attributes = 3;
+ }
+ repeated Netname netname = 4;
+}
+
+// And-Inverter-Graph model.
+message Model {
+ message Node {
+ // Type of AIG node - or, what its' value is.
+ enum Type {
+ TYPE_INVALID = 0;
+ // The node's value is the value of the specified input port bit.
+ TYPE_PORT = 1;
+ // The node's value is the inverted value of the specified input
+ // port bit.
+ TYPE_NPORT = 2;
+ // The node's value is the ANDed value of specified nodes.
+ TYPE_AND = 3;
+ // The node's value is the NANDed value of specified nodes.
+ TYPE_NAND = 4;
+ // The node's value is a constant 1.
+ TYPE_TRUE = 5;
+ // The node's value is a constant 0.
+ TYPE_FALSE = 6;
+ };
+ Type type = 1;
+
+ message Port {
+ // Name of port.
+ string portname = 1;
+ // Bit index in port.
+ int64 bitindex = 2;
+ }
+ message Gate {
+ // Node index of left side of operation.
+ int64 left = 1;
+ // Node index of right side of operation.
+ int64 right = 2;
+ }
+ oneof node {
+ // Set for PORT, NPORT
+ Port port = 2;
+ // Set for AND, NAND.
+ Gate gate = 3;
+ }
+
+ // Set when the node drives given output port(s).
+ message OutPort {
+ // Name of port.
+ string name = 1;
+ // Bit index in port.
+ int64 bit_index = 2;
+ }
+ repeated OutPort out_port = 4;
+ }
+
+ // List of AIG nodes - each is explicitely numbered by its' index in this
+ // array.
+ repeated Node node = 1;
+}
+
+// A Yosys design netlist dumped from RTLIL.
+message Design {
+ // Human-readable freeform 'remark' string.
+ string creator = 1;
+ // List of named modules in design.
+ map<string, Module> modules = 2;
+ // List of named AIG models in design (if AIG export enabled).
+ map<string, Model> models = 3;
+}
diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc
index e698926f9..cfccca966 100644
--- a/passes/cmds/add.cc
+++ b/passes/cmds/add.cc
@@ -83,7 +83,7 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n
struct AddPass : public Pass {
AddPass() : Pass("add", "add objects to the design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -106,7 +106,7 @@ struct AddPass : public Pass {
log("selected modules.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string command;
std::string arg_name;
diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc
index 497b35f5c..6094f8f16 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", "change type of cells in the design") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index bb8fe6856..64697c134 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -51,7 +51,7 @@ struct CheckPass : public Pass {
log("problems are found in the current design.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
int counter = 0;
bool noinit = false;
diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc
index a8c1fef85..522758eae 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") { }
- virtual void help()
+ 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. this options can be combined\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool assert2assume = false;
bool assume2assert = false;
diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc
index 90d51667c..979aeadd4 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
IdString set_type;
dict<IdString, IdString> map_types;
diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc
index 52611cf44..d480b79ac 100644
--- a/passes/cmds/connect.cc
+++ b/passes/cmds/connect.cc
@@ -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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -75,7 +75,7 @@ struct ConnectPass : public Pass {
log("This command does not operate on module with processes.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
RTLIL::Module *module = NULL;
for (auto &it : design->modules_) {
diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc
index 1ea48b7eb..5a15cbbaf 100644
--- a/passes/cmds/connwrappers.cc
+++ b/passes/cmds/connwrappers.cc
@@ -150,7 +150,7 @@ struct ConnwrappersWorker
struct ConnwrappersPass : public Pass {
ConnwrappersPass() : Pass("connwrappers", "match width of input-output port pairs") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -172,7 +172,7 @@ struct ConnwrappersPass : public Pass {
log("The options -signed, -unsigned, and -port can be specified multiple times.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
ConnwrappersWorker worker;
diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc
index fb863512b..acd2dba52 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
if (args.size() != 3)
log_cmd_error("Invalid number of arguments!\n");
diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc
index 1475475c3..0ec747671 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<FILE*> out_files;
std::vector<std::string> patterns;
@@ -128,7 +128,7 @@ struct CoverPass : public Pass {
log("\n");
}
-#if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
+#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
for (auto &it : get_coverage_data()) {
if (!patterns.empty()) {
for (auto &p : patterns)
diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc
index 6d51d30e7..f8d91ea48 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool flag_input = false;
bool flag_output = false;
diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc
index 490c8dde5..172addcc1 100644
--- a/passes/cmds/design.cc
+++ b/passes/cmds/design.cc
@@ -27,7 +27,7 @@ std::vector<RTLIL::Design*> pushed_designs;
struct DesignPass : public Pass {
DesignPass() : Pass("design", "save, restore and reset current design") { }
- virtual ~DesignPass() {
+ ~DesignPass() YS_OVERRIDE {
for (auto &it : saved_designs)
delete it.second;
saved_designs.clear();
@@ -35,7 +35,7 @@ struct DesignPass : public Pass {
delete it;
pushed_designs.clear();
}
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -94,7 +94,7 @@ struct DesignPass : public Pass {
log("between calls to 'read_verilog'. This command resets this memory.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool got_mode = false;
bool reset_mode = false;
diff --git a/passes/cmds/edgetypes.cc b/passes/cmds/edgetypes.cc
index 7b75a009f..58ed6457d 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/cmds/logcmd.cc b/passes/cmds/logcmd.cc
index 85386f3d2..522e1089d 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design*)
+ void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
{
size_t argidx;
bool to_stdout = false;
diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc
index 42dc794ec..05701710b 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool noff = false;
diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc
index 828c671de..aa6d5b6cc 100644
--- a/passes/cmds/plugin.cc
+++ b/passes/cmds/plugin.cc
@@ -58,7 +58,7 @@ void load_plugin(std::string, std::vector<std::string>)
struct PluginPass : public Pass {
PluginPass() : Pass("plugin", "load and list loaded plugins") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -76,7 +76,7 @@ struct PluginPass : public Pass {
log(" List loaded plugins\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string plugin_filename;
std::vector<std::string> plugin_aliases;
diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc
index f2dfa760e..1c64a7b77 100644
--- a/passes/cmds/qwp.cc
+++ b/passes/cmds/qwp.cc
@@ -778,7 +778,7 @@ struct QwpWorker
struct QwpPass : public Pass {
QwpPass() : Pass("qwp", "quadratic wirelength placer") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
QwpConfig config;
xorshift32_state = 123456789;
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index 6a002869b..dce576fdf 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -54,7 +54,7 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std::
struct RenamePass : public Pass {
RenamePass() : Pass("rename", "rename object in the design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -81,7 +81,7 @@ struct RenamePass : public Pass {
log("Rename top module.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string pattern_prefix = "_", pattern_suffix = "_";
bool flag_enumerate = false;
diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc
index f083e1f67..7123ba9fb 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -41,7 +41,7 @@ struct ScatterPass : public Pass {
log("Use the opt_clean command to get rid of the additional nets.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
CellTypes ct(design);
extra_args(args, 1, design);
diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc
index 76363e051..99f4fbae8 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)") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::map<std::string, std::string> setAttr;
bool allCellTypes = false;
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index a0720797f..d97aa2b37 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -950,7 +950,7 @@ PRIVATE_NAMESPACE_BEGIN
struct SelectPass : public Pass {
SelectPass() : Pass("select", "modify and view the list of selected objects") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -964,7 +964,7 @@ struct SelectPass : public Pass {
log("list of selected objects.\n");
log("\n");
log("Note that many commands support an optional [selection] argument that can be\n");
- log("used to override the global selection for the command. The syntax of this\n");
+ log("used to YS_OVERRIDE the global selection for the command. The syntax of this\n");
log("optional argument is identical to the syntax of the <selection> argument\n");
log("described here.\n");
log("\n");
@@ -1167,7 +1167,7 @@ struct SelectPass : public Pass {
log(" select */t:SWITCH %%x:+[GATE] */t:SWITCH %%d\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool add_mode = false;
bool del_mode = false;
@@ -1470,7 +1470,7 @@ struct SelectPass : public Pass {
struct CdPass : public Pass {
CdPass() : Pass("cd", "a shortcut for 'select -module <name>'") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1496,7 +1496,7 @@ struct CdPass : public Pass {
log("This is just a shortcut for 'select -clear'.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
if (args.size() != 1 && args.size() != 2)
log_cmd_error("Invalid number of arguments.\n");
@@ -1578,7 +1578,7 @@ static void log_matches(const char *title, Module *module, T list)
struct LsPass : public Pass {
LsPass() : Pass("ls", "list modules or objects in modules") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1589,7 +1589,7 @@ struct LsPass : public Pass {
log("When an active module is selected, this prints a list of objects in the module.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 689e3148b..d38a6b3da 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -56,7 +56,7 @@ static void do_setunset(dict<RTLIL::IdString, RTLIL::Const> &attrs, const std::v
struct SetattrPass : public Pass {
SetattrPass() : Pass("setattr", "set/unset attributes on objects") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<setunset_t> setunset_list;
bool flag_mod = false;
@@ -130,7 +130,7 @@ struct SetattrPass : public Pass {
struct SetparamPass : public Pass {
SetparamPass() : Pass("setparam", "set/unset parameters on objects") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -142,7 +142,7 @@ struct SetparamPass : public Pass {
log("The -type option can be used to change the cell type of the selected cells.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
vector<setunset_t> setunset_list;
string new_cell_type;
@@ -188,7 +188,7 @@ struct SetparamPass : public Pass {
struct ChparamPass : public Pass {
ChparamPass() : Pass("chparam", "re-evaluate modules with new parameters") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -203,7 +203,7 @@ struct ChparamPass : public Pass {
log("List the available parameters of the selected modules.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<setunset_t> setunset_list;
dict<RTLIL::IdString, RTLIL::Const> new_parameters;
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index 9827ac0b1..a1dfa9b5c 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -23,9 +23,44 @@
#include "kernel/rtlil.h"
#include "kernel/log.h"
+#define MODE_ZERO 0
+#define MODE_ONE 1
+#define MODE_UNDEF 2
+#define MODE_RANDOM 3
+#define MODE_ANYSEQ 4
+#define MODE_ANYCONST 5
+
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+static RTLIL::Wire * add_wire(RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output)
+{
+ RTLIL::Wire *wire = NULL;
+ name = RTLIL::escape_id(name);
+
+ if (module->count_id(name) != 0)
+ {
+ log("Module %s already has such an object %s.\n", module->name.c_str(), name.c_str());
+ name += "$";
+ return add_wire(module, name, width, flag_input, flag_output);
+ }
+ else
+ {
+ wire = module->addWire(name, width);
+ wire->port_input = flag_input;
+ wire->port_output = flag_output;
+
+ if (flag_input || flag_output) {
+ wire->port_id = module->wires_.size();
+ module->fixup_ports();
+ }
+
+ log("Added wire %s to module %s.\n", name.c_str(), module->name.c_str());
+ }
+
+ return wire;
+}
+
struct SetundefWorker
{
int next_bit_mode;
@@ -34,24 +69,32 @@ struct SetundefWorker
RTLIL::State next_bit()
{
- if (next_bit_mode == 0)
+ if (next_bit_mode == MODE_ZERO)
return RTLIL::State::S0;
- if (next_bit_mode == 1)
+ if (next_bit_mode == MODE_ONE)
return RTLIL::State::S1;
- // xorshift32
- next_bit_state ^= next_bit_state << 13;
- next_bit_state ^= next_bit_state >> 17;
- next_bit_state ^= next_bit_state << 5;
- log_assert(next_bit_state != 0);
+ if (next_bit_mode == MODE_UNDEF)
+ return RTLIL::State::Sx;
+
+ if (next_bit_mode == MODE_RANDOM)
+ {
+ // xorshift32
+ next_bit_state ^= next_bit_state << 13;
+ next_bit_state ^= next_bit_state >> 17;
+ next_bit_state ^= next_bit_state << 5;
+ log_assert(next_bit_state != 0);
+
+ return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1;
+ }
- return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1;
+ log_abort();
}
void operator()(RTLIL::SigSpec &sig)
{
- if (next_bit_mode == 2) {
+ if (next_bit_mode == MODE_ANYSEQ || next_bit_mode == MODE_ANYCONST) {
siglist.push_back(&sig);
return;
}
@@ -64,7 +107,7 @@ struct SetundefWorker
struct SetundefPass : public Pass {
SetundefPass() : Pass("setundef", "replace undef values with defined constants") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -75,15 +118,24 @@ struct SetundefPass : public Pass {
log(" -undriven\n");
log(" also set undriven nets to constant values\n");
log("\n");
+ log(" -expose\n");
+ log(" also expose undriven nets as inputs (use with -undriven)\n");
+ log("\n");
log(" -zero\n");
log(" replace with bits cleared (0)\n");
log("\n");
log(" -one\n");
log(" replace with bits set (1)\n");
log("\n");
+ log(" -undef\n");
+ log(" replace with undef (x) bits, may be used with -undriven\n");
+ log("\n");
log(" -anyseq\n");
log(" replace with $anyseq drivers (for formal)\n");
log("\n");
+ log(" -anyconst\n");
+ log(" replace with $anyconst drivers (for formal)\n");
+ log("\n");
log(" -random <seed>\n");
log(" replace with random bits using the specified integer als seed\n");
log(" value for the random number generator.\n");
@@ -92,10 +144,11 @@ struct SetundefPass : public Pass {
log(" also create/update init values for flip-flops\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool got_value = false;
bool undriven_mode = false;
+ bool expose_mode = false;
bool init_mode = false;
SetundefWorker worker;
@@ -108,19 +161,38 @@ struct SetundefPass : public Pass {
undriven_mode = true;
continue;
}
+ if (args[argidx] == "-expose") {
+ expose_mode = true;
+ continue;
+ }
if (args[argidx] == "-zero") {
got_value = true;
- worker.next_bit_mode = 0;
+ worker.next_bit_mode = MODE_ZERO;
+ worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-one") {
got_value = true;
- worker.next_bit_mode = 1;
+ worker.next_bit_mode = MODE_ONE;
+ worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-anyseq") {
got_value = true;
- worker.next_bit_mode = 2;
+ worker.next_bit_mode = MODE_ANYSEQ;
+ worker.next_bit_state = 0;
+ continue;
+ }
+ if (args[argidx] == "-anyconst") {
+ got_value = true;
+ worker.next_bit_mode = MODE_ANYCONST;
+ worker.next_bit_state = 0;
+ continue;
+ }
+ if (args[argidx] == "-undef") {
+ got_value = true;
+ worker.next_bit_mode = MODE_UNDEF;
+ worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-init") {
@@ -129,7 +201,7 @@ struct SetundefPass : public Pass {
}
if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
got_value = true;
- worker.next_bit_mode = 3;
+ worker.next_bit_mode = MODE_RANDOM;
worker.next_bit_state = atoi(args[++argidx].c_str()) + 1;
for (int i = 0; i < 10; i++)
worker.next_bit();
@@ -139,8 +211,20 @@ struct SetundefPass : public Pass {
}
extra_args(args, argidx, design);
+ if (!got_value && expose_mode) {
+ log("Using default as -undef with -expose.\n");
+ got_value = true;
+ worker.next_bit_mode = MODE_UNDEF;
+ worker.next_bit_state = 0;
+ }
+
+ 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, or -random <seed> must be specified.\n");
+ log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, or -random <seed> 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");
for (auto module : design->selected_modules())
{
@@ -149,28 +233,103 @@ struct SetundefPass : public Pass {
if (!module->processes.empty())
log_error("The 'setundef' command can't operate in -undriven mode on modules with processes. Run 'proc' first.\n");
- SigMap sigmap(module);
- SigPool undriven_signals;
-
- for (auto &it : module->wires_)
- undriven_signals.add(sigmap(it.second));
-
- for (auto &it : module->wires_)
- if (it.second->port_input)
- undriven_signals.del(sigmap(it.second));
-
- CellTypes ct(design);
- 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))
- undriven_signals.del(sigmap(conn.second));
-
- RTLIL::SigSpec sig = undriven_signals.export_all();
- for (auto &c : sig.chunks()) {
- RTLIL::SigSpec bits;
- for (int i = 0; i < c.width; i++)
- bits.append(worker.next_bit());
- module->connect(RTLIL::SigSig(c, bits));
+ if (expose_mode)
+ {
+ SigMap sigmap(module);
+ dict<SigBit, bool> wire_drivers;
+ pool<SigBit> used_wires;
+ SigPool undriven_signals;
+
+ for (auto cell : module->cells())
+ for (auto &conn : cell->connections()) {
+ SigSpec sig = sigmap(conn.second);
+ if (cell->input(conn.first))
+ for (auto bit : sig)
+ if (bit.wire)
+ used_wires.insert(bit);
+ if (cell->output(conn.first))
+ for (int i = 0; i < GetSize(sig); i++)
+ if (sig[i].wire)
+ wire_drivers[sig[i]] = true;
+ }
+
+ for (auto wire : module->wires()) {
+ if (wire->port_input) {
+ SigSpec sig = sigmap(wire);
+ for (int i = 0; i < GetSize(sig); i++)
+ wire_drivers[sig[i]] = true;
+ }
+ if (wire->port_output) {
+ SigSpec sig = sigmap(wire);
+ for (auto bit : sig)
+ if (bit.wire)
+ used_wires.insert(bit);
+ }
+ }
+
+ pool<RTLIL::Wire*> undriven_wires;
+ for (auto bit : used_wires)
+ if (!wire_drivers.count(bit))
+ undriven_wires.insert(bit.wire);
+
+ for (auto &it : undriven_wires)
+ undriven_signals.add(sigmap(it));
+
+ for (auto &it : undriven_wires)
+ if (it->port_input)
+ undriven_signals.del(sigmap(it));
+
+ CellTypes ct(design);
+ 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))
+ undriven_signals.del(sigmap(conn.second));
+
+ RTLIL::SigSpec sig = undriven_signals.export_all();
+ for (auto &c : sig.chunks()) {
+ RTLIL::Wire * wire;
+ if (c.wire->width == c.width) {
+ wire = c.wire;
+ wire->port_input = true;
+ } else {
+ string name = c.wire->name.str() + "$[" + std::to_string(c.width + c.offset) + ":" + std::to_string(c.offset) + "]";
+ wire = add_wire(module, name, c.width, true, false);
+ module->connect(RTLIL::SigSig(c, wire));
+ }
+ log("Exposing undriven wire %s as input.\n", wire->name.c_str());
+ }
+ module->fixup_ports();
+ }
+ else
+ {
+ SigMap sigmap(module);
+ SigPool undriven_signals;
+
+ for (auto &it : module->wires_)
+ undriven_signals.add(sigmap(it.second));
+
+ for (auto &it : module->wires_)
+ if (it.second->port_input)
+ undriven_signals.del(sigmap(it.second));
+
+ CellTypes ct(design);
+ 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))
+ undriven_signals.del(sigmap(conn.second));
+
+ RTLIL::SigSpec sig = undriven_signals.export_all();
+ for (auto &c : sig.chunks()) {
+ RTLIL::SigSpec bits;
+ if (worker.next_bit_mode == MODE_ANYSEQ)
+ bits = module->Anyseq(NEW_ID, c.width);
+ else if (worker.next_bit_mode == MODE_ANYCONST)
+ bits = module->Anyconst(NEW_ID, c.width);
+ else
+ for (int i = 0; i < c.width; i++)
+ bits.append(worker.next_bit());
+ module->connect(RTLIL::SigSig(c, bits));
+ }
}
}
@@ -256,7 +415,7 @@ struct SetundefPass : public Pass {
module->rewrite_sigspecs(worker);
- if (worker.next_bit_mode == 2)
+ if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)
{
vector<SigSpec*> siglist;
siglist.swap(worker.siglist);
@@ -273,7 +432,10 @@ struct SetundefPass : public Pass {
width++;
if (width > 0) {
- sig.replace(cursor, module->Anyseq(NEW_ID, width));
+ if (worker.next_bit_mode == MODE_ANYSEQ)
+ sig.replace(cursor, module->Anyseq(NEW_ID, width));
+ else
+ sig.replace(cursor, module->Anyconst(NEW_ID, width));
cursor += width;
} else {
cursor++;
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index 56e1122bf..a48873244 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -573,7 +573,7 @@ struct ShowWorker
struct ShowPass : public Pass {
ShowPass() : Pass("show", "generate schematics using graphviz") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -584,6 +584,7 @@ struct ShowPass : public Pass {
log("\n");
log(" -viewer <viewer>\n");
log(" Run the specified command with the graphics file as parameter.\n");
+ log(" On Windows, this pauses yosys until the viewer exits.\n");
log("\n");
log(" -format <format>\n");
log(" Generate a graphics file in the specified format. Use 'dot' to just\n");
@@ -645,7 +646,7 @@ struct ShowPass : public Pass {
log(" do not add the module name as graph title to the dot file\n");
log("\n");
log("When no <format> is specified, 'dot' is used. When no <format> and <viewer> is\n");
- log("specified, 'xdot' is used to display the schematic.\n");
+ log("specified, 'xdot' is used to display the schematic (POSIX systems only).\n");
log("\n");
log("The generated output files are '~/.yosys_show.dot' and '~/.yosys_show.<format>',\n");
log("unless another prefix is specified using -prefix <prefix>.\n");
@@ -655,7 +656,7 @@ struct ShowPass : public Pass {
log("the 'show' command is executed.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Generating Graphviz representation of design.\n");
log_push();
@@ -817,14 +818,30 @@ struct ShowPass : public Pass {
log_cmd_error("Nothing there to show.\n");
if (format != "dot" && !format.empty()) {
- std::string cmd = stringf("dot -T%s '%s' > '%s.new' && mv '%s.new' '%s'", format.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str(), out_file.c_str());
+ #ifdef _WIN32
+ // system()/cmd.exe does not understand single quotes on Windows.
+ #define DOT_CMD "dot -T%s \"%s\" > \"%s.new\" && move \"%s.new\" \"%s\""
+ #else
+ #define DOT_CMD "dot -T%s '%s' > '%s.new' && mv '%s.new' '%s'"
+ #endif
+ 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 (run_command(cmd) != 0)
log_cmd_error("Shell command failed!\n");
}
if (!viewer_exe.empty()) {
- std::string cmd = stringf("%s '%s' &", viewer_exe.c_str(), out_file.c_str());
+ #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.
+ #define VIEW_CMD "%s \"%s\""
+ #else
+ #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");
diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc
index 7418ec4d2..bafafca4e 100644
--- a/passes/cmds/splice.cc
+++ b/passes/cmds/splice.cc
@@ -247,7 +247,7 @@ struct SpliceWorker
struct SplicePass : public Pass {
SplicePass() : Pass("splice", "create explicit splicing cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -288,7 +288,7 @@ struct SplicePass : public Pass {
log("by selected wires are rewired.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool sel_by_cell = false;
bool sel_by_wire = false;
diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc
index 5e37fc597..f5a1f17b3 100644
--- a/passes/cmds/splitnets.cc
+++ b/passes/cmds/splitnets.cc
@@ -87,7 +87,7 @@ struct SplitnetsWorker
struct SplitnetsPass : public Pass {
SplitnetsPass() : Pass("splitnets", "split up multi-bit nets") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -109,7 +109,7 @@ struct SplitnetsPass : public Pass {
log(" and split nets so that no driver drives only part of a net.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool flag_ports = false;
bool flag_driver = false;
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index e52a192db..54f4ea817 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -142,7 +142,7 @@ struct statdata_t
}
}
- void log_data()
+ void log_data(RTLIL::IdString mod_name, bool top_mod)
{
log(" Number of wires: %6d\n", num_wires);
log(" Number of wire bits: %6d\n", num_wire_bits);
@@ -163,7 +163,7 @@ struct statdata_t
if (area != 0) {
log("\n");
- log(" Chip area for this module: %f\n", area);
+ log(" Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area);
}
}
};
@@ -209,7 +209,7 @@ void read_liberty_cellarea(dict<IdString, double> &cell_area, string liberty_fil
struct StatPass : public Pass {
StatPass() : Pass("stat", "print some statistics") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -231,7 +231,7 @@ struct StatPass : public Pass {
log(" e.g. $add_8 for an 8 bit wide $add cell.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Printing statistics.\n");
@@ -275,7 +275,7 @@ struct StatPass : public Pass {
log("\n");
log("=== %s%s ===\n", RTLIL::id2cstr(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)");
log("\n");
- data.log_data();
+ data.log_data(mod->name, false);
}
if (top_mod != NULL && GetSize(mod_stat) > 1)
@@ -288,7 +288,7 @@ struct StatPass : public Pass {
statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0);
log("\n");
- data.log_data();
+ data.log_data(top_mod->name, true);
}
log("\n");
diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc
index b68c089e9..ff80f3859 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") { }
- virtual void help()
+ 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/subract INT from the -v setting for this command.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<FILE*> backup_log_files, files_to_close;
int backup_log_verbose_level = log_verbose_level;
diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc
index 56223610d..3c0eac8de 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool noautostop = false;
dict<IdString, pool<IdString>> stop_db;
diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc
index 1a5f873ff..f5305cde9 100644
--- a/passes/cmds/trace.cc
+++ b/passes/cmds/trace.cc
@@ -25,34 +25,34 @@ PRIVATE_NAMESPACE_BEGIN
struct TraceMonitor : public RTLIL::Monitor
{
- virtual void notify_module_add(RTLIL::Module *module) YS_OVERRIDE
+ void notify_module_add(RTLIL::Module *module) YS_OVERRIDE
{
log("#TRACE# Module add: %s\n", log_id(module));
}
- virtual void notify_module_del(RTLIL::Module *module) YS_OVERRIDE
+ void notify_module_del(RTLIL::Module *module) YS_OVERRIDE
{
log("#TRACE# Module delete: %s\n", log_id(module));
}
- virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_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));
}
- virtual void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) YS_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));
}
- virtual void notify_connect(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &sigsig_vec) YS_OVERRIDE
+ void notify_connect(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &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));
}
- virtual void notify_blackout(RTLIL::Module *module) YS_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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -95,4 +95,3 @@ struct TracePass : public Pass {
} TracePass;
PRIVATE_NAMESPACE_END
-
diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc
index 70892a945..9613b462b 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*)
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> 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 0494a724f..71599f46e 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, Design *design)
+ void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
{
bool try_mode = false;
diff --git a/passes/equiv/equiv_induct.cc b/passes/equiv/equiv_induct.cc
index c958c3de4..bcc68d6d2 100644
--- a/passes/equiv/equiv_induct.cc
+++ b/passes/equiv/equiv_induct.cc
@@ -162,7 +162,7 @@ struct EquivInductWorker
struct EquivInductPass : public Pass {
EquivInductPass() : Pass("equiv_induct", "proving $equiv cells using temporal induction") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, Design *design)
+ void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
{
int success_counter = 0;
bool model_undef = false;
diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc
index b20463777..b1f88d55e 100644
--- a/passes/equiv/equiv_make.cc
+++ b/passes/equiv/equiv_make.cc
@@ -390,7 +390,7 @@ struct EquivMakeWorker
struct EquivMakePass : public Pass {
EquivMakePass() : Pass("equiv_make", "prepare a circuit for equivalence checking") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -415,7 +415,7 @@ struct EquivMakePass : public Pass {
log("checking problem. Use 'miter -equiv' if you want to create a miter circuit.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 22c501763..135eaf145 100644
--- a/passes/equiv/equiv_mark.cc
+++ b/passes/equiv/equiv_mark.cc
@@ -204,7 +204,7 @@ struct EquivMarkWorker
struct EquivMarkPass : public Pass {
EquivMarkPass() : Pass("equiv_mark", "mark equivalence checking regions") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, Design *design)
+ void execute(std::vector<std::string> 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 eb2e5a171..e06f9515b 100644
--- a/passes/equiv/equiv_miter.cc
+++ b/passes/equiv/equiv_miter.cc
@@ -261,7 +261,7 @@ struct EquivMiterWorker
struct EquivMiterPass : public Pass {
EquivMiterPass() : Pass("equiv_miter", "extract miter from equiv circuit") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
EquivMiterWorker worker;
worker.ct.setup(design);
diff --git a/passes/equiv/equiv_purge.cc b/passes/equiv/equiv_purge.cc
index f8d3cd0af..18b3e7d36 100644
--- a/passes/equiv/equiv_purge.cc
+++ b/passes/equiv/equiv_purge.cc
@@ -176,7 +176,7 @@ struct EquivPurgeWorker
struct EquivPurgePass : public Pass {
EquivPurgePass() : Pass("equiv_purge", "purge equivalence checking module") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, Design *design)
+ void execute(std::vector<std::string> 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 770497a51..c5c28c7d9 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, Design *design)
+ void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
{
bool mode_gold = false;
bool mode_gate = false;
diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc
index e69e17ac6..c2fab26f2 100644
--- a/passes/equiv/equiv_simple.cc
+++ b/passes/equiv/equiv_simple.cc
@@ -273,7 +273,7 @@ struct EquivSimpleWorker
struct EquivSimplePass : public Pass {
EquivSimplePass() : Pass("equiv_simple", "try proving simple $equiv instances") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, Design *design)
+ void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
{
bool verbose = false, short_cones = false, model_undef = false, nogroup = false;
int success_counter = 0;
diff --git a/passes/equiv/equiv_status.cc b/passes/equiv/equiv_status.cc
index 7b9230b35..b4a93ccf5 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, Design *design)
+ void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
{
bool assert_mode = false;
int unproven_count = 0;
diff --git a/passes/equiv/equiv_struct.cc b/passes/equiv/equiv_struct.cc
index c4ced6a71..a7973fd04 100644
--- a/passes/equiv/equiv_struct.cc
+++ b/passes/equiv/equiv_struct.cc
@@ -283,7 +283,7 @@ struct EquivStructWorker
struct EquivStructPass : public Pass {
EquivStructPass() : Pass("equiv_struct", "structural equivalence checking") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -314,7 +314,7 @@ struct EquivStructPass : public Pass {
log(" maximum number of iterations to run before aborting\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, Design *design)
+ void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
{
pool<IdString> fwonly_cells({ "$equiv" });
bool mode_icells = false;
diff --git a/passes/fsm/fsm.cc b/passes/fsm/fsm.cc
index 997558b85..c5cb338ab 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 9fb5446e7..fc504e98c 100644
--- a/passes/fsm/fsm_detect.cc
+++ b/passes/fsm/fsm_detect.cc
@@ -245,7 +245,7 @@ static void detect_fsm(RTLIL::Wire *wire)
struct FsmDetectPass : public Pass {
FsmDetectPass() : Pass("fsm_detect", "finding FSMs in design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -261,7 +261,7 @@ struct FsmDetectPass : public Pass {
log("'fsm_encoding' attribute to \"none\".\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing FSM_DETECT pass (finding FSMs in design).\n");
extra_args(args, 1, design);
diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc
index 2c344a1c1..c34d0c15c 100644
--- a/passes/fsm/fsm_expand.cc
+++ b/passes/fsm/fsm_expand.cc
@@ -265,7 +265,7 @@ struct FsmExpand
struct FsmExpandPass : public Pass {
FsmExpandPass() : Pass("fsm_expand", "expand FSM cells by merging logic into it") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool full_mode = false;
diff --git a/passes/fsm/fsm_export.cc b/passes/fsm/fsm_export.cc
index 1cbfcfae8..8eb1872f0 100644
--- a/passes/fsm/fsm_export.cc
+++ b/passes/fsm/fsm_export.cc
@@ -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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
dict<RTLIL::IdString, RTLIL::Const>::iterator attr_it;
std::string arg;
diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc
index 8a4ee3f26..67551f673 100644
--- a/passes/fsm/fsm_extract.cc
+++ b/passes/fsm/fsm_extract.cc
@@ -401,7 +401,7 @@ static void extract_fsm(RTLIL::Wire *wire)
struct FsmExtractPass : public Pass {
FsmExtractPass() : Pass("fsm_extract", "extracting FSMs in design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -417,7 +417,7 @@ struct FsmExtractPass : public Pass {
log("'opt_clean' pass to eliminate this signal.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing FSM_EXTRACT pass (extracting FSM from design).\n");
extra_args(args, 1, design);
diff --git a/passes/fsm/fsm_info.cc b/passes/fsm/fsm_info.cc
index 2cc1a7d53..0548259ee 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -41,7 +41,7 @@ struct FsmInfoPass : public Pass {
log("pass so that this information is included in the synthesis log file.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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);
diff --git a/passes/fsm/fsm_map.cc b/passes/fsm/fsm_map.cc
index 3edaf84d2..90c958912 100644
--- a/passes/fsm/fsm_map.cc
+++ b/passes/fsm/fsm_map.cc
@@ -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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -331,7 +331,7 @@ struct FsmMapPass : public Pass {
log("This pass translates FSM cells to flip-flops and logic.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing FSM_MAP pass (mapping FSMs to basic logic).\n");
extra_args(args, 1, design);
diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc
index 5b1da44fc..3a6ac2746 100644
--- a/passes/fsm/fsm_opt.cc
+++ b/passes/fsm/fsm_opt.cc
@@ -323,7 +323,7 @@ PRIVATE_NAMESPACE_BEGIN
struct FsmOptPass : public Pass {
FsmOptPass() : Pass("fsm_opt", "optimize finite state machines") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -334,7 +334,7 @@ struct FsmOptPass : public Pass {
log("combination with the 'opt_clean' pass (see also 'help fsm').\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing FSM_OPT pass (simple optimizations of FSMs).\n");
extra_args(args, 1, design);
diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc
index e1bde728f..fa1ff48cc 100644
--- a/passes/fsm/fsm_recode.cc
+++ b/passes/fsm/fsm_recode.cc
@@ -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") { }
- virtual void help()
+ 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 <old_bitpattern> <new_bitpattern>\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
FILE *fm_set_fsm_file = NULL;
FILE *encfile = NULL;
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index 898763c64..5df69848e 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -18,6 +18,7 @@
*/
#include "kernel/yosys.h"
+#include "frontends/verific/verific.h"
#include <stdlib.h>
#include <stdio.h>
#include <set>
@@ -138,7 +139,7 @@ void generate(RTLIL::Design *design, const std::vector<std::string> &celltypes,
}
}
-bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, std::vector<std::string> &libdirs)
+bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, std::vector<std::string> &libdirs)
{
bool did_something = false;
std::map<RTLIL::Cell*, std::pair<int, int>> array_cells;
@@ -173,20 +174,24 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
for (auto &dir : libdirs)
{
- filename = dir + "/" + RTLIL::unescape_id(cell->type) + ".v";
- if (check_file_exists(filename)) {
- Frontend::frontend_call(design, NULL, filename, "verilog");
- goto loaded_module;
- }
+ static const vector<pair<string, string>> extensions_list =
+ {
+ {".v", "verilog"},
+ {".sv", "verilog -sv"},
+ {".il", "ilang"}
+ };
- filename = dir + "/" + RTLIL::unescape_id(cell->type) + ".il";
- if (check_file_exists(filename)) {
- Frontend::frontend_call(design, NULL, filename, "ilang");
- goto loaded_module;
+ for (auto &ext : extensions_list)
+ {
+ filename = dir + "/" + RTLIL::unescape_id(cell->type) + ext.first;
+ if (check_file_exists(filename)) {
+ Frontend::frontend_call(design, NULL, filename, ext.second);
+ goto loaded_module;
+ }
}
}
- if (flag_check && cell->type[0] != '$')
+ if ((flag_check || flag_simcheck) && cell->type[0] != '$')
log_error("Module `%s' referenced in module `%s' in cell `%s' is not part of the design.\n",
cell->type.c_str(), module->name.c_str(), cell->name.c_str());
continue;
@@ -196,7 +201,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str());
did_something = true;
} else
- if (flag_check)
+ if (flag_check || flag_simcheck)
{
RTLIL::Module *mod = design->module(cell->type);
for (auto &conn : cell->connections())
@@ -214,10 +219,14 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
log_id(cell->type), log_id(module), log_id(cell), log_id(param.first));
}
- if (cell->parameters.size() == 0)
+ if (design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) {
+ if (flag_simcheck)
+ log_error("Module `%s' referenced in module `%s' in cell `%s' is a blackbox module.\n",
+ cell->type.c_str(), module->name.c_str(), cell->name.c_str());
continue;
+ }
- if (design->modules_.at(cell->type)->get_bool_attribute("\\blackbox"))
+ if (cell->parameters.size() == 0)
continue;
RTLIL::Module *mod = design->modules_[cell->type];
@@ -250,7 +259,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
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->wires_.at(portname)->width;
- if (conn_size == port_size)
+ if (conn_size == port_size || conn_size == 0)
continue;
if (conn_size != port_size*num)
log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first));
@@ -334,7 +343,7 @@ int find_top_mod_score(Design *design, Module *module, dict<Module*, int> &db)
struct HierarchyPass : public Pass {
HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -350,6 +359,10 @@ struct HierarchyPass : public Pass {
log(" also check the design hierarchy. this generates an error when\n");
log(" an unknown module is used as cell type.\n");
log("\n");
+ log(" -simcheck\n");
+ log(" like -check, but also thow an error if blackbox modules are\n");
+ log(" instantiated, and throw an error if the design has no top module\n");
+ log("\n");
log(" -purge_lib\n");
log(" by default the hierarchy command will not remove library (blackbox)\n");
log(" modules. use this option to also remove unused blackbox modules.\n");
@@ -401,13 +414,15 @@ struct HierarchyPass : public Pass {
log("in the current design.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing HIERARCHY pass (managing design hierarchy).\n");
bool flag_check = false;
+ bool flag_simcheck = false;
bool purge_lib = false;
RTLIL::Module *top_mod = NULL;
+ std::string load_top_mod;
std::vector<std::string> libdirs;
bool auto_top_mode = false;
@@ -421,7 +436,7 @@ struct HierarchyPass : public Pass {
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
- if (args[argidx] == "-generate" && !flag_check && !top_mod) {
+ if (args[argidx] == "-generate" && !flag_check && !flag_simcheck && !top_mod) {
generate_mode = true;
log("Entering generate mode.\n");
while (++argidx < args.size()) {
@@ -464,6 +479,10 @@ struct HierarchyPass : public Pass {
flag_check = true;
continue;
}
+ if (args[argidx] == "-simcheck") {
+ flag_simcheck = true;
+ continue;
+ }
if (args[argidx] == "-purge_lib") {
purge_lib = true;
continue;
@@ -494,7 +513,7 @@ struct HierarchyPass : public Pass {
top_mod = design->modules_.count(RTLIL::escape_id(args[argidx])) ? design->modules_.at(RTLIL::escape_id(args[argidx])) : NULL;
}
if (top_mod == NULL)
- log_cmd_error("Module `%s' not found!\n", args[argidx].c_str());
+ load_top_mod = args[argidx];
continue;
}
if (args[argidx] == "-auto-top") {
@@ -505,6 +524,22 @@ struct HierarchyPass : public Pass {
}
extra_args(args, argidx, design, false);
+ if (!load_top_mod.empty()) {
+#ifdef YOSYS_ENABLE_VERIFIC
+ if (verific_import_pending) {
+ verific_import(design, load_top_mod);
+ top_mod = design->module(RTLIL::escape_id(load_top_mod));
+ }
+#endif
+ if (top_mod == NULL)
+ log_cmd_error("Module `%s' not found!\n", load_top_mod.c_str());
+ } else {
+#ifdef YOSYS_ENABLE_VERIFIC
+ if (verific_import_pending)
+ verific_import(design);
+#endif
+ }
+
if (generate_mode) {
generate(design, generate_cells, generate_ports);
return;
@@ -530,6 +565,9 @@ struct HierarchyPass : public Pass {
log("Automatically selected %s as design top module.\n", log_id(top_mod));
}
+ if (flag_simcheck && top_mod == nullptr)
+ log_error("Design has no top module.\n");
+
bool did_something = true;
while (did_something)
{
@@ -545,7 +583,7 @@ struct HierarchyPass : public Pass {
}
for (auto module : used_modules) {
- if (expand_module(design, module, flag_check, libdirs))
+ if (expand_module(design, module, flag_check, flag_simcheck, libdirs))
did_something = true;
}
}
diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc
index e9ee4eef9..ec242aa1f 100644
--- a/passes/hierarchy/submod.cc
+++ b/passes/hierarchy/submod.cc
@@ -269,7 +269,7 @@ struct SubmodWorker
struct SubmodPass : public Pass {
SubmodPass() : Pass("submod", "moving part of a module to a new submodule") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -297,7 +297,7 @@ struct SubmodPass : public Pass {
log("with -copy to not modify the source module.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing SUBMOD pass (moving cells to submodules as requested).\n");
log_push();
diff --git a/passes/hierarchy/uniquify.cc b/passes/hierarchy/uniquify.cc
index 1da0870f6..c88ecd82e 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing UNIQUIFY pass (creating unique copies of modules).\n");
diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc
index 947d598be..712bc2537 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -48,7 +48,7 @@ struct MemoryPass : public Pass {
log("or multiport memory blocks if called with the -nomap option.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 a7f9cf382..e8552bbcf 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -1120,7 +1120,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
struct MemoryBramPass : public Pass {
MemoryBramPass() : Pass("memory_bram", "map memories to block rams") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1210,7 +1210,7 @@ struct MemoryBramPass : public Pass {
log("the data bits to accommodate the enable pattern of port A.\n");
log("\n");
}
- virtual void execute(vector<string> args, Design *design)
+ void execute(vector<string> args, Design *design) YS_OVERRIDE
{
rules_t rules;
diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc
index ab66e3fb8..70d98713c 100644
--- a/passes/memory/memory_collect.cc
+++ b/passes/memory/memory_collect.cc
@@ -246,7 +246,7 @@ static void handle_module(Design *design, Module *module)
struct MemoryCollectPass : public Pass {
MemoryCollectPass() : Pass("memory_collect", "creating multi-port memory cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -256,7 +256,7 @@ struct MemoryCollectPass : public Pass {
log("memory cells.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
log_header(design, "Executing MEMORY_COLLECT pass (generating $mem cells).\n");
extra_args(args, 1, design);
for (auto &mod_it : design->modules_)
diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc
index 40691d160..32df19174 100644
--- a/passes/memory/memory_dff.cc
+++ b/passes/memory/memory_dff.cc
@@ -33,8 +33,20 @@ struct MemoryDffWorker
dict<SigBit, int> sigbit_users_count;
dict<SigSpec, Cell*> mux_cells_a, mux_cells_b;
pool<Cell*> forward_merged_dffs, candidate_dffs;
+ pool<SigBit> init_bits;
- MemoryDffWorker(Module *module) : module(module), sigmap(module) { }
+ MemoryDffWorker(Module *module) : module(module), sigmap(module)
+ {
+ for (auto wire : module->wires()) {
+ if (wire->attributes.count("\\init") == 0)
+ continue;
+ SigSpec sig = sigmap(wire);
+ Const initval = wire->attributes.count("\\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]);
+ }
+ }
bool find_sig_before_dff(RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity, bool after = false)
{
@@ -45,6 +57,9 @@ struct MemoryDffWorker
if (bit.wire == NULL)
continue;
+ if (!after && init_bits.count(sigmap(bit)))
+ return false;
+
for (auto cell : dff_cells)
{
if (after && forward_merged_dffs.count(cell))
@@ -72,6 +87,9 @@ struct MemoryDffWorker
if (d.size() != 1)
continue;
+ if (after && init_bits.count(d))
+ return false;
+
bit = d;
clk = this_clk;
clk_polarity = this_clk_polarity;
@@ -265,7 +283,7 @@ struct MemoryDffWorker
struct MemoryDffPass : public Pass {
MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memories") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -279,7 +297,7 @@ struct MemoryDffPass : public Pass {
log(" do not merge registers on read ports\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 bffeec857..a0b808e56 100644
--- a/passes/memory/memory_map.cc
+++ b/passes/memory/memory_map.cc
@@ -352,7 +352,7 @@ struct MemoryMapWorker
struct MemoryMapPass : public Pass {
MemoryMapPass() : Pass("memory_map", "translate multiport memories to basic cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -362,7 +362,7 @@ struct MemoryMapPass : public Pass {
log("pass to word-wide DFFs and address decoders.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
log_header(design, "Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n");
extra_args(args, 1, design);
for (auto mod : design->selected_modules())
diff --git a/passes/memory/memory_memx.cc b/passes/memory/memory_memx.cc
index 2b02e2490..958370164 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ void execute(std::vector<std::string> 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);
diff --git a/passes/memory/memory_nordff.cc b/passes/memory/memory_nordff.cc
index 5f87e8b79..ba0361c0f 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing MEMORY_NORDFF pass (extracting $dff cells from $mem).\n");
@@ -61,49 +61,59 @@ struct MemoryNordffPass : public Pass {
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++)
{
bool clk_enable = rd_clk_enable[i] == State::S1;
- if (!clk_enable)
- continue;
+ if (clk_enable)
+ {
+ bool clk_polarity = cell->getParam("\\RD_CLK_POLARITY")[i] == State::S1;
+ bool transparent = cell->getParam("\\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("\\RD_CLK")[i] ;
+ SigSpec en = cell->getPort("\\RD_EN")[i];
+ Cell *c;
- SigSpec clk = cell->getPort("\\RD_CLK")[i] ;
- SigSpec en = cell->getPort("\\RD_EN")[i];
- Cell *c;
+ if (transparent)
+ {
+ SigSpec sig_q = module->addWire(NEW_ID, abits);
+ SigSpec sig_d = rd_addr.extract(abits * i, abits);
+ rd_addr.replace(abits * i, sig_q);
+ if (en != State::S1)
+ sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
+ c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
+ }
+ else
+ {
+ SigSpec sig_d = module->addWire(NEW_ID, width);
+ SigSpec sig_q = rd_data.extract(width * i, width);
+ rd_data.replace(width *i, sig_d);
+ if (en != State::S1)
+ sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
+ c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
+ }
- if (transparent)
- {
- SigSpec sig_q = module->addWire(NEW_ID, abits);
- SigSpec sig_d = rd_addr.extract(abits * i, abits);
- rd_addr.replace(abits * i, sig_q);
- if (en != State::S1)
- sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
- c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
- }
- else
- {
- SigSpec sig_d = module->addWire(NEW_ID, width);
- SigSpec sig_q = rd_data.extract(width * i, width);
- rd_data.replace(width *i, sig_d);
- if (en != State::S1)
- sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
- c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
+ log("Extracted %s FF from read port %d of %s.%s: %s\n", transparent ? "addr" : "data",
+ i, log_id(module), log_id(cell), log_id(c));
}
- log("Extracted %s FF from read port %d of %s.%s: %s\n", transparent ? "addr" : "data",
- i, log_id(module), log_id(cell), log_id(c));
+ rd_en[i] = State::S1;
+ rd_clk[i] = State::S0;
rd_clk_enable[i] = State::S0;
+ rd_clk_polarity[i] = State::S1;
}
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 ca09ac52c..172afe0cb 100644
--- a/passes/memory/memory_share.cc
+++ b/passes/memory/memory_share.cc
@@ -726,7 +726,7 @@ struct MemoryShareWorker
struct MemorySharePass : public Pass {
MemorySharePass() : Pass("memory_share", "consolidate memory ports") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -752,7 +752,7 @@ struct MemorySharePass : public Pass {
log("optimizations) such as \"share\" and \"opt_merge\".\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
log_header(design, "Executing MEMORY_SHARE pass (consolidating $memrd/$memwr cells).\n");
extra_args(args, 1, design);
for (auto module : design->selected_modules())
diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc
index a0fc31b5e..49ec66792 100644
--- a/passes/memory/memory_unpack.cc
+++ b/passes/memory/memory_unpack.cc
@@ -127,7 +127,7 @@ void handle_module(RTLIL::Design *design, RTLIL::Module *module)
struct MemoryUnpackPass : public Pass {
MemoryUnpackPass() : Pass("memory_unpack", "unpack multi-port memory cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -137,7 +137,7 @@ struct MemoryUnpackPass : public Pass {
log("$memwr cells. It is the counterpart to the memory_collect pass.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ void execute(std::vector<std::string> 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 &mod_it : design->modules_)
diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc
index 021c1a03f..a4aca2fee 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -63,7 +63,7 @@ struct OptPass : public Pass {
log("\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string opt_clean_args;
std::string opt_expr_args;
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index 25d462ada..c3b13acaf 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -442,7 +442,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
struct OptCleanPass : public Pass {
OptCleanPass() : Pass("opt_clean", "remove unused cells and wires") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -459,7 +459,7 @@ struct OptCleanPass : public Pass {
log(" also remove internal nets if they have a public name\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool purge_mode = false;
@@ -505,7 +505,7 @@ struct OptCleanPass : public Pass {
struct CleanPass : public Pass {
CleanPass() : Pass("clean", "remove unused cells and wires") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -520,7 +520,7 @@ struct CleanPass : public Pass {
log("in -purge mode between the commands.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool purge_mode = false;
diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc
index f2af1cb93..1699a6454 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 45331aa0b..0ba233c62 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -718,6 +718,23 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
+ if (cell->type == "$_TBUF_" || cell->type == "$tribuf") {
+ RTLIL::SigSpec input = cell->getPort(cell->type == "$_TBUF_" ? "\\E" : "\\EN");
+ RTLIL::SigSpec a = cell->getPort("\\A");
+ assign_map.apply(input);
+ assign_map.apply(a);
+ if (input == State::S1)
+ ACTION_DO("\\Y", cell->getPort("\\A"));
+ if (input == State::S0 && !a.is_fully_undef()) {
+ cover("opt.opt_expr.action_" S__LINE__);
+ log("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
+ cell->type.c_str(), cell->name.c_str(), module->name.c_str());
+ cell->setPort("\\A", SigSpec(State::Sx, GetSize(a)));
+ did_something = true;
+ goto next_cell;
+ }
+ }
+
if (cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex")
{
RTLIL::SigSpec a = cell->getPort("\\A");
@@ -1453,7 +1470,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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1487,7 +1504,7 @@ struct OptExprPass : public Pass {
log(" replaced by 'a'. the -keepdc option disables all such optimizations.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool mux_undef = false;
bool mux_bool = false;
diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc
index 2aeb514e4..eedf88904 100644
--- a/passes/opt/opt_merge.cc
+++ b/passes/opt/opt_merge.cc
@@ -341,7 +341,7 @@ struct OptMergeWorker
struct OptMergePass : public Pass {
OptMergePass() : Pass("opt_merge", "consolidate identical cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -357,7 +357,7 @@ struct OptMergePass : public Pass {
log(" Operate on all cell types, not just built-in types.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 f5ddc2af9..87c7ce9b2 100644
--- a/passes/opt/opt_muxtree.cc
+++ b/passes/opt/opt_muxtree.cc
@@ -449,7 +449,7 @@ struct OptMuxtreeWorker
struct OptMuxtreePass : public Pass {
OptMuxtreePass() : Pass("opt_muxtree", "eliminate dead trees in multiplexer trees") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -462,7 +462,7 @@ struct OptMuxtreePass : public Pass {
log("This pass only operates on completely selected modules without processes.\n");
log("\n");
}
- virtual void execute(vector<std::string> args, RTLIL::Design *design)
+ void execute(vector<std::string> 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 eb9d02ad5..d99f1ca6a 100644
--- a/passes/opt/opt_reduce.cc
+++ b/passes/opt/opt_reduce.cc
@@ -329,7 +329,7 @@ struct OptReduceWorker
struct OptReducePass : public Pass {
OptReducePass() : Pass("opt_reduce", "simplify large MUXes and AND/OR gates") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -350,7 +350,7 @@ struct OptReducePass : public Pass {
log(" alias for -fine\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 b5edb357b..5880254c1 100644
--- a/passes/opt/opt_rmdff.cc
+++ b/passes/opt/opt_rmdff.cc
@@ -399,7 +399,7 @@ delete_dff:
struct OptRmdffPass : public Pass {
OptRmdffPass() : Pass("opt_rmdff", "remove DFFs with constant inputs") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -409,7 +409,7 @@ struct OptRmdffPass : public Pass {
log("a constant driver.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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");
diff --git a/passes/opt/rmports.cc b/passes/opt/rmports.cc
index 756be7473..fc1596ebf 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 22914eaa7..b80280829 100644
--- a/passes/opt/share.cc
+++ b/passes/opt/share.cc
@@ -1421,7 +1421,7 @@ struct ShareWorker
struct SharePass : public Pass {
SharePass() : Pass("share", "perform sat-based resource sharing") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1453,7 +1453,7 @@ struct SharePass : public Pass {
log(" Only perform the first N merges, then stop. This is useful for debugging.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
ShareWorkerConfig config;
diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc
index 07503fbb3..0164f58d6 100644
--- a/passes/opt/wreduce.cc
+++ b/passes/opt/wreduce.cc
@@ -353,7 +353,7 @@ struct WreduceWorker
struct WreducePass : public Pass {
WreducePass() : Pass("wreduce", "reduce the word size of operations if possible") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -373,7 +373,7 @@ struct WreducePass : public Pass {
log(" flows that use the 'memory_memx' pass.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, Design *design)
+ void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
{
WreduceConfig config;
bool opt_memx = false;
diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc
index d5366f266..ef7cb0f71 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -57,7 +57,7 @@ struct ProcPass : public Pass {
log(" executed in -ifx mode.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 216b00ddd..b69eba3f9 100644
--- a/passes/proc/proc_arst.cc
+++ b/passes/proc/proc_arst.cc
@@ -203,7 +203,7 @@ restart_proc_arst:
struct ProcArstPass : public Pass {
ProcArstPass() : Pass("proc_arst", "detect asynchronous resets") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string global_arst;
bool global_arst_neg = false;
diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc
index 7dbabc211..b9e43d1db 100644
--- a/passes/proc/proc_clean.cc
+++ b/passes/proc/proc_clean.cc
@@ -143,7 +143,7 @@ void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count)
struct ProcCleanPass : public Pass {
ProcCleanPass() : Pass("proc_clean", "remove empty parts of processes") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -153,7 +153,7 @@ struct ProcCleanPass : public Pass {
log("if it contains only empty structures.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
int total_count = 0;
log_header(design, "Executing PROC_CLEAN pass (remove empty switches from decision trees).\n");
diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc
index f732baa17..519d35cd6 100644
--- a/passes/proc/proc_dff.cc
+++ b/passes/proc/proc_dff.cc
@@ -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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 15200ec12..d9d5dfbed 100644
--- a/passes/proc/proc_dlatch.cc
+++ b/passes/proc/proc_dlatch.cc
@@ -422,7 +422,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
struct ProcDlatchPass : public Pass {
ProcDlatchPass() : Pass("proc_dlatch", "extract latches from processes") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -432,7 +432,7 @@ struct ProcDlatchPass : public Pass {
log("d-type latches.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 0c8fb83dc..e2dc07e53 100644
--- a/passes/proc/proc_init.cc
+++ b/passes/proc/proc_init.cc
@@ -102,7 +102,7 @@ void proc_init(RTLIL::Module *mod, RTLIL::Process *proc)
struct ProcInitPass : public Pass {
ProcInitPass() : Pass("proc_init", "convert initial block to init attributes") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -113,7 +113,7 @@ struct ProcInitPass : public Pass {
log("respective wire.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 57e131ca5..1329c1fef 100644
--- a/passes/proc/proc_mux.cc
+++ b/passes/proc/proc_mux.cc
@@ -382,7 +382,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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -396,7 +396,7 @@ struct ProcMuxPass : public Pass {
log(" 'case' expressions and 'if' conditions.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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_rmdead.cc b/passes/proc/proc_rmdead.cc
index 5672fb475..7c334e661 100644
--- a/passes/proc/proc_rmdead.cc
+++ b/passes/proc/proc_rmdead.cc
@@ -65,7 +65,7 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter)
struct ProcRmdeadPass : public Pass {
ProcRmdeadPass() : Pass("proc_rmdead", "eliminate dead trees in decision trees") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -74,7 +74,7 @@ struct ProcRmdeadPass : public Pass {
log("This pass identifies unreachable branches in decision trees and removes them.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 4fcce2fad..8ab0280c0 100644
--- a/passes/sat/Makefile.inc
+++ b/passes/sat/Makefile.inc
@@ -7,4 +7,5 @@ OBJS += passes/sat/miter.o
OBJS += passes/sat/expose.o
OBJS += passes/sat/assertpmux.o
OBJS += passes/sat/clk2fflogic.o
+OBJS += passes/sat/async2sync.o
diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc
index 63a907671..509cb0ba9 100644
--- a/passes/sat/assertpmux.cc
+++ b/passes/sat/assertpmux.cc
@@ -181,7 +181,7 @@ struct AssertpmuxWorker
struct AssertpmuxPass : public Pass {
AssertpmuxPass() : Pass("assertpmux", "convert internal signals to module ports") { }
- virtual void help()
+ 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 constrained and check the $pmux condition always.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool flag_noinit = false;
bool flag_always = false;
diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc
new file mode 100644
index 000000000..c92db7118
--- /dev/null
+++ b/passes/sat/async2sync.cc
@@ -0,0 +1,147 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct Async2syncPass : public Pass {
+ Async2syncPass() : Pass("async2sync", "convert async FF inputs to sync circuits") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" async2sync [options] [selection]\n");
+ log("\n");
+ log("This command replaces async FF inputs with sync circuits emulating the same\n");
+ log("behavior for when the async signals are actually synchronized to the clock.\n");
+ log("\n");
+ log("This pass assumes negative hold time for the async FF inputs. For example when\n");
+ log("a reset deasserts with the clock edge, then the FF output will still drive the\n");
+ log("reset value in the next cycle regardless of the data-in value at the time of\n");
+ log("the clock edge.\n");
+ log("\n");
+ log("Currently only $adff cells are supported by this pass.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ // bool flag_noinit = false;
+
+ log_header(design, "Executing ASYNC2SYNC pass.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-noinit") {
+ // flag_noinit = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ {
+ SigMap sigmap(module);
+ dict<SigBit, State> initbits;
+ pool<SigBit> del_initbits;
+
+ for (auto wire : module->wires())
+ if (wire->attributes.count("\\init") > 0)
+ {
+ Const initval = wire->attributes.at("\\init");
+ SigSpec initsig = sigmap(wire);
+
+ for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++)
+ if (initval[i] == State::S0 || initval[i] == State::S1)
+ initbits[initsig[i]] = initval[i];
+ }
+
+ for (auto cell : vector<Cell*>(module->selected_cells()))
+ {
+ if (cell->type.in("$adff"))
+ {
+ // 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("\\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),
+ log_signal(sig_arst), log_signal(sig_d), log_signal(sig_q));
+
+ Const init_val;
+ for (int i = 0; i < GetSize(sig_q); i++) {
+ SigBit bit = sigmap(sig_q[i]);
+ init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx);
+ del_initbits.insert(bit);
+ }
+
+ Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d));
+ Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q));
+ new_q->attributes["\\init"] = init_val;
+
+ if (arst_pol) {
+ module->addMux(NEW_ID, sig_d, arst_val, sig_arst, new_d);
+ module->addMux(NEW_ID, new_q, arst_val, sig_arst, sig_q);
+ } else {
+ module->addMux(NEW_ID, arst_val, sig_d, sig_arst, new_d);
+ module->addMux(NEW_ID, arst_val, new_q, sig_arst, sig_q);
+ }
+
+ 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;
+ }
+ }
+
+ for (auto wire : module->wires())
+ if (wire->attributes.count("\\init") > 0)
+ {
+ bool delete_initattr = true;
+ Const initval = wire->attributes.at("\\init");
+ SigSpec initsig = sigmap(wire);
+
+ for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++)
+ if (del_initbits.count(initsig[i]) > 0)
+ initval[i] = State::Sx;
+ else if (initval[i] != State::Sx)
+ delete_initattr = false;
+
+ if (delete_initattr)
+ wire->attributes.erase("\\init");
+ else
+ wire->attributes.at("\\init") = initval;
+ }
+ }
+ }
+} Async2syncPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc
index 736c6f571..49ec795d3 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
// bool flag_noinit = false;
diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc
index 09f69cc5c..008cd2dfa 100644
--- a/passes/sat/eval.cc
+++ b/passes/sat/eval.cc
@@ -360,7 +360,7 @@ struct VlogHammerReporter
struct EvalPass : public Pass {
EvalPass() : Pass("eval", "evaluate the circuit given an input") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -383,7 +383,7 @@ struct EvalPass : public Pass {
log(" then all output ports of the current module are used.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<std::pair<std::string, std::string>> sets;
std::vector<std::string> shows, tables;
diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc
index 9427547f3..809345486 100644
--- a/passes/sat/expose.cc
+++ b/passes/sat/expose.cc
@@ -220,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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -236,6 +236,10 @@ struct ExposePass : public Pass {
log(" when exposing a wire, create an input/output pair and cut the internal\n");
log(" signal path at that wire.\n");
log("\n");
+ log(" -input\n");
+ log(" when exposing a wire, create an input port and disconnect the internal\n");
+ log(" driver.\n");
+ log("\n");
log(" -shared\n");
log(" only expose those signals that are shared among the selected modules.\n");
log(" this is useful for preparing modules for equivalence checking.\n");
@@ -253,12 +257,13 @@ struct ExposePass : public Pass {
log(" designator for the exposed signal.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool flag_shared = false;
bool flag_evert = false;
bool flag_dff = false;
bool flag_cut = false;
+ bool flag_input = false;
bool flag_evert_dff = false;
std::string sep = ".";
@@ -279,10 +284,14 @@ struct ExposePass : public Pass {
flag_dff = true;
continue;
}
- if (args[argidx] == "-cut") {
+ if (args[argidx] == "-cut" && !flag_input) {
flag_cut = true;
continue;
}
+ if (args[argidx] == "-input" && !flag_cut) {
+ flag_input = true;
+ continue;
+ }
if (args[argidx] == "-evert-dff") {
flag_evert_dff = true;
continue;
@@ -464,16 +473,42 @@ struct ExposePass : public Pass {
continue;
}
- 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_input)
+ {
+ 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 (!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) {
+ 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_cut) {
- 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 &it : module->cells_) {
+ if (!ct.cell_known(it.second->type))
+ continue;
+ for (auto &conn : it.second->connections_)
+ if (ct.cell_output(it.second->type, conn.first))
+ conn.second = out_to_in_map(sigmap(conn.second));
}
+
+ for (auto &conn : module->connections_)
+ conn.first = out_to_in_map(sigmap(conn.first));
}
if (flag_cut)
diff --git a/passes/sat/freduce.cc b/passes/sat/freduce.cc
index a3028bfce..f29631639 100644
--- a/passes/sat/freduce.cc
+++ b/passes/sat/freduce.cc
@@ -760,7 +760,7 @@ struct FreduceWorker
struct FreducePass : public Pass {
FreducePass() : Pass("freduce", "perform functional reduction") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
reduce_counter = 0;
reduce_stop_at = 0;
diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc
index 9e150b60c..d37f1b126 100644
--- a/passes/sat/miter.cc
+++ b/passes/sat/miter.cc
@@ -358,7 +358,7 @@ void create_miter_assert(struct Pass *that, std::vector<std::string> args, RTLIL
struct MiterPass : public Pass {
MiterPass() : Pass("miter", "automatically create a miter circuit") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -402,7 +402,7 @@ struct MiterPass : public Pass {
log(" call 'flatten; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
if (args.size() > 1 && args[1] == "-equiv") {
create_miter_equiv(this, args, design);
diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc
index a6ac7afd4..695a03e15 100644
--- a/passes/sat/sat.cc
+++ b/passes/sat/sat.cc
@@ -691,7 +691,6 @@ struct SatHelper
// VCD has some limits on internal (non-display) identifier names, so make legal ones
std::map<std::string, std::string> vcdnames;
- fprintf(f, "$timescale 1ns\n"); // arbitrary time scale since actual clock period is unknown/unimportant
fprintf(f, "$scope module %s $end\n", module->name.c_str());
for (auto &info : modelInfo)
{
@@ -891,7 +890,7 @@ void print_qed()
struct SatPass : public Pass {
SatPass() : Pass("sat", "solve a SAT problem in the circuit") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1058,7 +1057,7 @@ struct SatPass : public Pass {
log(" Like -falsify but do not return an error for timeouts.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<std::pair<std::string, std::string>> sets, sets_init, prove, prove_x;
std::map<int, std::vector<std::pair<std::string, std::string>>> sets_at;
diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc
index b49c12529..53e248adf 100644
--- a/passes/sat/sim.cc
+++ b/passes/sat/sim.cc
@@ -745,7 +745,7 @@ struct SimWorker : SimShared
struct SimPass : public Pass {
SimPass() : Pass("sim", "simulate the circuit") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -778,7 +778,7 @@ struct SimPass : public Pass {
log(" number of cycles to simulate (default: 20)\n");
log("\n");
log(" -a\n");
- log(" include all nets in VCD output, nut just those with public names\n");
+ log(" include all nets in VCD output, not just those with public names\n");
log("\n");
log(" -w\n");
log(" writeback mode: use final simulation state as new init state\n");
@@ -787,7 +787,7 @@ struct SimPass : public Pass {
log(" enable debug output\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
SimWorker worker;
int numcycles = 20;
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 140a9f892..4faa0ab00 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -35,6 +35,7 @@ OBJS += passes/techmap/insbuf.o
OBJS += passes/techmap/attrmvcp.o
OBJS += passes/techmap/attrmap.o
OBJS += passes/techmap/zinit.o
+OBJS += passes/techmap/dff2dffs.o
endif
GENFILES += passes/techmap/techmap.inc
@@ -57,4 +58,3 @@ yosys-filterlib$(EXE): passes/techmap/filterlib.o
$(Q) mkdir -p $(dir $@)
$(P) $(LD) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS)
endif
-
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index be86f642a..d2d15a4a9 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -60,6 +60,10 @@
#include "frontends/blif/blifparse.h"
+#ifdef YOSYS_LINK_ABC
+extern "C" int Abc_RealMain(int argc, char *argv[]);
+#endif
+
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -546,11 +550,13 @@ std::string replace_tempdir(std::string text, std::string tempdir_name, bool sho
}
std::string selfdir_name = proc_self_dirname();
- while (1) {
- size_t pos = text.find(selfdir_name);
- if (pos == std::string::npos)
- break;
- text = text.substr(0, pos) + "<yosys-exe-dir>/" + text.substr(pos + GetSize(selfdir_name));
+ if (selfdir_name != "/") {
+ while (1) {
+ size_t pos = text.find(selfdir_name);
+ if (pos == std::string::npos)
+ break;
+ text = text.substr(0, pos) + "<yosys-exe-dir>/" + text.substr(pos + GetSize(selfdir_name));
+ }
}
return text;
@@ -943,8 +949,24 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
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
abc_output_filter filt(tempdir_name, show_tempdir);
int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1));
+#else
+ // These needs to be mutable, supposedly due to getopt
+ char *abc_argv[5];
+ string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str());
+ abc_argv[0] = strdup(exe_file.c_str());
+ abc_argv[1] = strdup("-s");
+ abc_argv[2] = strdup("-f");
+ abc_argv[3] = strdup(tmp_script_name.c_str());
+ abc_argv[4] = 0;
+ int ret = Abc_RealMain(4, abc_argv);
+ free(abc_argv[0]);
+ free(abc_argv[1]);
+ free(abc_argv[2]);
+ free(abc_argv[3]);
+#endif
if (ret != 0)
log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
@@ -1226,7 +1248,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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1388,13 +1410,17 @@ struct AbcPass : public Pass {
log("When neither -liberty nor -lut is used, the Yosys standard cell library is\n");
log("loaded into ABC before the ABC script is executed.\n");
log("\n");
- log("This pass does not operate on modules with unprocessed processes in it.\n");
- log("(I.e. the 'proc' pass should be used first to convert processes to netlists.)\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 the 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ABC pass (technology mapping using ABC).\n");
log_push();
diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc
index b9ac7aded..35df2ff79 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
log("\n");
log(" aigmap [options] [selection]\n");
@@ -37,7 +37,7 @@ struct AigmapPass : public Pass {
log(" Enable creation of $_NAND_ cells\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool nand_mode = false;
diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc
index 95be7ab3b..dc7d416b0 100644
--- a/passes/techmap/alumacc.cc
+++ b/passes/techmap/alumacc.cc
@@ -539,7 +539,7 @@ struct AlumaccWorker
struct AlumaccPass : public Pass {
AlumaccPass() : Pass("alumacc", "extract ALU and MACC cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -549,7 +549,7 @@ struct AlumaccPass : public Pass {
log("and $macc cells.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 dec81d216..0b5576b06 100644
--- a/passes/techmap/attrmap.cc
+++ b/passes/techmap/attrmap.cc
@@ -81,7 +81,7 @@ struct AttrmapAction {
struct AttrmapTocase : AttrmapAction {
string name;
- virtual bool apply(IdString &id, Const&) {
+ 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;
- virtual bool apply(IdString &id, Const&) {
+ 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;
- virtual bool apply(IdString &id, Const &val) {
+ 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);
@@ -112,7 +112,7 @@ struct AttrmapMap : AttrmapAction {
struct AttrmapRemove : AttrmapAction {
string name, value;
- virtual bool apply(IdString &id, Const &val) {
+ bool apply(IdString &id, Const &val) YS_OVERRIDE {
return !(match_name(name, id) && match_value(value, val));
}
};
@@ -144,7 +144,7 @@ void attrmap_apply(string objname, vector<std::unique_ptr<AttrmapAction>> &actio
struct AttrmapPass : public Pass {
AttrmapPass() : Pass("attrmap", "renaming attributes") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -179,7 +179,7 @@ struct AttrmapPass : public Pass {
log(" -imap keep=\"false\" keep=0 -remove keep=0\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ATTRMAP pass (move or copy attributes).\n");
diff --git a/passes/techmap/attrmvcp.cc b/passes/techmap/attrmvcp.cc
index 1537def00..e59aa6518 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ATTRMVCP pass (move or copy attributes).\n");
diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc
index ed4e45762..9f0c7bf67 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing DEMINOUT pass (demote inout ports to input or output).\n");
@@ -57,7 +57,7 @@ struct DeminoutPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- pool<SigBit> bits_written, bits_used, bits_inout;
+ pool<SigBit> bits_written, bits_used, bits_inout, bits_tribuf;
dict<SigBit, int> bits_numports;
for (auto wire : module->wires())
@@ -82,6 +82,25 @@ struct DeminoutPass : public Pass {
if (cellport_in)
for (auto bit : sigmap(conn.second))
bits_used.insert(bit);
+
+ if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_"))
+ {
+ bool tribuf = (cell->type == "$_TBUF_");
+
+ if (!tribuf) {
+ for (auto &c : cell->connections()) {
+ if (!c.first.in("\\A", "\\B"))
+ continue;
+ for (auto b : sigmap(c.second))
+ if (b == State::Sz)
+ tribuf = true;
+ }
+ }
+
+ if (tribuf)
+ for (auto bit : sigmap(conn.second))
+ bits_tribuf.insert(bit);
+ }
}
for (auto wire : module->selected_wires())
@@ -95,10 +114,15 @@ struct DeminoutPass : public Pass {
if (bits_numports[bit] > 1 || bits_inout.count(bit))
new_input = true, new_output = true;
- if (bits_written.count(bit))
+ if (bits_written.count(bit)) {
new_output = true;
- else if (bits_used.count(bit))
- new_input = true;
+ if (bits_tribuf.count(bit))
+ goto tribuf_bit;
+ } else {
+ tribuf_bit:
+ if (bits_used.count(bit))
+ new_input = true;
+ }
}
if (new_input != new_output) {
diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc
index 1b8920bb7..3291f5a4a 100644
--- a/passes/techmap/dff2dffe.cc
+++ b/passes/techmap/dff2dffe.cc
@@ -253,7 +253,7 @@ struct Dff2dffeWorker
struct Dff2dffePass : public Pass {
Dff2dffePass() : Pass("dff2dffe", "transform $dff cells to $dffe cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -279,11 +279,12 @@ struct Dff2dffePass : public Pass {
log(" -direct-match <pattern>\n");
log(" like -direct for all DFF cell types matching the expression.\n");
log(" this will use $__DFFE_* as <external_gate_type> matching the\n");
- log(" internal gate type $_DFF_*_, except for $_DFF_[NP]_, which is\n");
- log(" converted to $_DFFE_[NP]_.\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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
@@ -315,6 +316,15 @@ struct Dff2dffePass : public Pass {
if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict["$_DFF_PN1_"] = "$__DFFE_PN1";
if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict["$_DFF_PP0_"] = "$__DFFE_PP0";
if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict["$_DFF_PP1_"] = "$__DFFE_PP1";
+
+ if (patmatch(pattern, "$__DFFS_NN0_")) found_match = true, direct_dict["$__DFFS_NN0_"] = "$__DFFSE_NN0";
+ if (patmatch(pattern, "$__DFFS_NN1_")) found_match = true, direct_dict["$__DFFS_NN1_"] = "$__DFFSE_NN1";
+ if (patmatch(pattern, "$__DFFS_NP0_")) found_match = true, direct_dict["$__DFFS_NP0_"] = "$__DFFSE_NP0";
+ if (patmatch(pattern, "$__DFFS_NP1_")) found_match = true, direct_dict["$__DFFS_NP1_"] = "$__DFFSE_NP1";
+ if (patmatch(pattern, "$__DFFS_PN0_")) found_match = true, direct_dict["$__DFFS_PN0_"] = "$__DFFSE_PN0";
+ if (patmatch(pattern, "$__DFFS_PN1_")) found_match = true, direct_dict["$__DFFS_PN1_"] = "$__DFFSE_PN1";
+ if (patmatch(pattern, "$__DFFS_PP0_")) found_match = true, direct_dict["$__DFFS_PP0_"] = "$__DFFSE_PP0";
+ if (patmatch(pattern, "$__DFFS_PP1_")) found_match = true, direct_dict["$__DFFS_PP1_"] = "$__DFFSE_PP1";
if (!found_match)
log_cmd_error("No cell types matched pattern '%s'.\n", pattern);
continue;
diff --git a/passes/techmap/dff2dffs.cc b/passes/techmap/dff2dffs.cc
new file mode 100644
index 000000000..39a4f6ade
--- /dev/null
+++ b/passes/techmap/dff2dffs.cc
@@ -0,0 +1,142 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 David Shah <dave@ds0.me>
+ *
+ * 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 Dff2dffsPass : public Pass {
+ Dff2dffsPass() : Pass("dff2dffs", "process sync set/reset with SR over CE priority") { }
+ void help() YS_OVERRIDE
+ {
+ log("\n");
+ log(" dff2dffs [options] [selection]\n");
+ log("\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");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing dff2dffs pass (merge synchronous set/reset into FF cells).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-singleton") {
+ // singleton_mode = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ pool<IdString> dff_types;
+ dff_types.insert("$_DFF_N_");
+ dff_types.insert("$_DFF_P_");
+
+ for (auto module : design->selected_modules())
+ {
+ log("Merging set/reset $_MUX_ cells into DFFs in %s.\n", log_id(module));
+
+ SigMap sigmap(module);
+ dict<SigBit, Cell*> sr_muxes;
+ vector<Cell*> ff_cells;
+
+ for (auto cell : module->selected_cells())
+ {
+ if (dff_types.count(cell->type)) {
+ ff_cells.push_back(cell);
+ continue;
+ }
+
+ if (cell->type != "$_MUX_")
+ continue;
+
+ 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("\\Y"))] = cell;
+ }
+
+ for (auto cell : ff_cells)
+ {
+ SigSpec sig_d = cell->getPort("\\D");
+
+ if (GetSize(sig_d) < 1)
+ continue;
+
+ SigBit bit_d = sigmap(sig_d[0]);
+
+ if (sr_muxes.count(bit_d) == 0)
+ continue;
+
+ Cell *mux_cell = sr_muxes.at(bit_d);
+ 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));
+
+ SigBit sr_val, sr_sig;
+ bool invert_sr;
+ sr_sig = bit_s;
+ if (bit_a.wire == nullptr) {
+ bit_d = bit_b;
+ sr_val = bit_a;
+ invert_sr = true;
+ } else {
+ log_assert(bit_b.wire == nullptr);
+ bit_d = bit_a;
+ sr_val = bit_b;
+ invert_sr = false;
+ }
+
+ if (sr_val == State::S1) {
+ if (cell->type == "$_DFF_N_") {
+ if (invert_sr) cell->type = "$__DFFS_NN1_";
+ else cell->type = "$__DFFS_NP1_";
+ } else {
+ log_assert(cell->type == "$_DFF_P_");
+ if (invert_sr) cell->type = "$__DFFS_PN1_";
+ else cell->type = "$__DFFS_PP1_";
+ }
+ } else {
+ if (cell->type == "$_DFF_N_") {
+ if (invert_sr) cell->type = "$__DFFS_NN0_";
+ else cell->type = "$__DFFS_NP0_";
+ } else {
+ log_assert(cell->type == "$_DFF_P_");
+ if (invert_sr) cell->type = "$__DFFS_PN0_";
+ else cell->type = "$__DFFS_PP0_";
+ }
+ }
+ cell->setPort("\\R", sr_sig);
+ cell->setPort("\\D", bit_d);
+ }
+ }
+ }
+} Dff2dffsPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc
index 6a8a86383..a8eecc970 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -44,7 +44,7 @@ struct DffinitPass : public Pass {
log(" mode.)\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing DFFINIT pass (set INIT param on FF cells).\n");
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index 4cb1489a8..416ed2bd5 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -240,6 +240,10 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
if (cell->id != "cell" || cell->args.size() != 1)
continue;
+ LibertyAst *dn = cell->find("dont_use");
+ if (dn != NULL && dn->value == "true")
+ continue;
+
LibertyAst *ff = cell->find("ff");
if (ff == NULL)
continue;
@@ -533,7 +537,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
struct DfflibmapPass : public Pass {
DfflibmapPass() : Pass("dfflibmap", "technology mapping of flip-flops") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
log("\n");
log(" dfflibmap [-prepare] -liberty <file> [selection]\n");
@@ -549,7 +553,7 @@ struct DfflibmapPass : public Pass {
log("liberty file.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n");
diff --git a/passes/techmap/dffsr2dff.cc b/passes/techmap/dffsr2dff.cc
index 0d4d53627..086a1d2fa 100644
--- a/passes/techmap/dffsr2dff.cc
+++ b/passes/techmap/dffsr2dff.cc
@@ -176,7 +176,7 @@ void adff_worker(SigMap &sigmap, Module *module, Cell *cell)
struct Dffsr2dffPass : public Pass {
Dffsr2dffPass() : Pass("dffsr2dff", "convert DFFSR cells to simpler FF cell types") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -186,7 +186,7 @@ struct Dffsr2dffPass : public Pass {
log("$_DFF_???_) to simpler FF cell types when any of the set/reset inputs is unused.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing DFFSR2DFF pass (mapping DFFSR cells to simpler FFs).\n");
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc
index 71e29c60b..fff90f13c 100644
--- a/passes/techmap/extract.cc
+++ b/passes/techmap/extract.cc
@@ -352,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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -440,7 +440,7 @@ struct ExtractPass : public Pass {
log("See 'help techmap' for a pass that does the opposite thing.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing EXTRACT pass (map subcircuits to cells).\n");
log_push();
diff --git a/passes/techmap/extract_counter.cc b/passes/techmap/extract_counter.cc
index af0eb852a..a8d0bc834 100644
--- a/passes/techmap/extract_counter.cc
+++ b/passes/techmap/extract_counter.cc
@@ -559,7 +559,7 @@ void counter_worker(
struct ExtractCounterPass : public Pass {
ExtractCounterPass() : Pass("extract_counter", "Extract GreenPak4 counter cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -578,7 +578,7 @@ struct ExtractCounterPass : public Pass {
log("\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing EXTRACT_COUNTER pass (find counters in netlist).\n");
diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc
index a68cc5e2e..9e6dc0d24 100644
--- a/passes/techmap/extract_fa.cc
+++ b/passes/techmap/extract_fa.cc
@@ -531,7 +531,7 @@ struct ExtractFaWorker
struct ExtractFaPass : public Pass {
ExtractFaPass() : Pass("extract_fa", "find and extract full/half adders") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -553,7 +553,7 @@ struct ExtractFaPass : public Pass {
log(" Verbose output\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
ExtractFaConfig config;
diff --git a/passes/techmap/extract_reduce.cc b/passes/techmap/extract_reduce.cc
index cc21c8665..a77bbc0b7 100644
--- a/passes/techmap/extract_reduce.cc
+++ b/passes/techmap/extract_reduce.cc
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include <deque>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -33,7 +34,7 @@ struct ExtractReducePass : public Pass
ExtractReducePass() : Pass("extract_reduce", "converts gate chains into $reduce_* cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -62,7 +63,7 @@ struct ExtractReducePass : public Pass
(cell->type == "$_XOR_" && gt == GateType::Xor);
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing EXTRACT_REDUCE pass.\n");
log_push();
diff --git a/passes/techmap/hilomap.cc b/passes/techmap/hilomap.cc
index 82cecac26..9ec651aef 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing HILOMAP pass (mapping to constant drivers).\n");
diff --git a/passes/techmap/insbuf.cc b/passes/techmap/insbuf.cc
index aa81468dc..2173049b4 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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
log("\n");
log(" insbuf [options] [selection]\n");
@@ -37,7 +37,7 @@ struct InsbufPass : public Pass {
log(" call to \"clean\" will remove all $_BUF_ in the design.)\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing INSBUF pass (insert buffer cells for connected wires).\n");
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index 4acbf7c0d..efcc082d5 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)") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
log("\n");
log(" iopadmap [options] [selection]\n");
@@ -78,7 +78,7 @@ struct IopadmapPass : public Pass {
log("Tristate PADS (-toutpad, -tinoutpad) always operate in -bits mode.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
@@ -146,11 +146,37 @@ struct IopadmapPass : public Pass {
for (auto module : design->selected_modules())
{
dict<IdString, pool<int>> skip_wires;
+ pool<SigBit> skip_wire_bits;
+ SigMap sigmap(module);
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type == RTLIL::escape_id(inpad_celltype) && cell->hasPort(RTLIL::escape_id(inpad_portname2)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inpad_portname2))))
+ skip_wire_bits.insert(bit);
+
+ if (cell->type == RTLIL::escape_id(outpad_celltype) && cell->hasPort(RTLIL::escape_id(outpad_portname2)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(outpad_portname2))))
+ skip_wire_bits.insert(bit);
+
+ if (cell->type == RTLIL::escape_id(inoutpad_celltype) && cell->hasPort(RTLIL::escape_id(inoutpad_portname2)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inoutpad_portname2))))
+ skip_wire_bits.insert(bit);
+
+ if (cell->type == RTLIL::escape_id(toutpad_celltype) && cell->hasPort(RTLIL::escape_id(toutpad_portname3)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(toutpad_portname3))))
+ skip_wire_bits.insert(bit);
+
+ if (cell->type == RTLIL::escape_id(tinoutpad_celltype) && cell->hasPort(RTLIL::escape_id(tinoutpad_portname4)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(tinoutpad_portname4))))
+ skip_wire_bits.insert(bit);
+ }
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
{
- SigMap sigmap(module);
dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits;
+ pool<pair<IdString, IdString>> norewrites;
+ SigMap rewrites;
for (auto cell : module->cells())
if (cell->type == "$_TBUF_") {
@@ -177,6 +203,9 @@ struct IopadmapPass : public Pass {
if (tbuf_bits.count(mapped_wire_bit) == 0)
continue;
+ if (skip_wire_bits.count(mapped_wire_bit))
+ continue;
+
auto &tbuf_cache = tbuf_bits.at(mapped_wire_bit);
Cell *tbuf_cell = module->cell(tbuf_cache.first);
@@ -219,6 +248,9 @@ struct IopadmapPass : public Pass {
module->remove(tbuf_cell);
skip_wires[wire->name].insert(i);
+
+ norewrites.insert(make_pair(cell->name, RTLIL::escape_id(tinoutpad_portname4)));
+ rewrites.add(sigmap(wire_bit), owire);
continue;
}
@@ -256,6 +288,22 @@ struct IopadmapPass : public Pass {
}
}
}
+
+ if (GetSize(norewrites))
+ {
+ for (auto cell : module->cells())
+ for (auto port : cell->connections())
+ {
+ if (norewrites.count(make_pair(cell->name, port.first)))
+ continue;
+
+ SigSpec orig_sig = sigmap(port.second);
+ SigSpec new_sig = rewrites(orig_sig);
+
+ if (orig_sig != new_sig)
+ cell->setPort(port.first, new_sig);
+ }
+ }
}
for (auto wire : module->selected_wires())
@@ -272,6 +320,13 @@ struct IopadmapPass : public Pass {
skip_bit_indices = skip_wires.at(wire->name);
}
+ for (int i = 0; i < GetSize(wire); i++)
+ if (skip_wire_bits.count(sigmap(SigBit(wire, i))))
+ skip_bit_indices.insert(i);
+
+ if (GetSize(wire) == GetSize(skip_bit_indices))
+ continue;
+
if (wire->port_input && !wire->port_output) {
if (inpad_celltype.empty()) {
log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
diff --git a/passes/techmap/lut2mux.cc b/passes/techmap/lut2mux.cc
index 2bb0bd8b4..d32bbff14 100644
--- a/passes/techmap/lut2mux.cc
+++ b/passes/techmap/lut2mux.cc
@@ -56,7 +56,7 @@ int lut2mux(Cell *cell)
struct Lut2muxPass : public Pass {
Lut2muxPass() : Pass("lut2mux", "convert $lut to $_MUX_") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 32569d076..3e8e59e6b 100644
--- a/passes/techmap/maccmap.cc
+++ b/passes/techmap/maccmap.cc
@@ -365,7 +365,7 @@ PRIVATE_NAMESPACE_BEGIN
struct MaccmapPass : public Pass {
MaccmapPass() : Pass("maccmap", "mapping macc cells") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool unmap_mode = false;
diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc
index 1dc649587..12da9ed0c 100644
--- a/passes/techmap/muxcover.cc
+++ b/passes/techmap/muxcover.cc
@@ -561,7 +561,7 @@ struct MuxcoverWorker
struct MuxcoverPass : public Pass {
MuxcoverPass() : Pass("muxcover", "cover trees of MUX cells with wider MUXes") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -579,7 +579,7 @@ struct MuxcoverPass : public Pass {
log(" less efficient than the original circuit.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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 f1a41cc3e..cc765d89c 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
NlutmapConfig config;
diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc
index c626dbcc5..b7a22dc3b 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") { }
- virtual void help()
+ 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 a trees of $mux cells.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing PMUXTREE pass.\n");
diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc
index 6936b499e..f20863ba0 100644
--- a/passes/techmap/shregmap.cc
+++ b/passes/techmap/shregmap.cc
@@ -391,7 +391,7 @@ struct ShregmapWorker
struct ShregmapPass : public Pass {
ShregmapPass() : Pass("shregmap", "map shift registers") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -449,7 +449,7 @@ struct ShregmapPass : public Pass {
log(" map to greenpak4 shift registers.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
ShregmapOptions opts;
string clkpol, enpol;
diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc
index c6b932bdc..660b60601 100644
--- a/passes/techmap/simplemap.cc
+++ b/passes/techmap/simplemap.cc
@@ -575,7 +575,7 @@ PRIVATE_NAMESPACE_BEGIN
struct SimplemapPass : public Pass {
SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -590,7 +590,7 @@ struct SimplemapPass : public Pass {
log(" $sr, $ff, $dff, $dffsr, $adff, $dlatch\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
extra_args(args, 1, design);
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 02d0d47e8..d0e5e2236 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -891,7 +891,7 @@ struct TechmapWorker
struct TechmapPass : public Pass {
TechmapPass() : Pass("techmap", "generic technology mapper") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -933,7 +933,7 @@ struct TechmapPass : public Pass {
log(" -D <define>, -I <incdir>\n");
log(" this options are passed as-is to the Verilog frontend for loading the\n");
log(" map file. Note that the Verilog frontend is also called with the\n");
- log(" '-ignore_redef' option set.\n");
+ log(" '-nooverwrite' option set.\n");
log("\n");
log("When a module in the map file has the 'techmap_celltype' attribute set, it will\n");
log("match cells with a type that match the text value of this attribute. Otherwise\n");
@@ -1022,7 +1022,7 @@ struct TechmapPass : public Pass {
log("essentially techmap but using the design itself as map library).\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing TECHMAP pass (map to technology primitives).\n");
log_push();
@@ -1031,7 +1031,7 @@ struct TechmapPass : public Pass {
simplemap_get_mappers(worker.simplemap_mappers);
std::vector<std::string> map_files;
- std::string verilog_frontend = "verilog -ignore_redef";
+ std::string verilog_frontend = "verilog -nooverwrite";
int max_iter = -1;
size_t argidx;
@@ -1141,7 +1141,7 @@ struct TechmapPass : public Pass {
struct FlattenPass : public Pass {
FlattenPass() : Pass("flatten", "flatten design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1155,7 +1155,7 @@ struct FlattenPass : public Pass {
log("flattened by this command.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing FLATTEN pass (flatten design).\n");
log_push();
diff --git a/passes/techmap/tribuf.cc b/passes/techmap/tribuf.cc
index 03629082c..587cb9038 100644
--- a/passes/techmap/tribuf.cc
+++ b/passes/techmap/tribuf.cc
@@ -139,7 +139,7 @@ struct TribufWorker {
struct TribufPass : public Pass {
TribufPass() : Pass("tribuf", "infer tri-state buffers") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -156,7 +156,7 @@ struct TribufPass : public Pass {
log(" to non-tristate logic. this option implies -merge.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
TribufConfig config;
diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc
index a577e1235..b46147fb9 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool all_mode = false;
diff --git a/passes/tests/test_abcloop.cc b/passes/tests/test_abcloop.cc
index 09cb41954..5d5466afe 100644
--- a/passes/tests/test_abcloop.cc
+++ b/passes/tests/test_abcloop.cc
@@ -244,7 +244,7 @@ static void test_abcloop()
struct TestAbcloopPass : public Pass {
TestAbcloopPass() : Pass("test_abcloop", "automatically test handling of loops in abc command") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design*)
+ void execute(std::vector<std::string> 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 cb31056f4..bfb1d6642 100644
--- a/passes/tests/test_autotb.cc
+++ b/passes/tests/test_autotb.cc
@@ -324,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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -349,7 +349,7 @@ struct TestAutotbBackend : public Backend {
log(" number of iterations the test bench should run (default = 1000)\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> 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 47b6bdf23..e360b5edb 100644
--- a/passes/tests/test_cell.cc
+++ b/passes/tests/test_cell.cc
@@ -652,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") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -712,7 +712,7 @@ struct TestCellPass : public Pass {
log(" create a Verilog test bench to test simlib and write_verilog\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design*)
+ void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
{
int num_iter = 100;
std::string techmap_cmd = "techmap -assert";
diff --git a/techlibs/achronix/Makefile.inc b/techlibs/achronix/Makefile.inc
index affe0334a..994cf0015 100755
--- a/techlibs/achronix/Makefile.inc
+++ b/techlibs/achronix/Makefile.inc
@@ -1,5 +1,5 @@
-OBJS += techlibs/achronix/synth_speedster.o
+OBJS += techlibs/achronix/synth_achronix.o
$(eval $(call add_share_file,share/achronix/speedster22i/,techlibs/achronix/speedster22i/cells_sim.v))
$(eval $(call add_share_file,share/achronix/speedster22i/,techlibs/achronix/speedster22i/cells_map.v))
diff --git a/techlibs/achronix/speedster22i/cells_map.v b/techlibs/achronix/speedster22i/cells_map.v
index 90f87826d..95f5d59c5 100755
--- a/techlibs/achronix/speedster22i/cells_map.v
+++ b/techlibs/achronix/speedster22i/cells_map.v
@@ -16,53 +16,25 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
-// Normal mode DFF negedge clk, negedge reset
-module \$_DFF_N_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Normal mode DFF
-module \$_DFF_P_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-// Async Active Low Reset DFF
-module \$_DFF_PN0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Async Active High Reset DFF
-module \$_DFF_PP0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG)) _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
-// Async Active Low Reset DFF
-module \$_DFF_PN0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-/* */
-module \$__DFFE_PP0 (input D, C, E, R, output Q);
- parameter WYSIWYG="TRUE";
- wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
-endmodule
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Achronix eFPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board/custom chip.
+// > Input/Output buffers <
// Input buffer map
module \$__inpad (input I, output O);
PADIN _TECHMAP_REPLACE_ (.padout(O), .padin(I));
endmodule
-
// Output buffer map
module \$__outpad (input I, output O);
PADOUT _TECHMAP_REPLACE_ (.padout(O), .padin(I), .oe(1'b1));
endmodule
+// > end buffers <
+// > Look-Up table <
+// > VT: I still think Achronix folks would have choosen a better \
+// > logic architecture.
// LUT Map
-/* 0 -> datac
- 1 -> cin */
module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;
@@ -70,19 +42,31 @@ module \$lut (A, Y);
output Y;
generate
if (WIDTH == 1) begin
- assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
+ // VT: This is not consistent and ACE will complain: assign Y = ~A[0];
+ LUT4 #(.lut_function({4{LUT}})) _TECHMAP_REPLACE_
+ (.dout(Y), .din0(A[0]), .din1(1'b0), .din2(1'b0), .din3(1'b0));
end else
if (WIDTH == 2) begin
- LUT4 #(.lut_function({4{LUT}})) _TECHMAP_REPLACE_ (.dout(Y), .din0(A[0]), .din1(A[1]), .din2(1'b0),.din3(1'b0));
+ LUT4 #(.lut_function({4{LUT}})) _TECHMAP_REPLACE_
+ (.dout(Y), .din0(A[0]), .din1(A[1]), .din2(1'b0), .din3(1'b0));
end else
if(WIDTH == 3) begin
- LUT4 #(.lut_function({2{LUT}})) _TECHMAP_REPLACE_ (.dout(Y), .din0(A[0]), .din1(A[1]), .din2(A[2]),.din3(1'b0));
+ LUT4 #(.lut_function({2{LUT}})) _TECHMAP_REPLACE_
+ (.dout(Y), .din0(A[0]), .din1(A[1]), .din2(A[2]), .din3(1'b0));
end else
if(WIDTH == 4) begin
- LUT4 #(.lut_function(LUT)) _TECHMAP_REPLACE_ (.dout(Y), .din0(A[0]), .din1(A[1]), .din2(A[2]), .din3(A[3]));
+ LUT4 #(.lut_function(LUT)) _TECHMAP_REPLACE_
+ (.dout(Y), .din0(A[0]), .din1(A[1]), .din2(A[2]), .din3(A[3]));
end else
wire _TECHMAP_FAIL_ = 1;
endgenerate
-endmodule //
+endmodule
+// > end LUT <
+// > Flops <
+// DFF flop
+module \$_DFF_P_ (input D, C, output Q);
+ DFF _TECHMAP_REPLACE_
+ (.q(Q), .d(D), .ck(C));
+endmodule
diff --git a/techlibs/achronix/speedster22i/cells_sim.v b/techlibs/achronix/speedster22i/cells_sim.v
index 24c57c41a..da23fed7e 100755
--- a/techlibs/achronix/speedster22i/cells_sim.v
+++ b/techlibs/achronix/speedster22i/cells_sim.v
@@ -16,50 +16,31 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Achronix eFPGA technology sim models. User must first simulate the generated \
+// > netlist before going to test it on board/custom chip.
+// > Changelog: 1) Removed unused VCC/GND modules
+// > 2) Altera comments here (?). Removed.
+// > 3) Reusing LUT sim model, removed wrong wires and parameters.
-module VCC (output V);
- assign V = 1'b1;
-endmodule // VCC
-
-module GND (output G);
- assign G = 1'b0;
-endmodule // GND
-
-/* Altera MAX10 devices Input Buffer Primitive */
module PADIN (output padout, input padin);
assign padout = padin;
-endmodule // fiftyfivenm_io_ibuf
+endmodule
-/* Altera MAX10 devices Output Buffer Primitive */
module PADOUT (output padout, input padin, input oe);
assign padout = padin;
assign oe = oe;
-endmodule // fiftyfivenm_io_obuf
+endmodule
-/* Altera MAX10 4-input non-fracturable LUT Primitive */
module LUT4 (output dout,
input din0, din1, din2, din3);
-/* Internal parameters which define the behaviour
- of the LUT primitive.
- lut_mask define the lut function, can be expressed in 16-digit bin or hex.
- sum_lutc_input define the type of LUT (combinational | arithmetic).
- dont_touch for retiming || carry options.
- lpm_type for WYSIWYG */
-
-parameter lut_function = 16'hFFFF;
-//parameter dont_touch = "off";
-//parameter lpm_type = "fiftyfivenm_lcell_comb";
-//parameter sum_lutc_input = "datac";
-
-reg [1:0] lut_type;
-reg cout_rt;
+parameter [15:0] lut_function = 16'hFFFF;
reg combout_rt;
wire dataa_w;
wire datab_w;
wire datac_w;
wire datad_w;
-wire cin_w;
assign dataa_w = din0;
assign datab_w = din1;
@@ -78,49 +59,21 @@ reg [1:0] s1;
s1 = datab ? s2[3:2] : s2[1:0];
lut_data = dataa ? s1[1] : s1[0];
end
-
endfunction
-initial begin
- /*if (sum_lutc_input == "datac")*/ lut_type = 0;
- /*else
- if (sum_lutc_input == "cin") lut_type = 1;
- else begin
- $error("Error in sum_lutc_input. Parameter %s is not a valid value.\n", sum_lutc_input);
- $finish();
- end*/
-end
-
always @(dataa_w or datab_w or datac_w or datad_w or cin_w) begin
- if (lut_type == 0) begin // logic function
- combout_rt = lut_data(lut_function, dataa_w, datab_w,
- datac_w, datad_w);
- end
- else if (lut_type == 1) begin // arithmetic function
- combout_rt = lut_data(lut_function, dataa_w, datab_w,
- cin_w, datad_w);
- end
- cout_rt = lut_data(lut_function, dataa_w, datab_w, cin_w, 'b0);
+ combout_rt = lut_data(lut_function, dataa_w, datab_w,
+ datac_w, datad_w);
end
-
assign dout = combout_rt & 1'b1;
-//assign cout = cout_rt & 1'b1;
-
-endmodule // fiftyfivenm_lcell_comb
-
-/* Altera MAX10 D Flip-Flop Primitive */
-// TODO: Implement advanced simulation functions
-module dffeas ( output q,
- input d, clk, clrn, prn, ena,
- input asdata, aload, sclr, sload );
-
-parameter power_up="dontcare";
-parameter is_wysiwyg="false";
- reg q;
-
- always @(posedge clk)
- q <= d;
-
+endmodule
+
+module DFF (output q,
+ input d, ck);
+ reg q;
+ always @(posedge ck)
+ q <= d;
+
endmodule
diff --git a/techlibs/achronix/synth_speedster.cc b/techlibs/achronix/synth_achronix.cc
index 3808af6f1..92b10781d 100755
--- a/techlibs/achronix/synth_speedster.cc
+++ b/techlibs/achronix/synth_achronix.cc
@@ -25,14 +25,14 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-struct SynthIntelPass : public ScriptPass {
- SynthIntelPass() : ScriptPass("synth_speedster", "synthesis for Acrhonix Speedster22i FPGAs.") { }
+struct SynthAchronixPass : public ScriptPass {
+ SynthAchronixPass() : ScriptPass("synth_achronix", "synthesis for Acrhonix Speedster22i FPGAs.") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" synth_speedster [options]\n");
+ log(" synth_achronix [options]\n");
log("\n");
log("This command runs synthesis for Achronix Speedster eFPGAs. This work is still experimental.\n");
log("\n");
@@ -63,7 +63,7 @@ struct SynthIntelPass : public ScriptPass {
string top_opt, family_opt, vout_file;
bool retime, flatten;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
vout_file = "";
@@ -71,7 +71,7 @@ struct SynthIntelPass : public ScriptPass {
flatten = true;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -110,7 +110,7 @@ struct SynthIntelPass : public ScriptPass {
if (!design->full_selection())
log_cmd_error("This comannd only operates on fully selected designs!\n");
- log_header(design, "Executing SYNTH_SPEEDSTER pass.\n");
+ log_header(design, "Executing SYNTH_ACHRONIX pass.\n");
log_push();
run_script(design, run_from, run_to);
@@ -118,7 +118,7 @@ struct SynthIntelPass : public ScriptPass {
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
@@ -146,9 +146,9 @@ struct SynthIntelPass : public ScriptPass {
run("opt -undriven -fine");
run("dffsr2dff");
run("dff2dffe -direct-match $_DFF_*");
- run("opt -full");
+ run("opt -fine");
run("techmap -map +/techmap.v");
- run("opt -fast");
+ run("opt -full");
run("clean -purge");
run("setundef -undriven -zero");
if (retime || help_mode)
@@ -157,7 +157,7 @@ struct SynthIntelPass : public ScriptPass {
if (check_label("map_luts"))
{
- run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
+ run("abc -lut 4" + string(retime ? " -dff" : ""));
run("clean");
}
@@ -165,7 +165,7 @@ struct SynthIntelPass : public ScriptPass {
{
run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I");
run("techmap -map +/achronix/speedster22i/cells_map.v");
- run("dffinit -ff dffeas Q INIT");
+ // VT: not done yet run("dffinit -highlow -ff DFF q power_up");
run("clean -purge");
}
@@ -179,10 +179,10 @@ struct SynthIntelPass : public ScriptPass {
if (check_label("vout"))
{
if (!vout_file.empty() || help_mode)
- run(stringf("write_verilog -nodec -attr2comment -defparam -nohex -renameprefix yosys_ %s",
+ run(stringf("write_verilog -nodec -attr2comment -defparam -renameprefix syn_ %s",
help_mode ? "<file-name>" : vout_file.c_str()));
}
}
-} SynthIntelPass;
+} SynthAchronixPass;
PRIVATE_NAMESPACE_END
diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc
index 3dfc60383..897f37dbb 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") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -55,13 +55,14 @@ struct PrepPass : public ScriptPass
log("\n");
log(" -memx\n");
log(" simulate verilog simulation behavior for out-of-bounds memory accesses\n");
- log(" using the 'memory_memx' pass. This option implies -nordff.\n");
+ log(" using the 'memory_memx' pass.\n");
log("\n");
log(" -nomem\n");
log(" do not run any of the memory_* passes\n");
log("\n");
- log(" -nordff\n");
- log(" passed to 'memory_dff'. prohibits merging of FFs into memory read ports\n");
+ log(" -rdff\n");
+ log(" do not pass -nordff to 'memory_dff'. This enables merging of FFs into\n");
+ log(" memory read ports.\n");
log("\n");
log(" -nokeepdc\n");
log(" do not call opt_* with -keepdc\n");
@@ -77,13 +78,12 @@ struct PrepPass : public ScriptPass
log("\n");
}
- string top_module, fsm_opts, memory_opts;
- bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc;
+ string top_module, fsm_opts;
+ bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, nordff;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_module.clear();
- memory_opts.clear();
autotop = false;
flatten = false;
@@ -91,9 +91,10 @@ struct PrepPass : public ScriptPass
memxmode = false;
nomemmode = false;
nokeepdc = false;
+ nordff = true;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
@@ -129,7 +130,6 @@ struct PrepPass : public ScriptPass
}
if (args[argidx] == "-memx") {
memxmode = true;
- memory_opts += " -nordff";
continue;
}
if (args[argidx] == "-nomem") {
@@ -137,7 +137,11 @@ struct PrepPass : public ScriptPass
continue;
}
if (args[argidx] == "-nordff") {
- memory_opts += " -nordff";
+ nordff = true;
+ continue;
+ }
+ if (args[argidx] == "-rdff") {
+ nordff = false;
continue;
}
if (args[argidx] == "-nokeepdc") {
@@ -159,7 +163,7 @@ struct PrepPass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
@@ -196,7 +200,7 @@ struct PrepPass : public ScriptPass
run(memxmode ? "wreduce -memx" : "wreduce");
}
if (!nomemmode) {
- run("memory_dff" + (help_mode ? " [-nordff]" : memory_opts));
+ run(string("memory_dff") + (help_mode ? " [-nordff]" : nordff ? " -nordff" : ""));
if (help_mode || memxmode)
run("memory_memx", "(if -memx)");
run("opt_clean");
diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc
index 4ca34839e..efb214759 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") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -81,7 +81,7 @@ struct SynthPass : public ScriptPass
string top_module, fsm_opts, memory_opts;
bool autotop, flatten, noalumacc, nofsm, noabc, noshare;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_module.clear();
fsm_opts.clear();
@@ -95,7 +95,7 @@ struct SynthPass : public ScriptPass
noshare = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -165,7 +165,7 @@ struct SynthPass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
diff --git a/techlibs/coolrunner2/Makefile.inc b/techlibs/coolrunner2/Makefile.inc
index 96bbb0f47..d62c9960c 100644
--- a/techlibs/coolrunner2/Makefile.inc
+++ b/techlibs/coolrunner2/Makefile.inc
@@ -4,4 +4,5 @@ OBJS += techlibs/coolrunner2/coolrunner2_sop.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/tff_extract.v))
$(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/xc2_dff.lib))
diff --git a/techlibs/coolrunner2/coolrunner2_sop.cc b/techlibs/coolrunner2/coolrunner2_sop.cc
index b57214ccb..48da0d8ad 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> 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);
@@ -250,6 +250,64 @@ 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<SigBit> sig_fed_by_ff;
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "\\FDCP" || cell->type == "\\FDCP_N" || cell->type == "\\FDDCP" ||
+ cell->type == "\\LDCP" || cell->type == "\\LDCP_N" ||
+ cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP" ||
+ cell->type == "\\FDCPE" || cell->type == "\\FDCPE_N" || cell->type == "\\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 == "\\FDCP" || cell->type == "\\FDCP_N" || cell->type == "\\FDDCP" ||
+ cell->type == "\\LDCP" || cell->type == "\\LDCP_N" ||
+ cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP" ||
+ cell->type == "\\FDCPE" || cell->type == "\\FDCPE_N" || cell->type == "\\FDDCPE")
+ {
+ SigBit input;
+ if (cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\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 == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\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 183282629..a5dac3566 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") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -66,7 +66,7 @@ struct SynthCoolrunner2Pass : public ScriptPass
string top_opt, json_file;
bool flatten, retime;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
json_file = "";
@@ -74,7 +74,7 @@ struct SynthCoolrunner2Pass : public ScriptPass
retime = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -121,7 +121,7 @@ struct SynthCoolrunner2Pass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
@@ -149,6 +149,16 @@ struct SynthCoolrunner2Pass : public ScriptPass
run("dfflibmap -prepare -liberty +/coolrunner2/xc2_dff.lib");
}
+ if (check_label("map_tff"))
+ {
+ // This is quite hacky. By telling abc that it can only use AND and XOR gates, abc will try and use XOR
+ // gates "whenever possible." This will hopefully cause toggle flip-flop structures to turn into an XOR
+ // connected to a D flip-flop. We then match on these and convert them into XC2 TFF cells.
+ run("abc -g AND,XOR");
+ run("clean");
+ run("extract -map +/coolrunner2/tff_extract.v");
+ }
+
if (check_label("map_pla"))
{
run("abc -sop -I 40 -P 56");
@@ -160,12 +170,15 @@ struct SynthCoolrunner2Pass : public ScriptPass
run("dfflibmap -liberty +/coolrunner2/xc2_dff.lib");
run("dffinit -ff FDCP Q INIT");
run("dffinit -ff FDCP_N Q INIT");
+ run("dffinit -ff FTCP Q INIT");
+ run("dffinit -ff FTCP_N Q INIT");
run("dffinit -ff LDCP Q INIT");
run("dffinit -ff LDCP_N Q INIT");
run("coolrunner2_sop");
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("splitnets");
run("clean");
}
diff --git a/techlibs/coolrunner2/tff_extract.v b/techlibs/coolrunner2/tff_extract.v
new file mode 100644
index 000000000..b4237dd18
--- /dev/null
+++ b/techlibs/coolrunner2/tff_extract.v
@@ -0,0 +1,41 @@
+module FTCP (C, PRE, CLR, T, Q);
+ input C, PRE, CLR, T;
+ output wire Q;
+
+ wire xorout;
+
+ $_XOR_ xorgate (
+ .A(T),
+ .B(Q),
+ .Y(xorout),
+ );
+
+ $_DFFSR_PPP_ dff (
+ .C(C),
+ .D(xorout),
+ .Q(Q),
+ .S(PRE),
+ .R(CLR),
+ );
+endmodule
+
+module FTCP_N (C, PRE, CLR, T, Q);
+ input C, PRE, CLR, T;
+ output wire Q;
+
+ wire xorout;
+
+ $_XOR_ xorgate (
+ .A(T),
+ .B(Q),
+ .Y(xorout),
+ );
+
+ $_DFFSR_NPP_ dff (
+ .C(C),
+ .D(xorout),
+ .Q(Q),
+ .S(PRE),
+ .R(CLR),
+ );
+endmodule
diff --git a/techlibs/easic/synth_easic.cc b/techlibs/easic/synth_easic.cc
index e17138f3a..b5ed93be4 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") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -67,7 +67,7 @@ struct SynthEasicPass : public ScriptPass
string top_opt, vlog_file, etools_path;
bool flatten, retime;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
vlog_file = "";
@@ -76,7 +76,7 @@ struct SynthEasicPass : public ScriptPass
retime = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -127,7 +127,7 @@ struct SynthEasicPass : public ScriptPass
log_pop();
}
- virtual void script() YS_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());
diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc
new file mode 100644
index 000000000..9d3247347
--- /dev/null
+++ b/techlibs/ecp5/Makefile.inc
@@ -0,0 +1,8 @@
+
+OBJS += techlibs/ecp5/synth_ecp5.o
+
+$(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/drams_map.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dram.txt))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
diff --git a/techlibs/ecp5/arith_map.v b/techlibs/ecp5/arith_map.v
new file mode 100644
index 000000000..1094c5f8a
--- /dev/null
+++ b/techlibs/ecp5/arith_map.v
@@ -0,0 +1,79 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 David Shah <dave@ds0.me>
+ *
+ * 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.
+ *
+ */
+
+(* techmap_celltype = "$alu" *)
+module _80_ecp5_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;
+
+ input [A_WIDTH-1:0] A;
+ input [B_WIDTH-1:0] B;
+ output [Y_WIDTH-1:0] X, Y;
+
+ input CI, BI;
+ output [Y_WIDTH-1:0] CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
+
+ 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));
+
+ function integer round_up2;
+ input integer N;
+ begin
+ round_up2 = ((N + 1) / 2) * 2;
+ end
+ endfunction
+
+ localparam Y_WIDTH2 = round_up2(Y_WIDTH);
+
+ wire [Y_WIDTH2-1:0] AA = A_buf;
+ wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;
+ wire [Y_WIDTH2-1:0] C = {CO, CI};
+ wire [Y_WIDTH2-1:0] FCO, Y1;
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice
+ CCU2C #(
+ .INIT0(16'b0110011010101010),
+ .INIT1(16'b0110011010101010),
+ .INJECT1_0("NO"),
+ .INJECT1_1("NO")
+ ) ccu2c_i (
+ .CIN(C[i]),
+ .A0(AA[i]), .B0(BB[i]), .C0(1'b0), .D0(1'b1),
+ .A1(AA[i+1]), .B1(BB[i+1]), .C1(1'b0), .D1(1'b1),
+ .S0(Y[i]), .S1(Y1[i]),
+ .COUT(FCO[i])
+ );
+
+ assign CO[i] = (AA[i] && BB[i]) || (C[i] && (AA[i] || BB[i]));
+ if (i+1 < Y_WIDTH) begin
+ assign CO[i+1] = FCO[i];
+ assign Y[i+1] = Y1[i];
+ end
+ end endgenerate
+
+ assign X = AA ^ BB;
+endmodule
diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v
new file mode 100644
index 000000000..48162a4dc
--- /dev/null
+++ b/techlibs/ecp5/cells_map.v
@@ -0,0 +1,135 @@
+module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .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("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .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("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .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("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .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("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .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("DISABLED"), .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("DISABLED"), .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("DISABLED"), .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("DISABLED"), .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("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .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("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .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("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .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("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .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("DISABLED"), .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("DISABLED"), .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("DISABLED"), .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("DISABLED"), .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("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .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("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .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("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .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("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .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("DISABLED"), .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("DISABLED"), .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("DISABLED"), .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("DISABLED"), .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
+
+`ifndef NO_LUT
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(1'b0), .C(1'b0), .D(1'b0));
+ end else
+ if (WIDTH == 2) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(A[1]), .C(1'b0), .D(1'b0));
+ end else
+ if (WIDTH == 3) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(1'b0));
+ 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]));
+ `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));
+ 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));
+ 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));
+ `endif
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+endmodule
+`endif
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
new file mode 100644
index 000000000..1700694e8
--- /dev/null
+++ b/techlibs/ecp5/cells_sim.v
@@ -0,0 +1,448 @@
+// ---------------------------------------
+
+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];
+endmodule
+
+// ---------------------------------------
+
+module L6MUX21 (input D0, D1, SD, output Z);
+ assign Z = SD ? D1 : D0;
+endmodule
+
+// ---------------------------------------
+
+module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
+ output S0, S1, COUT);
+
+ parameter [15:0] INIT0 = 16'h0000;
+ parameter [15:0] INIT1 = 16'h0000;
+ parameter INJECT1_0 = "YES";
+ parameter INJECT1_1 = "YES";
+
+ // First half
+ wire LUT4_0, LUT2_0;
+ 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));
+
+ wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN;
+ assign S0 = LUT4_0 ^ gated_cin_0;
+
+ wire gated_lut2_0 = (INJECT1_0 == "YES") ? 1'b0 : LUT2_0;
+ wire cout_0 = (~LUT4_0 & gated_lut2_0) | (LUT4_0 & CIN);
+
+ // Second half
+ wire LUT4_1, LUT2_1;
+ 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));
+
+ 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);
+
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_RAM16X2 (
+ input DI0, DI1,
+ input WAD0, WAD1, WAD2, WAD3,
+ input WRE, WCK,
+ input RAD0, RAD1, RAD2, RAD3,
+ output DO0, DO1
+);
+ parameter WCKMUX = "WCK";
+ parameter WREMUX = "WRE";
+ parameter INITVAL_0 = 16'h0000;
+ parameter INITVAL_1 = 16'h0000;
+
+ reg [1:0] mem[15:0];
+
+ integer i;
+ initial begin
+ for (i = 0; i < 16; i = i + 1)
+ mem[i] <= {INITVAL_1[i], INITVAL_0[i]};
+ end
+
+ wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
+
+ reg muxwre;
+ always @(*)
+ case (WREMUX)
+ "1": muxwre = 1'b1;
+ "0": muxwre = 1'b0;
+ "INV": muxwre = ~WRE;
+ default: muxwre = WRE;
+ endcase
+
+
+ always @(posedge muxwck)
+ if (muxwre)
+ mem[{WAD3, WAD2, WAD1, WAD0}] <= {DI1, DI0};
+
+ assign {DO1, DO0} = mem[{RAD3, RAD2, RAD1, RAD0}];
+endmodule
+
+// ---------------------------------------
+
+module PFUMX (input ALUT, BLUT, C0, output Z);
+ assign Z = C0 ? ALUT : BLUT;
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_DPR16X4 (
+ input [3:0] DI,
+ input [3:0] WAD,
+ input WRE, WCK,
+ input [3:0] RAD,
+ output [3:0] DO
+);
+ parameter WCKMUX = "WCK";
+ parameter WREMUX = "WRE";
+ parameter [63:0] INITVAL = 64'h0000000000000000;
+
+ reg [3:0] mem[15:0];
+
+ integer i;
+ initial begin
+ for (i = 0; i < 16; i = i + 1)
+ mem[i] <= {INITVAL[i+3], INITVAL[i+2], INITVAL[i+1], INITVAL[i]};
+ end
+
+ wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
+
+ reg muxwre;
+ always @(*)
+ case (WREMUX)
+ "1": muxwre = 1'b1;
+ "0": muxwre = 1'b0;
+ "INV": muxwre = ~WRE;
+ default: muxwre = WRE;
+ endcase
+
+ always @(posedge muxwck)
+ if (muxwre)
+ mem[WAD] <= DI;
+
+ assign DO = mem[RAD];
+endmodule
+
+// ---------------------------------------
+
+module DPR16X4C (
+ input [3:0] DI,
+ input WCK, WRE,
+ input [3:0] RAD,
+ input [3:0] WAD,
+ output [3:0] DO
+);
+ // For legacy Lattice compatibility, INITIVAL is a hex
+ // string rather than a numeric parameter
+ parameter INITVAL = "0x0000000000000000";
+
+ function [63:0] convert_initval;
+ input [143:0] hex_initval;
+ reg done;
+ reg [63:0] temp;
+ reg [7:0] char;
+ integer i;
+ begin
+ done = 1'b0;
+ temp = 0;
+ for (i = 0; i < 16; i = i + 1) begin
+ if (!done) begin
+ char = hex_initval[8*i +: 8];
+ if (char == "x") begin
+ done = 1'b1;
+ end else begin
+ if (char >= "0" && char <= "9")
+ temp[4*i +: 4] = char - "0";
+ else if (char >= "A" && char <= "F")
+ temp[4*i +: 4] = 10 + char - "A";
+ else if (char >= "a" && char <= "f")
+ temp[4*i +: 4] = 10 + char - "a";
+ end
+ end
+ end
+ convert_initval = temp;
+ end
+ endfunction
+
+ localparam conv_initval = convert_initval(INITVAL);
+
+ reg [3:0] ram[0:15];
+ integer i;
+ initial begin
+ for (i = 0; i < 15; i = i + 1) begin
+ ram[i] <= conv_initval[4*i +: 4];
+ end
+ end
+
+ always @(posedge WCK)
+ if (WRE)
+ ram[WAD] <= DI;
+
+ assign DO = ram[RAD];
+
+endmodule
+
+// ---------------------------------------
+
+module LUT2(input A, B, output Z);
+ parameter [3:0] INIT = 4'h0;
+ wire [1:0] s1 = B ? INIT[ 3:2] : INIT[1:0];
+ assign Z = A ? s1[1] : s1[0];
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
+ parameter GSR = "ENABLED";
+ parameter [127:0] CEMUX = "1";
+ parameter CLKMUX = "CLK";
+ parameter LSRMUX = "LSR";
+ parameter SRMODE = "LSR_OVER_CE";
+ parameter REGSET = "RESET";
+
+ reg muxce;
+ always @(*)
+ case (CEMUX)
+ "1": muxce = 1'b1;
+ "0": muxce = 1'b0;
+ "INV": muxce = ~CE;
+ default: muxce = CE;
+ endcase
+
+ wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
+ wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
+
+ localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0;
+
+ initial Q = srval;
+
+ generate
+ if (SRMODE == "ASYNC") begin
+ always @(posedge muxclk, posedge muxlsr)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end else begin
+ always @(posedge muxclk)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end
+ endgenerate
+endmodule
+
+// ---------------------------------------
+
+module OBZ(input I, T, output O);
+assign O = T ? 1'bz : I;
+endmodule
+
+// ---------------------------------------
+
+module IB(input I, output O);
+assign O = I;
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_IO(
+ inout B,
+ input I,
+ input T,
+ output O
+);
+ parameter DIR = "INPUT";
+
+ generate
+ if (DIR == "INPUT") begin
+ assign B = 1'bz;
+ assign O = B;
+ end else if (DIR == "OUTPUT") begin
+ assign B = T ? 1'bz : I;
+ assign O = 1'bx;
+ end else if (DIR == "INOUT") begin
+ assign B = T ? 1'bz : I;
+ assign O = B;
+ end else begin
+ ERROR_UNKNOWN_IO_MODE error();
+ end
+ endgenerate
+
+endmodule
+
+// ---------------------------------------
+
+module OB(input I, output O);
+assign O = I;
+endmodule
+
+// ---------------------------------------
+
+module BB(input I, T, output O, inout B);
+assign B = T ? 1'bz : I;
+assign O = B;
+endmodule
+
+// ---------------------------------------
+
+module INV(input A, output Z);
+ assign Z = !A;
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_SLICE(
+ input A0, B0, C0, D0,
+ input A1, B1, C1, D1,
+ input M0, M1,
+ input FCI, FXA, FXB,
+
+ input CLK, LSR, CE,
+ input DI0, DI1,
+
+ input WD0, WD1,
+ input WAD0, WAD1, WAD2, WAD3,
+ input WRE, WCK,
+
+ output F0, Q0,
+ output F1, Q1,
+ output FCO, OFX0, OFX1,
+
+ output WDO0, WDO1, WDO2, WDO3,
+ output WADO0, WADO1, WADO2, WADO3
+);
+
+ parameter MODE = "LOGIC";
+ parameter GSR = "ENABLED";
+ parameter SRMODE = "LSR_OVER_CE";
+ parameter [127:0] CEMUX = "1";
+ parameter CLKMUX = "CLK";
+ parameter LSRMUX = "LSR";
+ parameter LUT0_INITVAL = 16'h0000;
+ parameter LUT1_INITVAL = 16'h0000;
+ parameter REG0_SD = "0";
+ parameter REG1_SD = "0";
+ parameter REG0_REGSET = "RESET";
+ parameter REG1_REGSET = "RESET";
+ parameter [127:0] CCU2_INJECT1_0 = "NO";
+ parameter [127:0] CCU2_INJECT1_1 = "NO";
+ parameter WREMUX = "WRE";
+
+ function [15:0] permute_initval;
+ input [15:0] initval;
+ integer i;
+ begin
+ for (i = 0; i < 16; i = i + 1) begin
+ permute_initval[{i[0], i[2], i[1], i[3]}] = initval[i];
+ end
+ end
+ endfunction
+
+ generate
+ if (MODE == "LOGIC") begin
+ // LUTs
+ LUT4 #(
+ .INIT(LUT0_INITVAL)
+ ) lut4_0 (
+ .A(A0), .B(B0), .C(C0), .D(D0),
+ .Z(F0)
+ );
+ LUT4 #(
+ .INIT(LUT1_INITVAL)
+ ) lut4_1 (
+ .A(A1), .B(B1), .C(C1), .D(D1),
+ .Z(F1)
+ );
+ // LUT expansion muxes
+ PFUMX lut5_mux (.ALUT(F1), .BLUT(F0), .C0(M0), .Z(OFX0));
+ L6MUX21 lutx_mux (.D0(FXA), .D1(FXB), .SD(M1), .Z(OFX1));
+ end else if (MODE == "CCU2") begin
+ CCU2C #(
+ .INIT0(LUT0_INITVAL),
+ .INIT1(LUT1_INITVAL),
+ .INJECT1_0(CCU2_INJECT1_0),
+ .INJECT1_1(CCU2_INJECT1_1)
+ ) ccu2c_i (
+ .CIN(FCI),
+ .A0(A0), .B0(B0), .C0(C0), .D0(D0),
+ .A1(A1), .B1(B1), .C1(C1), .D1(D1),
+ .S0(F0), .S1(F1),
+ .COUT(FCO)
+ );
+ end else if (MODE == "RAMW") begin
+ assign WDO0 = C1;
+ assign WDO1 = A1;
+ assign WDO2 = D1;
+ assign WDO3 = B1;
+ assign WADO0 = D0;
+ assign WADO1 = B0;
+ assign WADO2 = C0;
+ assign WADO3 = A0;
+ end else if (MODE == "DPRAM") begin
+ TRELLIS_RAM16X2 #(
+ .INITVAL_0(permute_initval(LUT0_INITVAL)),
+ .INITVAL_1(permute_initval(LUT1_INITVAL)),
+ .WREMUX(WREMUX)
+ ) ram_i (
+ .DI0(WD0), .DI1(WD1),
+ .WAD0(WAD0), .WAD1(WAD1), .WAD2(WAD2), .WAD3(WAD3),
+ .WRE(WRE), .WCK(WCK),
+ .RAD0(D0), .RAD1(B0), .RAD2(C0), .RAD3(A0),
+ .DO0(F0), .DO1(F1)
+ );
+ // TODO: confirm RAD and INITVAL ordering
+ // DPRAM mode contract?
+ always @(*) begin
+ assert(A0==A1);
+ assert(B0==B1);
+ assert(C0==C1);
+ assert(D0==D1);
+ end
+ end else begin
+ ERROR_UNKNOWN_SLICE_MODE error();
+ end
+ endgenerate
+
+ // FF input selection muxes
+ wire muxdi0 = (REG0_SD == "1") ? DI0 : M0;
+ wire muxdi1 = (REG1_SD == "1") ? DI1 : M1;
+ // Flipflops
+ TRELLIS_FF #(
+ .GSR(GSR),
+ .CEMUX(CEMUX),
+ .CLKMUX(CLKMUX),
+ .LSRMUX(LSRMUX),
+ .SRMODE(SRMODE),
+ .REGSET(REG0_REGSET)
+ ) ff_0 (
+ .CLK(CLK), .LSR(LSR), .CE(CE),
+ .DI(muxdi0),
+ .Q(Q0)
+ );
+ TRELLIS_FF #(
+ .GSR(GSR),
+ .CEMUX(CEMUX),
+ .CLKMUX(CLKMUX),
+ .LSRMUX(LSRMUX),
+ .SRMODE(SRMODE),
+ .REGSET(REG1_REGSET)
+ ) ff_1 (
+ .CLK(CLK), .LSR(LSR), .CE(CE),
+ .DI(muxdi1),
+ .Q(Q1)
+ );
+endmodule
+
diff --git a/techlibs/ecp5/dram.txt b/techlibs/ecp5/dram.txt
new file mode 100644
index 000000000..b3252fa9a
--- /dev/null
+++ b/techlibs/ecp5/dram.txt
@@ -0,0 +1,16 @@
+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
+
+match $__TRELLIS_DPR16X4
+ make_outreg
+endmatch
diff --git a/techlibs/ecp5/drams_map.v b/techlibs/ecp5/drams_map.v
new file mode 100644
index 000000000..3b3de831f
--- /dev/null
+++ b/techlibs/ecp5/drams_map.v
@@ -0,0 +1,28 @@
+module \$__TRELLIS_DPR16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter [63:0] INIT = 64'bx;
+ parameter CLKPOL2 = 1;
+ input CLK1;
+
+ input [3:0] A1ADDR;
+ output [3:0] A1DATA;
+
+ input [3:0] B1ADDR;
+ input [3:0] B1DATA;
+ input B1EN;
+
+ localparam WCKMUX = CLKPOL2 ? "WCK" : "INV";
+
+ TRELLIS_DPR16X4 #(
+ .INITVAL(INIT),
+ .WCKMUX(WCKMUX),
+ .WREMUX("WRE")
+ ) _TECHMAP_REPLACE_ (
+ .RAD(A1ADDR),
+ .DO(A1DATA),
+
+ .WAD(B1ADDR),
+ .DI(B1DATA),
+ .WCK(CLK1),
+ .WRE(B1EN)
+ );
+endmodule
diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc
new file mode 100644
index 000000000..a13dd8d41
--- /dev/null
+++ b/techlibs/ecp5/synth_ecp5.cc
@@ -0,0 +1,331 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Clifford Wolf <dave@ds0.me>
+ *
+ * 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/celltypes.h"
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct SynthEcp5Pass : public ScriptPass
+{
+ SynthEcp5Pass() : ScriptPass("synth_ecp5", "synthesis for ECP5 FPGAs") { }
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_ecp5 [options]\n");
+ log("\n");
+ log("This command runs synthesis for ECP5 FPGAs.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module\n");
+ log("\n");
+ log(" -blif <file>\n");
+ log(" write the design to the specified BLIF file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -edif <file>\n");
+ log(" write the design to the specified EDIF file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -json <file>\n");
+ log(" write the design to the specified JSON file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\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(" -noflatten\n");
+ log(" do not flatten design before synthesis\n");
+ log("\n");
+ log(" -retime\n");
+ log(" run 'abc' with -dff option\n");
+ log("\n");
+ log(" -noccu2\n");
+ log(" do not use CCU2 cells in output netlist\n");
+ log("\n");
+ log(" -nodffe\n");
+ log(" do not use flipflops with CE in output netlist\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use BRAM cells in output netlist\n");
+ log("\n");
+ log(" -nodram\n");
+ log(" do not use distributed RAM cells in output netlist\n");
+ log("\n");
+ log(" -nomux\n");
+ log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
+ log("\n");
+ log(" -abc2\n");
+ log(" run two passes of 'abc' for slightly improved logic density\n");
+ log("\n");
+ log(" -vpr\n");
+ log(" generate an output netlist (and BLIF file) suitable for VPR\n");
+ log(" (this feature is experimental and incomplete)\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;
+ bool noccu2, nodffe, nobram, nodram, nomux, flatten, retime, abc2, vpr;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ blif_file = "";
+ edif_file = "";
+ json_file = "";
+ noccu2 = false;
+ nodffe = false;
+ nobram = false;
+ nodram = false;
+ nomux = false;
+ flatten = true;
+ retime = false;
+ abc2 = false;
+ vpr = false;
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ string run_from, run_to;
+ clear_flags();
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-top" && argidx+1 < args.size()) {
+ top_opt = "-top " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-blif" && argidx+1 < args.size()) {
+ blif_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-edif" && argidx+1 < args.size()) {
+ edif_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-json" && argidx+1 < args.size()) {
+ json_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] == "-flatten") {
+ flatten = true;
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ flatten = false;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
+ if (args[argidx] == "-noccu2") {
+ noccu2 = true;
+ continue;
+ }
+ if (args[argidx] == "-nodffe") {
+ nodffe = true;
+ continue;
+ }
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-nodram") {
+ nodram = true;
+ continue;
+ }
+ if (args[argidx] == "-nomux") {
+ nomux = true;
+ continue;
+ }
+ if (args[argidx] == "-abc2") {
+ abc2 = true;
+ continue;
+ }
+ if (args[argidx] == "-vpr") {
+ vpr = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (!design->full_selection())
+ log_cmd_error("This comannd only operates on fully selected designs!\n");
+
+ log_header(design, "Executing SYNTH_ECP5 pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() YS_OVERRIDE
+ {
+ if (check_label("begin"))
+ {
+ run("read_verilog -lib +/ecp5/cells_sim.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <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");
+ }
+
+ if (!nobram && check_label("bram", "(skip if -nobram)"))
+ {
+ //TODO
+#if 0
+ run("memory_bram -rules +/ecp5/brams.txt");
+ run("techmap -map +/ecp5/brams_map.v");
+#endif
+ }
+
+ if (!nodram && check_label("dram", "(skip if -nodram)"))
+ {
+ run("memory_bram -rules +/ecp5/dram.txt");
+ run("techmap -map +/ecp5/drams_map.v");
+ }
+
+ if (check_label("fine"))
+ {
+ run("opt -fast -mux_undef -undriven -fine");
+ run("memory_map");
+ run("opt -undriven -fine");
+ if (noccu2)
+ run("techmap");
+ else
+ run("techmap -map +/techmap.v -map +/ecp5/arith_map.v");
+ if (retime || help_mode)
+ 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 $__DFFS_*");
+ run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
+ run("opt_expr -mux_undef");
+ run("simplemap");
+ // TODO
+#if 0
+ run("ecp5_ffinit");
+#endif
+ }
+
+ if (check_label("map_luts"))
+ {
+ if (abc2 || help_mode) {
+ run("abc", " (only if -abc2)");
+ }
+ //TODO
+#if 0
+ run("techmap -map +/ecp5/latches_map.v");
+#endif
+ if (nomux)
+ run("abc -lut 4");
+ else
+ run("abc -lut 4:7");
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ 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");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("blif"))
+ {
+ if (!blif_file.empty() || help_mode) {
+ if (vpr || help_mode) {
+ run(stringf("opt_clean -purge"),
+ " (vpr mode)");
+ run(stringf("write_blif -attr -cname -conn -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (vpr mode)");
+ }
+ if (!vpr)
+ run(stringf("write_blif -gates -attr -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (non-vpr mode)");
+ }
+ }
+
+ if (check_label("edif"))
+ {
+ if (!edif_file.empty() || help_mode)
+ run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
+ }
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
+ }
+} SynthEcp5Pass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 44dec265d..793f345be 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") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -61,14 +61,14 @@ struct SynthGowinPass : public ScriptPass
string top_opt, vout_file;
bool retime;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
vout_file = "";
retime = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -111,7 +111,7 @@ struct SynthGowinPass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
diff --git a/techlibs/greenpak4/greenpak4_dffinv.cc b/techlibs/greenpak4/greenpak4_dffinv.cc
index 7d9d7d5b0..d57e978a0 100644
--- a/techlibs/greenpak4/greenpak4_dffinv.cc
+++ b/techlibs/greenpak4/greenpak4_dffinv.cc
@@ -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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing GREENPAK4_DFFINV pass (merge input/output inverters into FF/latch cells).\n");
diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc
index 5e0e9e5d5..b91d5273a 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") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -70,7 +70,7 @@ struct SynthGreenPAK4Pass : public ScriptPass
string top_opt, part, json_file;
bool flatten, retime;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
part = "SLG46621V";
@@ -79,7 +79,7 @@ struct SynthGreenPAK4Pass : public ScriptPass
retime = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -133,7 +133,7 @@ struct SynthGreenPAK4Pass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v
index 6550b75cf..d0ddfd02e 100644
--- a/techlibs/ice40/cells_map.v
+++ b/techlibs/ice40/cells_map.v
@@ -27,7 +27,7 @@ module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (
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_SB_LUT4
+`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index 814895e70..e0a07af32 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -1,6 +1,6 @@
-`define SB_DFF_REG reg Q = 0;
-// `define SB_DFF_REG reg Q;
+`define SB_DFF_REG reg Q = 0
+// `define SB_DFF_REG reg Q
// SiliconBlue IO Cells
@@ -132,21 +132,18 @@ endmodule
// Positive Edge SiliconBlue FF Cells
-module SB_DFF (output Q, input C, D);
- `SB_DFF_REG
+module SB_DFF (output `SB_DFF_REG, input C, D);
always @(posedge C)
Q <= D;
endmodule
-module SB_DFFE (output Q, input C, E, D);
- `SB_DFF_REG
+module SB_DFFE (output `SB_DFF_REG, input C, E, D);
always @(posedge C)
if (E)
Q <= D;
endmodule
-module SB_DFFSR (output Q, input C, R, D);
- `SB_DFF_REG
+module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
always @(posedge C)
if (R)
Q <= 0;
@@ -154,8 +151,7 @@ module SB_DFFSR (output Q, input C, R, D);
Q <= D;
endmodule
-module SB_DFFR (output Q, input C, R, D);
- `SB_DFF_REG
+module SB_DFFR (output `SB_DFF_REG, input C, R, D);
always @(posedge C, posedge R)
if (R)
Q <= 0;
@@ -163,8 +159,7 @@ module SB_DFFR (output Q, input C, R, D);
Q <= D;
endmodule
-module SB_DFFSS (output Q, input C, S, D);
- `SB_DFF_REG
+module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
always @(posedge C)
if (S)
Q <= 1;
@@ -172,8 +167,7 @@ module SB_DFFSS (output Q, input C, S, D);
Q <= D;
endmodule
-module SB_DFFS (output Q, input C, S, D);
- `SB_DFF_REG
+module SB_DFFS (output `SB_DFF_REG, input C, S, D);
always @(posedge C, posedge S)
if (S)
Q <= 1;
@@ -181,8 +175,7 @@ module SB_DFFS (output Q, input C, S, D);
Q <= D;
endmodule
-module SB_DFFESR (output Q, input C, E, R, D);
- `SB_DFF_REG
+module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
always @(posedge C)
if (E) begin
if (R)
@@ -192,8 +185,7 @@ module SB_DFFESR (output Q, input C, E, R, D);
end
endmodule
-module SB_DFFER (output Q, input C, E, R, D);
- `SB_DFF_REG
+module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
always @(posedge C, posedge R)
if (R)
Q <= 0;
@@ -201,8 +193,7 @@ module SB_DFFER (output Q, input C, E, R, D);
Q <= D;
endmodule
-module SB_DFFESS (output Q, input C, E, S, D);
- `SB_DFF_REG
+module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
always @(posedge C)
if (E) begin
if (S)
@@ -212,8 +203,7 @@ module SB_DFFESS (output Q, input C, E, S, D);
end
endmodule
-module SB_DFFES (output Q, input C, E, S, D);
- `SB_DFF_REG
+module SB_DFFES (output `SB_DFF_REG, input C, E, S, D);
always @(posedge C, posedge S)
if (S)
Q <= 1;
@@ -223,21 +213,18 @@ endmodule
// Negative Edge SiliconBlue FF Cells
-module SB_DFFN (output Q, input C, D);
- `SB_DFF_REG
+module SB_DFFN (output `SB_DFF_REG, input C, D);
always @(negedge C)
Q <= D;
endmodule
-module SB_DFFNE (output Q, input C, E, D);
- `SB_DFF_REG
+module SB_DFFNE (output `SB_DFF_REG, input C, E, D);
always @(negedge C)
if (E)
Q <= D;
endmodule
-module SB_DFFNSR (output Q, input C, R, D);
- `SB_DFF_REG
+module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
always @(negedge C)
if (R)
Q <= 0;
@@ -245,8 +232,7 @@ module SB_DFFNSR (output Q, input C, R, D);
Q <= D;
endmodule
-module SB_DFFNR (output Q, input C, R, D);
- `SB_DFF_REG
+module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
always @(negedge C, posedge R)
if (R)
Q <= 0;
@@ -254,8 +240,7 @@ module SB_DFFNR (output Q, input C, R, D);
Q <= D;
endmodule
-module SB_DFFNSS (output Q, input C, S, D);
- `SB_DFF_REG
+module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
always @(negedge C)
if (S)
Q <= 1;
@@ -263,8 +248,7 @@ module SB_DFFNSS (output Q, input C, S, D);
Q <= D;
endmodule
-module SB_DFFNS (output Q, input C, S, D);
- `SB_DFF_REG
+module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
always @(negedge C, posedge S)
if (S)
Q <= 1;
@@ -272,8 +256,7 @@ module SB_DFFNS (output Q, input C, S, D);
Q <= D;
endmodule
-module SB_DFFNESR (output Q, input C, E, R, D);
- `SB_DFF_REG
+module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
always @(negedge C)
if (E) begin
if (R)
@@ -283,8 +266,7 @@ module SB_DFFNESR (output Q, input C, E, R, D);
end
endmodule
-module SB_DFFNER (output Q, input C, E, R, D);
- `SB_DFF_REG
+module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
always @(negedge C, posedge R)
if (R)
Q <= 0;
@@ -292,8 +274,7 @@ module SB_DFFNER (output Q, input C, E, R, D);
Q <= D;
endmodule
-module SB_DFFNESS (output Q, input C, E, S, D);
- `SB_DFF_REG
+module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
always @(negedge C)
if (E) begin
if (S)
@@ -303,8 +284,7 @@ module SB_DFFNESS (output Q, input C, E, S, D);
end
endmodule
-module SB_DFFNES (output Q, input C, E, S, D);
- `SB_DFF_REG
+module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D);
always @(negedge C, posedge S)
if (S)
Q <= 1;
@@ -677,7 +657,12 @@ module ICESTORM_LC (
parameter [0:0] SET_NORESET = 0;
parameter [0:0] ASYNC_SR = 0;
- wire COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && CIN) : 1'bx;
+ parameter [0:0] CIN_CONST = 0;
+ parameter [0:0] CIN_SET = 0;
+
+ wire mux_cin = CIN_CONST ? CIN_SET : CIN;
+
+ assign COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && mux_cin) : 1'bx;
wire [7:0] lut_s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
wire [3:0] lut_s2 = I2 ? lut_s3[ 7:4] : lut_s3[3:0];
@@ -935,19 +920,40 @@ parameter A_SIGNED = 1'b0;
parameter B_SIGNED = 1'b0;
endmodule
-(* blackbox *)
-module SB_SPRAM256KA(
+module SB_SPRAM256KA (
input [13:0] ADDRESS,
input [15:0] DATAIN,
input [3:0] MASKWREN,
- input WREN,
- input CHIPSELECT,
- input CLOCK,
- input STANDBY,
- input SLEEP,
- input POWEROFF,
- output [15:0] DATAOUT
+ input WREN, CHIPSELECT, CLOCK, STANDBY, SLEEP, POWEROFF,
+ output reg [15:0] DATAOUT
);
+`ifndef BLACKBOX
+ reg [15:0] mem [0:16383];
+ wire off = SLEEP || !POWEROFF;
+ integer i;
+
+ always @(negedge POWEROFF) begin
+ for (i = 0; i <= 16383; i = i+1)
+ mem[i] = 'bx;
+ end
+
+ always @(posedge CLOCK, posedge off) begin
+ if (off) begin
+ DATAOUT <= 0;
+ end else
+ 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
endmodule
(* blackbox *)
@@ -1246,4 +1252,3 @@ module SB_IO_OD (
endgenerate
`endif
endmodule
-
diff --git a/techlibs/ice40/ice40_ffinit.cc b/techlibs/ice40/ice40_ffinit.cc
index c914b20e8..3089d8932 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ICE40_FFINIT pass (implement FF init values).\n");
diff --git a/techlibs/ice40/ice40_ffssr.cc b/techlibs/ice40/ice40_ffssr.cc
index 9afbc0fce..668df09dd 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") { }
- virtual void help()
+ 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");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ICE40_FFSSR pass (merge synchronous set/reset into FF cells).\n");
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index ae72f5d64..162740059 100644
--- a/techlibs/ice40/ice40_opt.cc
+++ b/techlibs/ice40/ice40_opt.cc
@@ -26,6 +26,13 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+static SigBit get_bit_or_zero(const SigSpec &sig)
+{
+ if (GetSize(sig) == 0)
+ return State::S0;
+ return sig[0];
+}
+
static void run_ice40_opts(Module *module, bool unlut_mode)
{
pool<SigBit> optimized_co;
@@ -45,7 +52,11 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
SigSpec non_const_inputs, replacement_output;
int count_zeros = 0, count_ones = 0;
- SigBit inbit[3] = {cell->getPort("\\I0"), cell->getPort("\\I1"), cell->getPort("\\CI")};
+ SigBit inbit[3] = {
+ 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) {
if (inbit[i] == State::S1)
@@ -63,8 +74,8 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
replacement_output = non_const_inputs;
if (GetSize(replacement_output)) {
- optimized_co.insert(sigmap(cell->getPort("\\CO")));
- module->connect(cell->getPort("\\CO"), 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));
@@ -78,10 +89,10 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
{
SigSpec inbits;
- inbits.append(cell->getPort("\\I0"));
- inbits.append(cell->getPort("\\I1"));
- inbits.append(cell->getPort("\\I2"));
- inbits.append(cell->getPort("\\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 (unlut_mode)
@@ -104,8 +115,13 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
cell->unsetParam("\\LUT_INIT");
- cell->setPort("\\A", SigSpec({cell->getPort("\\I3"), cell->getPort("\\I2"), cell->getPort("\\I1"), cell->getPort("\\I0")}));
- cell->setPort("\\Y", cell->getPort("\\O"));
+ 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("\\Y", cell->getPort("\\O")[0]);
cell->unsetPort("\\I0");
cell->unsetPort("\\I1");
cell->unsetPort("\\I2");
@@ -120,7 +136,7 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
struct Ice40OptPass : public Pass {
Ice40OptPass() : Pass("ice40_opt", "iCE40: perform simple optimizations") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -140,7 +156,7 @@ struct Ice40OptPass : public Pass {
log("mapped SB_LUT4 cells back to logic.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string opt_expr_args = "-mux_undef -undriven";
bool unlut_mode = false;
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 0bb0fb139..b0687e5e3 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -29,7 +29,7 @@ struct SynthIce40Pass : public ScriptPass
{
SynthIce40Pass() : ScriptPass("synth_ice40", "synthesis for iCE40 FPGAs") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -45,7 +45,11 @@ struct SynthIce40Pass : public ScriptPass
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -edif <file>\n");
- log(" write the design to the specified edif file. writing of an output file\n");
+ log(" write the design to the specified EDIF file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -json <file>\n");
+ log(" write the design to the specified JSON file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
@@ -62,6 +66,9 @@ struct SynthIce40Pass : public ScriptPass
log(" -nocarry\n");
log(" do not use SB_CARRY cells in output netlist\n");
log("\n");
+ log(" -nodffe\n");
+ log(" do not use SB_DFFE* cells in output netlist\n");
+ log("\n");
log(" -nobram\n");
log(" do not use SB_RAM40_4K* cells in output netlist\n");
log("\n");
@@ -78,15 +85,17 @@ struct SynthIce40Pass : public ScriptPass
log("\n");
}
- string top_opt, blif_file, edif_file;
- bool nocarry, nobram, flatten, retime, abc2, vpr;
+ string top_opt, blif_file, edif_file, json_file;
+ bool nocarry, nodffe, nobram, flatten, retime, abc2, vpr;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
blif_file = "";
edif_file = "";
+ json_file = "";
nocarry = false;
+ nodffe = false;
nobram = false;
flatten = true;
retime = false;
@@ -94,7 +103,7 @@ struct SynthIce40Pass : public ScriptPass
vpr = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -114,6 +123,10 @@ struct SynthIce40Pass : public ScriptPass
edif_file = args[++argidx];
continue;
}
+ if (args[argidx] == "-json" && argidx+1 < args.size()) {
+ json_file = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-run" && argidx+1 < args.size()) {
size_t pos = args[argidx+1].find(':');
if (pos == std::string::npos)
@@ -138,6 +151,10 @@ struct SynthIce40Pass : public ScriptPass
nocarry = true;
continue;
}
+ if (args[argidx] == "-nodffe") {
+ nodffe = true;
+ continue;
+ }
if (args[argidx] == "-nobram") {
nobram = true;
continue;
@@ -165,7 +182,7 @@ struct SynthIce40Pass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
@@ -209,8 +226,9 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_ffs"))
{
run("dffsr2dff");
- run("dff2dffe -direct-match $_DFF_*");
- run("techmap -D NO_SB_LUT4 -map +/ice40/cells_map.v");
+ if (!nodffe)
+ run("dff2dffe -direct-match $_DFF_*");
+ run("techmap -D NO_LUT -map +/ice40/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
run("ice40_ffinit");
@@ -232,9 +250,9 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_cells"))
{
if (vpr)
- run("techmap -D NO_SB_LUT4 -map +/ice40/cells_map.v");
+ run("techmap -D NO_LUT -map +/ice40/cells_map.v");
else
- run("techmap -map +/ice40/cells_map.v", "(with -D NO_SB_LUT4 in vpr mode)");
+ run("techmap -map +/ice40/cells_map.v", "(with -D NO_LUT in vpr mode)");
run("clean");
}
@@ -251,13 +269,15 @@ struct SynthIce40Pass : public ScriptPass
if (!blif_file.empty() || help_mode) {
if (vpr || help_mode) {
run(stringf("opt_clean -purge"),
- " (vpr mode)");
- run(stringf("write_blif %s", help_mode ? "<file-name>" : blif_file.c_str()),
- " (vpr mode)");
+ " (vpr mode)");
+ run(stringf("write_blif -attr -cname -conn -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (vpr mode)");
}
if (!vpr)
run(stringf("write_blif -gates -attr -param %s",
- help_mode ? "<file-name>" : blif_file.c_str()), "(non-vpr mode)");
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (non-vpr mode)");
}
}
@@ -266,6 +286,12 @@ struct SynthIce40Pass : public ScriptPass
if (!edif_file.empty() || help_mode)
run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
}
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
}
} SynthIce40Pass;
diff --git a/techlibs/intel/cyclone10/cells_map.v b/techlibs/intel/cyclone10/cells_map.v
index 8ac5a55ec..c2f6f403c 100644
--- a/techlibs/intel/cyclone10/cells_map.v
+++ b/techlibs/intel/cyclone10/cells_map.v
@@ -16,33 +16,43 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+
// Normal mode DFF negedge clk, negedge reset
module \$_DFF_N_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Normal mode DFF
module \$_DFF_P_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Async Active Low Reset DFF
module \$_DFF_PN0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Async Active High Reset DFF
module \$_DFF_PP0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG)) _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));
+ 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_PP0 (input D, C, E, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
endmodule
// Input buffer map
diff --git a/techlibs/intel/cycloneiv/cells_map.v b/techlibs/intel/cycloneiv/cells_map.v
index b991fbae7..191488430 100644
--- a/techlibs/intel/cycloneiv/cells_map.v
+++ b/techlibs/intel/cycloneiv/cells_map.v
@@ -16,33 +16,43 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+
// Normal mode DFF negedge clk, negedge reset
module \$_DFF_N_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Normal mode DFF
module \$_DFF_P_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Async Active Low Reset DFF
module \$_DFF_PN0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Async Active High Reset DFF
module \$_DFF_PP0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG)) _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));
+ 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_PP0 (input D, C, E, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
endmodule
// Input buffer map
diff --git a/techlibs/intel/cycloneive/arith_map.v b/techlibs/intel/cycloneive/arith_map.v
index 634cec789..b3a11272b 100644
--- a/techlibs/intel/cycloneive/arith_map.v
+++ b/techlibs/intel/cycloneive/arith_map.v
@@ -16,6 +16,48 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
+/* TODO: Describe the following mode */
+module fa
+ (input a_c,
+ input b_c,
+ input cin_c,
+ output cout_t,
+ output sum_x);
+
+ wire a_c;
+ wire b_c;
+ wire cout_t;
+ wire cin_c;
+ wire sum_x;
+ wire VCC;
+
+ assign VCC = 1'b1;
+
+ cycloneiv_lcell_comb gen_sum_0 (.combout(sum_x),
+ .dataa(a_c),
+ .datab(b_c),
+ .datac(cin_c),
+ .datad(VCC));
+ defparam syn__05_.lut_mask = 16'b1001011010010110;
+ defparam syn__05_.sum_lutc_input = "datac";
+
+ cycloneiv_lcell_comb gen_cout_0 (.combout(cout_t),
+ .dataa(cin_c),
+ .datab(b_c),
+ .datac(a_c),
+ .datad(VCC));
+ defparam syn__06_.lut_mask = 16'b1110000011100000;
+ defparam syn__06_.sum_lutc_input = "datac";
+
+endmodule // fa
+
+module f_stage();
+
+endmodule // f_stage
+
+module f_end();
+
+endmodule // f_end
module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO);
parameter A_SIGNED = 0;
@@ -41,8 +83,13 @@ module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO);
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
wire [Y_WIDTH:0] C = {CO, CI};
- cycloneive_lcell_comb #(.lut_mask(16'b0110_0110_1000_1000), .sum_lutc_input("cin")) carry_start (.cout(CO[0]), .dataa(BB[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
- genvar i;
+ fa f0 (.a_c(AA[0]),
+ .b_c(BB[0]),
+ .cin_c(C[0]),
+ .cout_t(C0[1]),
+ .sum_x(Y[0]));
+
+ genvar i;
generate for (i = 1; i < Y_WIDTH; i = i + 1) begin:slice
cycloneive_lcell_comb #(.lut_mask(16'b0101_1010_0101_0000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(CO[i]), .dataa(BB[i]), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[i]));
end endgenerate
diff --git a/techlibs/intel/cycloneive/cells_map.v b/techlibs/intel/cycloneive/cells_map.v
index bf87f5525..abeb92eef 100644
--- a/techlibs/intel/cycloneive/cells_map.v
+++ b/techlibs/intel/cycloneive/cells_map.v
@@ -16,32 +16,43 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+
// Normal mode DFF negedge clk, negedge reset
module \$_DFF_N_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Normal mode DFF
module \$_DFF_P_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
+
// Async Active Low Reset DFF
module \$_DFF_PN0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Async Active High Reset DFF
module \$_DFF_PP0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG)) _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));
+ 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_PP0 (input D, C, E, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
endmodule
// Input buffer map
diff --git a/techlibs/intel/cyclonev/cells_map.v b/techlibs/intel/cyclonev/cells_map.v
index 9fe8db2da..bd60d4e17 100644
--- a/techlibs/intel/cyclonev/cells_map.v
+++ b/techlibs/intel/cyclonev/cells_map.v
@@ -16,33 +16,45 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+// 2) Cyclone V 7-input LUT function was wrong implemented. Removed abc option to map this function \
+// and added the explanation in this file instead. Such function needs to be implemented.
+
// Normal mode DFF negedge clk, negedge reset
module \$_DFF_N_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Normal mode DFF
module \$_DFF_P_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Async Active Low Reset DFF
module \$_DFF_PN0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Async Active High Reset DFF
module \$_DFF_PP0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG)) _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));
+ 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_PP0 (input D, C, E, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
endmodule
// Input buffer map
@@ -61,6 +73,10 @@ module \$lut (A, Y);
parameter LUT = 0;
input [WIDTH-1:0] A;
output Y;
+ wire VCC;
+ wire GND;
+ assign {VCC,GND} = {1'b1,1'b0};
+
generate
if (WIDTH == 1) begin
assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
@@ -72,11 +88,11 @@ module \$lut (A, Y);
(.combout(Y),
.dataa(A[0]),
.datab(A[1]),
- .datac(1'b1),
- .datad(1'b1),
- .datae(1'b1),
- .dataf(1'b1),
- .datag(1'b1));
+ .datac(VCC),
+ .datad(VCC),
+ .datae(VCC),
+ .dataf(VCC),
+ .datag(VCC));
end
else
if(WIDTH == 3) begin
@@ -86,10 +102,10 @@ module \$lut (A, Y);
.dataa(A[0]),
.datab(A[1]),
.datac(A[2]),
- .datad(1'b1),
- .datae(1'b1),
- .dataf(1'b1),
- .datag(1'b1));
+ .datad(VCC),
+ .datae(VCC),
+ .dataf(VCC),
+ .datag(VCC));
end
else
if(WIDTH == 4) begin
@@ -100,9 +116,9 @@ module \$lut (A, Y);
.datab(A[1]),
.datac(A[2]),
.datad(A[3]),
- .datae(1'b1),
- .dataf(1'b1),
- .datag(1'b1));
+ .datae(VCC),
+ .dataf(VCC),
+ .datag(VCC));
end
else
if(WIDTH == 5) begin
@@ -114,8 +130,8 @@ module \$lut (A, Y);
.datac(A[2]),
.datad(A[3]),
.datae(A[4]),
- .dataf(1'b1),
- .datag(1'b1));
+ .dataf(VCC),
+ .datag(VCC));
end
else
if(WIDTH == 6) begin
@@ -128,21 +144,16 @@ module \$lut (A, Y);
.datad(A[3]),
.datae(A[4]),
.dataf(A[5]),
- .datag(1'b1));
+ .datag(VCC));
end
- else
+ /*else
if(WIDTH == 7) begin
- cyclonev_lcell_comb #(.lut_mask(LUT), .shared_arith("off"), .extended_lut("off"))
- _TECHMAP_REPLACE_
- (.combout(Y),
- .dataa(A[0]),
- .datab(A[1]),
- .datac(A[2]),
- .datad(A[3]),
- .datae(A[4]),
- .dataf(A[5]),
- .datag(A[6]));
- end
+ TODO: There's not a just 7-input function on Cyclone V, see the following note:
+ **Extended LUT Mode**
+ Use extended LUT mode to implement a specific set of 7-input functions. The set must
+ be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.
+ [source](Device Interfaces and Integration Basics for Cyclone V Devices).
+ end*/
else
wire _TECHMAP_FAIL_ = 1;
endgenerate
diff --git a/techlibs/intel/max10/cells_map.v b/techlibs/intel/max10/cells_map.v
index 9229fae51..6d604e072 100644
--- a/techlibs/intel/max10/cells_map.v
+++ b/techlibs/intel/max10/cells_map.v
@@ -16,43 +16,53 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+
// Normal mode DFF negedge clk, negedge reset
module \$_DFF_N_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Normal mode DFF
module \$_DFF_P_ (input D, C, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Async Active Low Reset DFF
module \$_DFF_PN0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
endmodule
// Async Active High Reset DFF
module \$_DFF_PP0_ (input D, C, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG)) _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));
+ 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_PP0 (input D, C, E, R, output Q);
parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
endmodule
// Input buffer map
module \$__inpad (input I, output O);
- fiftyfivenm_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
+ fiftyfivenm_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
endmodule
// Output buffer map
module \$__outpad (input I, output O);
- fiftyfivenm_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
+ fiftyfivenm_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
endmodule
// LUT Map
diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc
index 9e632c861..d74f295ec 100644
--- a/techlibs/intel/synth_intel.cc
+++ b/techlibs/intel/synth_intel.cc
@@ -28,7 +28,7 @@ PRIVATE_NAMESPACE_BEGIN
struct SynthIntelPass : public ScriptPass {
SynthIntelPass() : ScriptPass("synth_intel", "synthesis for Intel (Altera) FPGAs.") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -36,7 +36,7 @@ struct SynthIntelPass : public ScriptPass {
log("\n");
log("This command runs synthesis for Intel FPGAs.\n");
log("\n");
- log(" -family < max10 | a10gx | cyclonev | cycloneiv | cycloneive>\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 not family argument specified.\n");
log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
@@ -49,11 +49,19 @@ struct SynthIntelPass : public ScriptPass {
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.\n");
log("\n");
+ log(" -vpr <file>\n");
+ log(" write BLIF files for VPR flow experiments. The synthesized BLIF output file is not\n");
+ log(" compatible with the Quartus flow. Writing of an\n");
+ log(" output file is omitted if this parameter is not specified.\n");
+ log("\n");
log(" -run <from_label>:<to_label>\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(" -noiopads\n");
+ log(" do not use altsyncram cells in output netlist\n");
+ log("\n");
log(" -nobram\n");
log(" do not use altsyncram cells in output netlist\n");
log("\n");
@@ -68,20 +76,22 @@ struct SynthIntelPass : public ScriptPass {
log("\n");
}
- string top_opt, family_opt, vout_file;
- bool retime, flatten, nobram;
+ string top_opt, family_opt, vout_file, blif_file;
+ bool retime, flatten, nobram, noiopads;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
family_opt = "max10";
vout_file = "";
+ blif_file = "";
retime = false;
flatten = true;
nobram = false;
+ noiopads = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -101,6 +111,10 @@ struct SynthIntelPass : public ScriptPass {
vout_file = args[++argidx];
continue;
}
+ if (args[argidx] == "-vpr" && argidx+1 < args.size()) {
+ blif_file = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-run" && argidx+1 < args.size()) {
size_t pos = args[argidx+1].find(':');
if (pos == std::string::npos)
@@ -109,6 +123,10 @@ struct SynthIntelPass : public ScriptPass {
run_to = args[argidx].substr(pos+1);
continue;
}
+ if (args[argidx] == "-noiopads") {
+ noiopads = true;
+ continue;
+ }
if (args[argidx] == "-nobram") {
nobram = true;
continue;
@@ -138,7 +156,7 @@ struct SynthIntelPass : public ScriptPass {
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
@@ -198,7 +216,7 @@ struct SynthIntelPass : public ScriptPass {
if (check_label("map_luts"))
{
if(family_opt=="a10gx" || family_opt=="cyclonev")
- run("abc -luts 2:2,3,6:5,10" + string(retime ? " -dff" : ""));
+ run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
else
run("abc -lut 4" + string(retime ? " -dff" : ""));
run("clean");
@@ -206,7 +224,8 @@ struct SynthIntelPass : public ScriptPass {
if (check_label("map_cells"))
{
- run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I");
+ if (!noiopads)
+ run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(unless -noiopads)");
if(family_opt=="max10")
run("techmap -map +/intel/max10/cells_map.v");
else if(family_opt=="a10gx")
@@ -236,6 +255,15 @@ struct SynthIntelPass : public ScriptPass {
run(stringf("write_verilog -attr2comment -defparam -nohex -decimal -renameprefix syn_ %s",
help_mode ? "<file-name>" : vout_file.c_str()));
}
+
+ if (check_label("vpr"))
+ {
+ if (!blif_file.empty() || help_mode)
+ {
+ run(stringf("opt_clean -purge"));
+ run(stringf("write_blif %s", help_mode ? "<file-name>" : blif_file.c_str()));
+ }
+ }
}
} SynthIntelPass;
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index 8e5a83ce5..0771be0b9 100644
--- a/techlibs/xilinx/cells_map.v
+++ b/techlibs/xilinx/cells_map.v
@@ -15,6 +15,7 @@ module \$_DFF_NP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(
module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
+`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;
@@ -82,3 +83,4 @@ module \$lut (A, Y);
end
endgenerate
endmodule
+`endif
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index b60295ac0..590fe61d2 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -34,9 +34,11 @@ bool check_label(bool &active, std::string run_from, std::string run_to, std::st
return active;
}
-struct SynthXilinxPass : public Pass {
+struct SynthXilinxPass : public Pass
+{
SynthXilinxPass() : Pass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
- virtual void help()
+
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -53,6 +55,14 @@ struct SynthXilinxPass : public Pass {
log(" write the design to the specified edif file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
log("\n");
+ log(" -blif <file>\n");
+ log(" write the design to the specified BLIF file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -vpr\n");
+ log(" generate an output netlist (and BLIF file) suitable for VPR\n");
+ log(" (this feature is experimental and incomplete)\n");
+ log("\n");
log(" -run <from_label>:<to_label>\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");
@@ -102,7 +112,7 @@ struct SynthXilinxPass : public Pass {
log(" clean\n");
log("\n");
log(" map_cells:\n");
- log(" techmap -map +/xilinx/cells_map.v\n");
+ log(" techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n");
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\n");
log(" clean\n");
log("\n");
@@ -114,14 +124,19 @@ struct SynthXilinxPass : public Pass {
log(" edif: (only if -edif)\n");
log(" write_edif <file-name>\n");
log("\n");
+ log(" blif: (only if -blif)\n");
+ log(" write_blif <file-name>\n");
+ log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string top_opt = "-auto-top";
std::string edif_file;
+ std::string blif_file;
std::string run_from, run_to;
bool flatten = false;
bool retime = false;
+ bool vpr = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -134,6 +149,10 @@ struct SynthXilinxPass : public Pass {
edif_file = args[++argidx];
continue;
}
+ if (args[argidx] == "-blif" && argidx+1 < args.size()) {
+ blif_file = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-run" && argidx+1 < args.size()) {
size_t pos = args[argidx+1].find(':');
if (pos == std::string::npos)
@@ -150,6 +169,10 @@ struct SynthXilinxPass : public Pass {
retime = true;
continue;
}
+ if (args[argidx] == "-vpr") {
+ vpr = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -212,7 +235,10 @@ struct SynthXilinxPass : public Pass {
if (check_label(active, run_from, run_to, "map_cells"))
{
- Pass::call(design, "techmap -map +/xilinx/cells_map.v");
+ if (vpr)
+ Pass::call(design, "techmap -D NO_LUT -map +/xilinx/cells_map.v");
+ else
+ Pass::call(design, "techmap -map +/xilinx/cells_map.v");
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT");
Pass::call(design, "clean");
}
@@ -229,6 +255,11 @@ struct SynthXilinxPass : public Pass {
if (!edif_file.empty())
Pass::call(design, stringf("write_edif %s", edif_file.c_str()));
}
+ if (check_label(active, run_from, run_to, "blif"))
+ {
+ if (!blif_file.empty())
+ Pass::call(design, stringf("write_blif %s", edif_file.c_str()));
+ }
log_pop();
}
diff --git a/tests/simple/specify.v b/tests/simple/specify.v
new file mode 100644
index 000000000..f19418d90
--- /dev/null
+++ b/tests/simple/specify.v
@@ -0,0 +1,31 @@
+module test_specify;
+
+specparam a=1;
+
+specify
+endspecify
+
+specify
+(A => B) = ( 1 ) ;
+(A- => B) = ( 1,2 ) ;
+(A+ => B) = ( 1,2,3 ) ;
+(A => B) = (
+ 1.1, 2, 3,
+ 4, 5.5, 6.6
+) ;
+(A => B) = (
+ 1.1, 2, 3,
+ 4, 5.5, 6.6 ,
+ 7.7, 8.8, 9,
+ 10.1, 11, 12
+) ;
+specparam b=1;
+specparam [1:2] asasa=1;
+endspecify
+
+specify
+specparam c=1:2:3;
+endspecify
+
+endmodule
+
diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh
index d0b0a89d7..d6216244f 100755
--- a/tests/tools/autotest.sh
+++ b/tests/tools/autotest.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
libs=""
genvcd=false
@@ -100,7 +100,7 @@ do
echo -n "Test: $bn "
fi
- rm -f ${bn}.{err,log,sikp}
+ rm -f ${bn}.{err,log,skip}
mkdir -p ${bn}.out
rm -rf ${bn}.out/*