diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 2c1483345..2ed92c913 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -6,7 +6,7 @@ body: attributes: value: > - Learn more [here](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) about how to report bugs. We fix well-reported bugs the fastest. + Learn more in our [Reporting bugs](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) docs section. We fix well-reported bugs the fastest. If you have a general question, please ask it on the [Discourse forum](https://yosyshq.discourse.group/). diff --git a/.github/workflows/extra-builds.yml b/.github/workflows/extra-builds.yml index d6bf5226c..7209b3645 100644 --- a/.github/workflows/extra-builds.yml +++ b/.github/workflows/extra-builds.yml @@ -79,8 +79,8 @@ jobs: persist-credentials: false - name: Build run: | - WASI_SDK=wasi-sdk-27.0-x86_64-linux - WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz + WASI_SDK=wasi-sdk-33.0-x86_64-linux + WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-33/wasi-sdk-33.0-x86_64-linux.tar.gz if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi FLEX_VER=2.6.4 diff --git a/.github/workflows/test-compile.yml b/.github/workflows/test-compile.yml index 9c75784bf..99e4973a7 100644 --- a/.github/workflows/test-compile.yml +++ b/.github/workflows/test-compile.yml @@ -44,18 +44,18 @@ jobs: - ubuntu-latest compiler: # oldest supported - - 'clang-10' - - 'gcc-10' + - 'clang-14' + - 'gcc-11' # newest, make sure to update maximum standard step to match - - 'clang-19' - - 'gcc-14' + - 'clang-22' + - 'gcc-15' include: # macOS x86 - os: macos-15-intel - compiler: 'clang-19' + compiler: 'clang-22' # macOS arm - os: macos-latest - compiler: 'clang-19' + compiler: 'clang-22' fail-fast: false steps: - name: Checkout Yosys @@ -74,6 +74,7 @@ jobs: uses: aminya/setup-cpp@v1 with: compiler: ${{ matrix.compiler }} + gcc: ${{ (matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14') && '12' || '' }} - name: Tool versions shell: bash @@ -81,21 +82,26 @@ jobs: $CC --version $CXX --version - # minimum standard - - name: Build C++17 - shell: bash + - name: Fix clang-14 toolchain + if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14' run: | - make config-$CC_SHORT - make -j$procs CXXSTD=c++17 compile-only + echo 'CXXFLAGS=--gcc-toolchain=/usr -isystem /usr/include/c++/12 -isystem /usr/include/x86_64-linux-gnu/c++/12' >> $GITHUB_ENV - # maximum standard, only on newest compilers + # minimum standard - name: Build C++20 - if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-14' }} shell: bash run: | make config-$CC_SHORT make -j$procs CXXSTD=c++20 compile-only + # maximum standard, only on newest compilers + - name: Build C++26 + if: ${{ matrix.compiler == 'clang-22' || matrix.compiler == 'gcc-15' }} + shell: bash + run: | + make config-$CC_SHORT + make -j$procs CXXSTD=c++26 compile-only + test-compile-result: runs-on: ubuntu-latest needs: diff --git a/.github/workflows/test-verific.yml b/.github/workflows/test-verific.yml index 65efca79f..132aac589 100644 --- a/.github/workflows/test-verific.yml +++ b/.github/workflows/test-verific.yml @@ -78,7 +78,7 @@ jobs: - name: Run Verific specific Yosys tests run: | make -C tests/sva - cd tests/svtypes && bash run-test.sh + make -C tests/svtypes - name: Run SBY tests if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }} diff --git a/.github/workflows/wheels/cibw_before_all.sh b/.github/workflows/wheels/cibw_before_all.sh index 1aef650d7..6450ce273 100644 --- a/.github/workflows/wheels/cibw_before_all.sh +++ b/.github/workflows/wheels/cibw_before_all.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e -x # Build-time dependencies diff --git a/Brewfile b/Brewfile index 917f1bdb4..2530b323c 100644 --- a/Brewfile +++ b/Brewfile @@ -9,6 +9,6 @@ brew "python3" brew "uv" brew "xdot" brew "bash" -brew "llvm@20" +brew "llvm" brew "lld" brew "googletest" diff --git a/CHANGELOG b/CHANGELOG index 94e62df4b..01faf44c2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,9 +2,20 @@ List of major changes and improvements between releases ======================================================= -Yosys 0.64 .. Yosys 0.65-dev +Yosys 0.65 .. Yosys 0.66-dev -------------------------- +Yosys 0.64 .. Yosys 0.65 +-------------------------- + * New commands and options + - Added "arith_tree" pass to convert add/sub/macc chains + to carry-save adder trees. + - Removed "-force" option from "share" pass. + + * Various + - read_verilog: support positional assignment patterns + for unpacked arrays. + Yosys 0.63 .. Yosys 0.64 -------------------------- * New commands and options diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6eadbec31..849d1fb00 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,59 +5,11 @@ first time contributing to an open source project, please take a look at the following guide about the basics: https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project. -## Asking questions +Check out our [Contributing guidelines](https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html) to learn the best ways to -If you have a question about how to use Yosys, please ask on our [Discourse forum](https://yosyshq.discourse.group/). -The Discourse is also a great place to ask questions about developing or -contributing to Yosys. ++ get help ++ report bugs ++ contribute code ++ review code -We have open [dev 'jour fixe' (JF) meetings](https://docs.google.com/document/d/1SapA6QAsJcsgwsdKJDgnGR2mr97pJjV4eeXg_TVJhRU/edit?usp=sharing) where developers from YosysHQ and the -community come together to discuss open issues and PRs. This is also a good -place to talk to us about how to implement larger PRs. - -## Using the issue tracker - -The [issue tracker](https://github.com/YosysHQ/yosys/issues) is used for -tracking bugs or other problems with Yosys or its documentation. It is also the -place to go for requesting new features. - -### Bug reports - -Learn more [here](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) about how to report bugs. We fix well-reported bugs the fastest. - -## Contributing code - -If you're adding complex functionality, or modifying core parts of Yosys, -we highly recommend discussing your motivation and approach -ahead of time on the [Discourse forum](https://yosyshq.discourse.group/). - -### Using pull requests - -If you are working on something to add to Yosys, or fix something that isn't -working quite right, -make a [pull request (PR)](https://github.com/YosysHQ/yosys/pulls). - -An open PR, even as a draft, tells everyone that you're working on it and they -don't have to. It can also be a useful way to solicit feedback on in-progress -changes. See above to find the best way to [ask us questions](#asking-questions). - -### Continuous integration - -[Continuous Integration (CI)](https://github.com/YosysHQ/yosys/actions) tools -automatically compile Yosys and run it with the full suite of tests. -If you're a first time contributor, a maintainer has to trigger a run for you. -We test on various platforms, compilers. Sanitizer builds are only tested -on the main branch. - -### Labels - -We use [labels](https://github.com/YosysHQ/yosys/labels) to help categorise -issues and PRs. If a label seems relevant to your work, please do add it; this -also includes the labels beginning with 'status-'. The 'merge-' labels are used -by maintainers for tracking and communicating which PRs are ready and pending -merge; please do not use these labels if you are not a maintainer. - - -### Coding style - -Learn more [here](https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html). +If you're reading this file offline and don't have internet access, you can [read the contributing.rst file locally](docs/source/yosys_internals/extending_yosys/contributing.rst). diff --git a/Makefile b/Makefile index fc5172cc0..afbc11005 100644 --- a/Makefile +++ b/Makefile @@ -103,8 +103,8 @@ VPATH := $(YOSYS_SRC) # Unit test UNITESTPATH := $(YOSYS_SRC)/tests/unit -export CXXSTD ?= c++17 -CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include +export CXXSTD ?= c++20 +CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -Werror=unused -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include LIBS := $(LIBS) -lstdc++ -lm PLUGIN_LINKFLAGS := PLUGIN_LIBS := @@ -161,7 +161,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.64 +YOSYS_VER := 0.65 ifneq (, $(shell command -v git 2>/dev/null)) ifneq (, $(shell git rev-parse --git-dir 2>/dev/null)) @@ -291,18 +291,19 @@ ifeq ($(WASI_SDK),) CXX = clang++ AR = llvm-ar RANLIB = llvm-ranlib -WASIFLAGS := -target wasm32-wasi $(WASIFLAGS) +WASIFLAGS := -target wasm32-wasip1 $(WASIFLAGS) else CXX = $(WASI_SDK)/bin/clang++ AR = $(WASI_SDK)/bin/ar RANLIB = $(WASI_SDK)/bin/ranlib endif -CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) $(OPT_LEVEL) -D_WASI_EMULATED_PROCESS_CLOCKS $(filter-out -fPIC,$(CXXFLAGS)) -LINKFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LINKFLAGS)) +CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) $(OPT_LEVEL) -D_WASI_EMULATED_PROCESS_CLOCKS -fwasm-exceptions -mllvm -wasm-use-legacy-eh=false $(filter-out -fPIC,$(CXXFLAGS)) +LINKFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LINKFLAGS)) -fwasm-exceptions -lunwind LIBS := -lwasi-emulated-process-clocks $(filter-out -lrt,$(LIBS)) ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)" ABCMKARGS += ARCHFLAGS="$(WASIFLAGS) -D_WASI_EMULATED_PROCESS_CLOCKS -DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING -DABC_NO_RLIMIT" ABCMKARGS += OPTFLAGS="-Os" +LTOFLAGS = EXE = .wasm DISABLE_SPAWN := 1 @@ -918,110 +919,15 @@ else ABCOPT="" endif -# Tests that generate .mk with tests/gen-tests-makefile.sh -MK_TEST_DIRS = -MK_TEST_DIRS += tests/arch/analogdevices -MK_TEST_DIRS += tests/arch/anlogic -MK_TEST_DIRS += tests/arch/ecp5 -MK_TEST_DIRS += tests/arch/efinix -MK_TEST_DIRS += tests/arch/gatemate -MK_TEST_DIRS += tests/arch/gowin -MK_TEST_DIRS += tests/arch/ice40 -MK_TEST_DIRS += tests/arch/intel_alm -MK_TEST_DIRS += tests/arch/machxo2 -MK_TEST_DIRS += tests/arch/microchip -MK_TEST_DIRS += tests/arch/nanoxplore -MK_TEST_DIRS += tests/arch/nexus -MK_TEST_DIRS += tests/arch/quicklogic/pp3 -MK_TEST_DIRS += tests/arch/quicklogic/qlf_k6n10f -MK_TEST_DIRS += tests/arch/xilinx -MK_TEST_DIRS += tests/bugpoint -MK_TEST_DIRS += tests/opt -MK_TEST_DIRS += tests/sat -MK_TEST_DIRS += tests/sdc -MK_TEST_DIRS += tests/sim -MK_TEST_DIRS += tests/svtypes -MK_TEST_DIRS += tests/techmap -MK_TEST_DIRS += tests/various -MK_TEST_DIRS += tests/rtlil -ifeq ($(ENABLE_VERIFIC),1) -ifneq ($(YOSYS_NOVERIFIC),1) -MK_TEST_DIRS += tests/verific -endif -endif -MK_TEST_DIRS += tests/verilog - -# Tests that don't generate .mk -SH_TEST_DIRS = -SH_TEST_DIRS += tests/simple -SH_TEST_DIRS += tests/simple_abc9 -SH_TEST_DIRS += tests/hana -SH_TEST_DIRS += tests/asicworld -# SH_TEST_DIRS += tests/realmath -SH_TEST_DIRS += tests/share -SH_TEST_DIRS += tests/opt_share -SH_TEST_DIRS += tests/fsm -SH_TEST_DIRS += tests/memlib -SH_TEST_DIRS += tests/bram -SH_TEST_DIRS += tests/svinterfaces -SH_TEST_DIRS += tests/xprop -SH_TEST_DIRS += tests/select -SH_TEST_DIRS += tests/peepopt -SH_TEST_DIRS += tests/proc -SH_TEST_DIRS += tests/blif -SH_TEST_DIRS += tests/arch -SH_TEST_DIRS += tests/rpc -SH_TEST_DIRS += tests/memfile -SH_TEST_DIRS += tests/fmt -SH_TEST_DIRS += tests/cxxrtl -SH_TEST_DIRS += tests/liberty -ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) -SH_TEST_DIRS += tests/functional -endif - -# Tests that don't generate .mk and need special args -SH_ABC_TEST_DIRS = -SH_ABC_TEST_DIRS += tests/memories -SH_ABC_TEST_DIRS += tests/aiger -SH_ABC_TEST_DIRS += tests/alumacc - -# seed-tests/ is a dummy string, not a directory -.PHONY: seed-tests -seed-tests: $(SH_TEST_DIRS:%=seed-tests/%) -.PHONY: seed-tests/% -seed-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) - +cd $* && bash run-test.sh $(SEEDOPT) - +@echo "...passed tests in $*" - -# abcopt-tests/ is a dummy string, not a directory -.PHONY: abcopt-tests -abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-tests/%) -abcopt-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) - +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) - +@echo "...passed tests in $*" - -# makefile-tests/ is a dummy string, not a directory -.PHONY: makefile-tests -makefile-tests: $(MK_TEST_DIRS:%=makefile-tests/%) -# this target actually emits .mk files -%.mk: - +cd $(dir $*) && bash run-test.sh -# this one spawns submake on each -makefile-tests/%: %/run-test.mk $(TARGETS) $(EXTRA_TARGETS) - $(MAKE) -C $* -f run-test.mk - +@echo "...passed tests in $*" - test: vanilla-test unit-test -vanilla-test: makefile-tests abcopt-tests seed-tests - @echo "" - @echo " Passed \"make vanilla-test\"." -ifeq ($(ENABLE_VERIFIC),1) -ifeq ($(YOSYS_NOVERIFIC),1) - @echo " Ran tests without verific support due to YOSYS_NOVERIFIC=1." -endif -endif - @echo "" +.PHONY: vanilla-test + +vanilla-test: $(TARGETS) $(EXTRA_TARGETS) + @$(MAKE) -C tests vanilla-test \ + $(if $(ENABLE_VERIFIC),ENABLE_VERIFIC=$(ENABLE_VERIFIC)) \ + $(if $(YOSYS_NOVERIFIC),YOSYS_NOVERIFIC=$(YOSYS_NOVERIFIC)) \ + SEEDOPT=$(SEEDOPT) ABCOPT=$(ABCOPT) VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all @@ -1062,14 +968,14 @@ install-dev: $(PROGRAM_PREFIX)yosys-config share install: $(TARGETS) $(EXTRA_TARGETS) $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR) $(INSTALL_SUDO) cp $(filter-out libyosys.so libyosys.a,$(TARGETS)) $(DESTDIR)$(BINDIR) -ifneq ($(filter $(PROGRAM_PREFIX)yosys,$(TARGETS)),) - if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys; fi +ifneq ($(filter $(PROGRAM_PREFIX)yosys$(EXE),$(TARGETS)),) + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys$(EXE); fi endif -ifneq ($(filter $(PROGRAM_PREFIX)yosys-abc,$(TARGETS)),) - if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc; fi +ifneq ($(filter $(PROGRAM_PREFIX)yosys-abc$(EXE),$(TARGETS)),) + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc$(EXE); fi endif -ifneq ($(filter $(PROGRAM_PREFIX)yosys-filterlib,$(TARGETS)),) - if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib; fi +ifneq ($(filter $(PROGRAM_PREFIX)yosys-filterlib$(EXE),$(TARGETS)),) + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib$(EXE); fi endif $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR) $(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/. @@ -1187,16 +1093,8 @@ clean: clean-py clean-unit-test rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) rm -f kernel/version_*.o kernel/version_*.cc 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 - rm -rf tests/simple/*.out tests/simple/*.log - rm -rf tests/memories/*.out tests/memories/*.log tests/memories/*.dmp - rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log - rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp tests/various/temp rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_* - rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff - rm -f tests/tools/cmp_tbdata - rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) + -$(MAKE) -C $(YOSYS_SRC)/tests clean -$(MAKE) -C $(YOSYS_SRC)/docs clean rm -rf docs/util/__pycache__ rm -f libyosys.so @@ -1244,7 +1142,7 @@ vcxsrc: $(GENFILES) $(EXTRA_TARGETS) kernel/version_$(GIT_REV).cc rm -rf $(VCX_DIR_NAME){,.zip} cp -f kernel/version_$(GIT_REV).cc kernel/version.cc set -e; for f in `ls $(filter %.cc %.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS))) $(addsuffix .cpp,$(basename $(OBJS))) 2> /dev/null`; do \ - echo "Analyse: $$f" >&2; cpp -std=c++17 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt + echo "Analyse: $$f" >&2; cpp -std=c++20 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt echo "libs/fst/fst_win_unistd.h" >> srcfiles.txt echo "kernel/version.cc" >> srcfiles.txt bash misc/create_vcxsrc.sh $(VCX_DIR_NAME) $(YOSYS_VER) diff --git a/abc b/abc index 180a6adb6..5d51a5e42 160000 --- a/abc +++ b/abc @@ -1 +1 @@ -Subproject commit 180a6adb68e855942e859f3646eff7762c7bc3e6 +Subproject commit 5d51a5e420f5de493d07bf61109a977248c86ffb diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 0c49e84b8..1320937a0 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -340,7 +340,7 @@ struct AigerWriter if (cell->type == ID($scopeinfo)) continue; - log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + log_error("Unsupported cell type: %s (%s)\n", cell->type.unescape(), cell); } for (auto bit : unused_bits) @@ -349,10 +349,10 @@ struct AigerWriter if (!undriven_bits.empty()) { undriven_bits.sort(); for (auto bit : undriven_bits) { - log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + log_warning("Treating undriven bit %s.%s like $anyseq.\n", module, log_signal(bit)); input_bits.insert(bit); } - log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), module); } init_map.sort(); @@ -635,35 +635,35 @@ struct AigerWriter int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i)); + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", wire, i)); else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", wire)); } if (wire->port_output) { int o = ordered_outputs.at(SigSpec(wire, i)); if (GetSize(wire) != 1) - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", wire, i)); else - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", wire)); } if (init_inputs.count(sig[i])) { int a = init_inputs.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", wire, i)); else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", wire)); } if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : ""; if (GetSize(wire) != 1) - symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i)); + symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, wire, i)); else - symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire))); + symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, wire)); } } } @@ -705,30 +705,30 @@ struct AigerWriter int index = no_startoffset ? i : (wire->start_offset+i); if (verbose_map) - wire_lines[a] += stringf("wire %d %d %s\n", a, index, log_id(wire)); + wire_lines[a] += stringf("wire %d %d %s\n", a, index, wire); if (wire->port_input) { log_assert((a & 1) == 0); - input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, index, log_id(wire)); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, index, wire); } if (wire->port_output) { int o = ordered_outputs.at(SigSpec(wire, i)); - output_lines[o] += stringf("output %d %d %s\n", o, index, log_id(wire)); + output_lines[o] += stringf("output %d %d %s\n", o, index, wire); } if (init_inputs.count(sig[i])) { int a = init_inputs.at(sig[i]); log_assert((a & 1) == 0); - init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, index, log_id(wire)); + init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, index, wire); } if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); if (zinit_mode && (aig_latchinit.at(l) == 1)) - latch_lines[l] += stringf("invlatch %d %d %s\n", l, index, log_id(wire)); + latch_lines[l] += stringf("invlatch %d %d %s\n", l, index, wire); else - latch_lines[l] += stringf("latch %d %d %s\n", l, index, log_id(wire)); + latch_lines[l] += stringf("latch %d %d %s\n", l, index, wire); } } } @@ -1027,12 +1027,12 @@ struct AigerBackend : public Backend { log_error("Can't find top module in current design!\n"); if (!design->selected_whole_module(top_module)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module)); + log_cmd_error("Can't handle partially selected module %s!\n", top_module); if (!top_module->processes.empty()) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", log_id(top_module)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", top_module); if (!top_module->memories.empty()) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", log_id(top_module)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", top_module); AigerWriter writer(top_module, no_sort, zinit_mode, imode, omode, bmode, lmode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 988bc558b..cc1085f96 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -268,7 +268,7 @@ struct XAigerWriter if (ys_debug(1)) { static pool> seen; if (seen.emplace(inst_module->name, i.first).second) log("%s.%s[%d] abc9_arrival = %d\n", - log_id(cell->type), log_id(i.first.name), offset, d); + cell->type.unescape(), i.first.name.unescape(), offset, d); } #endif arrival_times[rhs[offset]] = d; @@ -285,7 +285,7 @@ struct XAigerWriter auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first); auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first); if (!is_input && !is_output) - log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); + log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", c.first.unescape(), cell, cell->type.unescape()); if (is_input) for (auto b : c.second) { @@ -303,7 +303,7 @@ struct XAigerWriter } } - //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + //log_warning("Unsupported cell type: %s (%s)\n", cell->type.unescape(), cell); } dict> box_ports; @@ -325,12 +325,12 @@ struct XAigerWriter if (w->get_bool_attribute(ID::abc9_carry)) { if (w->port_input) { if (carry_in != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module)); + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", box_module); carry_in = port_name; } if (w->port_output) { if (carry_out != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module)); + log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", box_module); carry_out = port_name; } } @@ -339,9 +339,9 @@ struct XAigerWriter } if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_module)); + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", box_module); if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module)); + log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", box_module); if (carry_in != IdString()) { r.first->second.push_back(carry_in); r.first->second.push_back(carry_out); @@ -612,7 +612,7 @@ struct XAigerWriter write_r_buffer(mergeability); State init = init_map.at(q, State::Sx); - log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", log_id(cell), log_id(cell->type), log_signal(init)); + log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", cell, cell->type.unescape(), log_signal(init)); if (init == State::S1) write_s_buffer(1); else if (init == State::S0) @@ -692,12 +692,12 @@ struct XAigerWriter if (input_bits.count(b)) { int a = aig_map.at(b); log_assert((a & 1) == 0); - input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire)); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, wire); } if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, log_id(wire)); + output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, wire); } } } @@ -709,7 +709,7 @@ struct XAigerWriter int box_count = 0; for (auto cell : box_list) - f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); + f << stringf("box %d %d %s\n", box_count++, 0, cell->name.unescape()); output_lines.sort(); for (auto &it : output_lines) @@ -774,12 +774,12 @@ struct XAigerBackend : public Backend { log_error("Can't find top module in current design!\n"); if (!design->selected_whole_module(top_module)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module)); + log_cmd_error("Can't handle partially selected module %s!\n", top_module); if (!top_module->processes.empty()) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", log_id(top_module)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", top_module); if (!top_module->memories.empty()) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", top_module); XAigerWriter writer(top_module, dff_mode); writer.write_aiger(*f, ascii_mode); diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 96e1fe75f..6d8ac8a24 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -21,6 +21,9 @@ // - gracefully handling inout ports (an error message probably) // - undriven wires // - zero-width operands +// - decide how to unify this with cellaigs +// - break up Index into something smaller +// - (C++20) remove snprintf-into-std::ostream weirdness #include "kernel/register.h" #include "kernel/newcelltypes.h" @@ -129,7 +132,7 @@ struct Index { continue; if (!submodule || submodule->get_blackbox_attribute()) log_error("Unsupported cell type: %s (%s in %s)\n", - log_id(cell->type), log_id(cell), log_id(m)); + cell->type.unescape(), cell, m); } } } @@ -179,6 +182,9 @@ struct Index { } else { // AigMaker::node2index + // In XAIGER, the ordering of inputs is used to distinguish between AND + // and XOR gates. AND gates have their first input literal be larger + // than their second, and vice-versa for XORs. if (a < b) std::swap(a, b); auto pair = std::make_pair(a, b); @@ -531,7 +537,7 @@ struct Index { Design *design = index.design; auto &minfo = leaf_minfo(index); if (!minfo.suboffsets.count(cell)) - log_error("Reached unsupport cell %s (%s in %s)\n", log_id(cell->type), log_id(cell), log_id(cell->module)); + log_error("Reached unsupported cell %s (%s in %s)\n", cell->type.unescape(), cell, cell->module); Module *def = design->module(cell->type); log_assert(def); levels.push_back(Level(index.modules.at(def), cell)); @@ -550,13 +556,13 @@ struct Index { { std::string ret; bool first = true; - for (auto pair : levels) { + for (auto [minfo, cell] : levels) { if (!first) ret += "."; - if (!pair.second) - ret += RTLIL::unescape_id(pair.first.module->name); + if (!cell) + ret += RTLIL::unescape_id(minfo.module->name); else - ret += RTLIL::unescape_id(pair.second->name); + ret += RTLIL::unescape_id(cell->name); first = false; } return ret; @@ -565,8 +571,8 @@ struct Index { int hash() const { int hash = 0; - for (auto pair : levels) - hash += (uintptr_t) pair.second; + for (auto [_, cell] : levels) + hash += (uintptr_t) cell; return hash; } @@ -575,9 +581,12 @@ struct Index { if (levels.size() != other.levels.size()) return false; - for (int i = 0; i < levels.size(); i++) - if (levels[i].second != other.levels[i].second) + for (int i = 0; i < levels.size(); i++) { + auto* cell = levels[i].second; + auto* other_cell = other.levels[i].second; + if (cell != other_cell) return false; + } return true; } @@ -627,10 +636,10 @@ struct Index { Wire *w = def->wire(portname); if (!w) log_error("Output port %s on instance %s of %s doesn't exist\n", - log_id(portname), log_id(driver), log_id(def)); + portname.unescape(), driver, def); if (bit.offset >= w->width) log_error("Bit position %d of output port %s on instance %s of %s is out of range (port has width %d)\n", - bit.offset, log_id(portname), log_id(driver), log_id(def), w->width); + bit.offset, portname.unescape(), driver, def, w->width); ret = visit(cursor, SigBit(w, bit.offset)); } cursor.exit(*this); @@ -646,11 +655,11 @@ struct Index { IdString portname = bit.wire->name; if (!instance->hasPort(portname)) log_error("Input port %s on instance %s of %s unconnected\n", - log_id(portname), log_id(instance), log_id(instance->type)); + portname.unescape(), instance, instance->type); auto &port = instance->getPort(portname); if (bit.offset >= port.size()) log_error("Bit %d of input port %s on instance %s of %s unconnected\n", - bit.offset, log_id(portname), log_id(instance), log_id(instance->type)); + bit.offset, portname.unescape(), instance, instance->type.unescape()); ret = visit(cursor, port[bit.offset]); } cursor.enter(*this, instance); @@ -740,6 +749,9 @@ struct AigerWriter : Index { nands++; lit_counter += 2; + // In XAIGER, the ordering of inputs is used to distinguish between AND + // and XOR gates. AND gates have their first input literal be larger + // than their second, and vice-versa for XORs. if (a < b) std::swap(a, b); encode(out - a); encode(a - b); @@ -756,7 +768,7 @@ struct AigerWriter : Index { log_assert(lit_counter == (Lit) (ninputs + nlatches + nands) * 2 + 2); char buf[128]; - snprintf(buf, sizeof(buf) - 1, "aig %08d %08d %08d %08d %08d\n", + snprintf(buf, sizeof(buf), "aig %08d %08d %08d %08d %08d\n", ninputs + nlatches + nands, ninputs, nlatches, noutputs, nands); f->write(buf, strlen(buf)); } @@ -773,8 +785,9 @@ struct AigerWriter : Index { log_assert(w); if (w->port_input && !w->port_output) for (int i = 0; i < w->width; i++) { - pi_literal(SigBit(w, i)) = lit_counter; - inputs.push_back(SigBit(w, i)); + auto bit = SigBit(w, i); + pi_literal(bit) = lit_counter; + inputs.push_back(bit); lit_counter += 2; ninputs++; } @@ -791,7 +804,7 @@ struct AigerWriter : Index { for (auto bit : SigSpec(w)) { (void) bit; char buf[16]; - snprintf(buf, sizeof(buf) - 1, "%08d\n", 0); + snprintf(buf, sizeof(buf), "%08d\n", 0); f->write(buf, strlen(buf)); noutputs++; } @@ -804,16 +817,19 @@ struct AigerWriter : Index { for (auto w : top->wires()) if (w->port_output) { for (auto bit : SigSpec(w)) + // Each call to eval_po eventually reaches emit_gate and + // encode which writes to f. outputs.push_back({bit, eval_po(bit)}); } + auto data_end = f->tellp(); // revisit header and the list of outputs f->seekp(file_start); write_header(); - for (auto pair : outputs) { + for (auto [_, po] : outputs) { char buf[16]; - snprintf(buf, sizeof(buf) - 1, "%08d\n", pair.second); + snprintf(buf, sizeof(buf), "%08d\n", po); f->write(buf, strlen(buf)); } // double check we arrived at the same offset for the @@ -822,12 +838,13 @@ struct AigerWriter : Index { f->seekp(data_end); int i = 0; - for (auto pair : outputs) { - if (SigSpec(pair.first).is_wire()) { + for (auto [bit, _] : outputs) { + if (SigSpec(bit).is_wire()) { + // primary output symbol char buf[32]; - snprintf(buf, sizeof(buf) - 1, "o%d ", i); + snprintf(buf, sizeof(buf), "o%d ", i); f->write(buf, strlen(buf)); - std::string name = RTLIL::unescape_id(pair.first.wire->name); + std::string name = RTLIL::unescape_id(bit.wire->name); f->write(name.data(), name.size()); f->put('\n'); } @@ -836,8 +853,9 @@ struct AigerWriter : Index { i = 0; for (auto bit : inputs) { if (SigSpec(bit).is_wire()) { + // primary input symbol char buf[32]; - snprintf(buf, sizeof(buf) - 1, "i%d ", i); + snprintf(buf, sizeof(buf), "i%d ", i); f->write(buf, strlen(buf)); std::string name = RTLIL::unescape_id(bit.wire->name); f->write(name.data(), name.size()); @@ -1030,7 +1048,7 @@ struct XAigerWriter : AigerWriter { } else if (!is_input && !inputs) { for (auto &bit : conn.second) { if (!bit.wire || (bit.wire->port_input && !bit.wire->port_output)) - log_error("Bad connection %s/%s ~ %s\n", log_id(box), log_id(conn.first), log_signal(conn.second)); + log_error("Bad connection %s/%s ~ %s\n", box, conn.first.unescape(), log_signal(conn.second)); ensure_pi(bit, cursor); @@ -1055,9 +1073,9 @@ struct XAigerWriter : AigerWriter { void prep_boxes(int pending_pos_num) { XAigerAnalysis analysis; - log_debug("preforming analysis on '%s'\n", log_id(top)); + log_debug("preforming analysis on '%s'\n", top); analysis.analyze(top); - log_debug("analysis on '%s' done\n", log_id(top)); + log_debug("analysis on '%s' done\n", top); // boxes which have timing data, maybe a whitebox model std::vector> nonopaque_boxes; @@ -1071,7 +1089,7 @@ struct XAigerWriter : AigerWriter { for (auto box : minfo.found_blackboxes) { log_debug(" - %s.%s (type %s): ", cursor.path(), RTLIL::unescape_id(box->name), - log_id(box->type)); + box->type.unescape()); Module *box_module = design->module(box->type), *box_derived; @@ -1140,7 +1158,7 @@ struct XAigerWriter : AigerWriter { } else { // FIXME: hierarchical path log_warning("connection on port %s[%d] of instance %s (type %s) missing, using 1'bx\n", - log_id(port_id), i, log_id(box), log_id(box->type)); + port_id.unescape(), i, box, box->type.unescape()); bit = RTLIL::Sx; } @@ -1175,7 +1193,7 @@ struct XAigerWriter : AigerWriter { } else { // FIXME: hierarchical path log_warning("connection on port %s[%d] of instance %s (type %s) missing\n", - log_id(port_id), i, log_id(box), log_id(box->type)); + port_id.unescape(), i, box, box->type.unescape()); pad_pi(); continue; } @@ -1192,7 +1210,7 @@ struct XAigerWriter : AigerWriter { holes_wb->setPort(port_id, w); } else { log_error("Ambiguous port direction on %s/%s\n", - log_id(box->type), log_id(port_id)); + box->type.unescape(), port_id.unescape()); } } } @@ -1242,29 +1260,29 @@ struct XAigerWriter : AigerWriter { reset_counters(); for (auto w : top->wires()) - if (w->port_input && !w->port_output) - for (int i = 0; i < w->width; i++) - ensure_pi(SigBit(w, i)); + if (w->port_input && !w->port_output) + for (int i = 0; i < w->width; i++) + ensure_pi(SigBit(w, i)); int proper_po_num = 0; for (auto w : top->wires()) - if (w->port_output) - proper_po_num += w->width; + if (w->port_output) + proper_po_num += w->width; prep_boxes(proper_po_num); for (auto w : top->wires()) - if (w->port_output) - for (int i = 0; i < w->width; i++) { - // When a module output is directly driven by an opaque box, we - // don't emit it to the mapping file to aid re-integration, but we - // do emit a proper PO. - if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) { - map_file << "po " << proper_pos_counter << " " << i - << " " << w->name.c_str() << "\n"; - } - proper_pos_counter++; - pos.push_back(std::make_pair(SigBit(w, i), HierCursor{})); - } + if (w->port_output) + for (int i = 0; i < w->width; i++) { + // When a module output is directly driven by an opaque box, we + // don't emit it to the mapping file to aid re-integration, but we + // do emit a proper PO. + if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) { + map_file << "po " << proper_pos_counter << " " << i + << " " << w->name.c_str() << "\n"; + } + proper_pos_counter++; + pos.push_back(std::make_pair(SigBit(w, i), HierCursor{})); + } this->f = f; // start with the header @@ -1274,7 +1292,7 @@ struct XAigerWriter : AigerWriter { // insert padding where output literals will go (once known) for (auto _ : pos) { char buf[16]; - snprintf(buf, sizeof(buf) - 1, "%08d\n", 0); + snprintf(buf, sizeof(buf), "%08d\n", 0); f->write(buf, strlen(buf)); } auto data_start = f->tellp(); @@ -1291,35 +1309,36 @@ struct XAigerWriter : AigerWriter { write_header(); for (auto lit : outlits) { char buf[16]; - snprintf(buf, sizeof(buf) - 1, "%08d\n", lit); + snprintf(buf, sizeof(buf), "%08d\n", lit); f->write(buf, strlen(buf)); } // double check we arrived at the same offset for the // main data section log_assert(data_start == f->tellp()); - // extensions + // XAIGER extensions f->seekp(0, std::ios::end); - f->put('c'); + f->put('c'); // 'c': comment (marks beginning of extensions) // insert empty 'r' and 's' sections (abc crashes if we provide 'a' without those) - f->put('r'); - write_be32(*f, 4); - write_be32(*f, 0); - f->put('s'); - write_be32(*f, 4); - write_be32(*f, 0); + f->put('r'); // 'r': register classes + write_be32(*f, 4); // length in bytes + write_be32(*f, 0); // no register classes - f->put('h'); + f->put('s'); // 's': register initial values + write_be32(*f, 4); // length in bytes + write_be32(*f, 0); // no register initial values + + f->put('h'); // 'h': hierarchy information // TODO: get rid of std::string copy std::string h_buffer_str = h_buffer.str(); - write_be32(*f, h_buffer_str.size()); - f->write(h_buffer_str.data(), h_buffer_str.size()); + write_be32(*f, h_buffer_str.size()); // length in bytes + f->write(h_buffer_str.data(), h_buffer_str.size()); // data #if 1 - f->put('a'); - write_be32(*f, 0); // size to be filled later + f->put('a'); // 'a': additional AIG (used for holes) + write_be32(*f, 0); // length in bytes (to be filled later) auto holes_aiger_start = f->tellp(); { AigerWriter holes_writer; @@ -1331,7 +1350,7 @@ struct XAigerWriter : AigerWriter { auto holes_aiger_size = f->tellp() - holes_aiger_start; f->seekp(holes_aiger_start, std::ios::beg); f->seekp(-4, std::ios::cur); - write_be32(*f, holes_aiger_size); + write_be32(*f, holes_aiger_size); // length in bytes #endif f->seekp(0, std::ios::end); @@ -1386,7 +1405,7 @@ struct Aiger2Backend : Backend { continue; if (known_ops(cell.type)) continue; - std::string name = log_id(cell.type); + std::string name = cell.type.unescape(); if (col + name.size() + 2 > 72) { log("\n "); col = 0; @@ -1408,7 +1427,7 @@ struct Aiger2Backend : Backend { continue; if (known_ops(cell.type)) continue; - std::string name = log_id(cell.type); + std::string name = cell.type.unescape(); if (col + name.size() + 2 > 72) { log("\n "); col = 0; diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index cc339bcbc..d16d39e5e 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -150,7 +150,7 @@ struct BlifDumper void dump_params(const char *command, dict ¶ms) { for (auto ¶m : params) { - f << stringf("%s %s ", command, log_id(param.first)); + f << stringf("%s %s ", command, param.first.unescape()); if (param.second.flags & RTLIL::CONST_FLAG_STRING) { std::string str = param.second.decode_string(); f << stringf("\""); @@ -678,9 +678,9 @@ struct BlifBackend : public Backend { continue; if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", log_id(module->name)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", module->name.unescape()); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", log_id(module->name)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", module->name.unescape()); if (module->name == RTLIL::escape_id(top_module_name)) { BlifDumper::dump(*f, module, design, config); diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index ca7cf8a7f..497ecc954 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -119,7 +119,7 @@ struct BtorWorker template string getinfo(T *obj, bool srcsym = false) { - string infostr = log_id(obj); + string infostr = obj->name.unescape(); if (!srcsym && !print_internal_names && infostr[0] == '$') return ""; if (obj->attributes.count(ID::src)) { string src = obj->attributes.at(ID::src).decode_string().c_str(); @@ -243,12 +243,12 @@ struct BtorWorker if (cell_recursion_guard.count(cell)) { string cell_list; for (auto c : cell_recursion_guard) - cell_list += stringf("\n %s", log_id(c)); - log_error("Found topological loop while processing cell %s. Active cells:%s\n", log_id(cell), cell_list); + cell_list += stringf("\n %s", c); + log_error("Found topological loop while processing cell %s. Active cells:%s\n", cell, cell_list); } cell_recursion_guard.insert(cell); - btorf_push(log_id(cell)); + btorf_push(cell->name.unescape()); if (cell->type.in(ID($add), ID($sub), ID($mul), ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($sshl), ID($shr), ID($sshr), ID($shift), ID($shiftx), ID($concat), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_))) @@ -726,7 +726,7 @@ struct BtorWorker if (symbol.empty() || (!print_internal_names && symbol[0] == '$')) btorf("%d state %d\n", nid, sid); else - btorf("%d state %d %s\n", nid, sid, log_id(symbol)); + btorf("%d state %d %s\n", nid, sid, symbol.unescape()); if (cell->get_bool_attribute(ID(clk2fflogic))) ywmap_state(cell->getPort(ID::D)); // For a clk2fflogic FF the named signal is the D input not the Q output @@ -804,12 +804,12 @@ struct BtorWorker if (asyncwr && syncwr) log_error("Memory %s.%s has mixed async/sync write ports.\n", - log_id(module), log_id(mem->memid)); + module, mem->memid.unescape()); for (auto &port : mem->rd_ports) { if (port.clk_enable) log_error("Memory %s.%s has sync read ports. Please use memory_nordff to convert them first.\n", - log_id(module), log_id(mem->memid)); + module, mem->memid.unescape()); } int data_sid = get_bv_sid(mem->width); @@ -871,7 +871,7 @@ struct BtorWorker if (mem->memid[0] == '$') btorf("%d state %d\n", nid, sid); else - btorf("%d state %d %s\n", nid, sid, log_id(mem->memid)); + btorf("%d state %d %s\n", nid, sid, mem->memid.unescape()); ywmap_state(cell); @@ -948,21 +948,20 @@ struct BtorWorker if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) { log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_btor`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") { log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_btor`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") { log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_btor`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } log_error("Unsupported cell type %s for cell %s.%s.\n", - log_id(cell->type), log_id(module), log_id(cell)); - + cell->type.unescape(), module, cell); okay: - btorf_pop(log_id(cell)); + btorf_pop(cell->name.unescape()); cell_recursion_guard.erase(cell); } @@ -1167,7 +1166,7 @@ struct BtorWorker f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad), cover_mode(cover_mode), print_internal_names(print_internal_names), info_filename(info_filename) { if (!info_filename.empty()) - infof("name %s\n", log_id(module)); + infof("name %s\n", module); if (!ywmap_filename.empty()) ywmap_json.write_to_file(ywmap_filename); @@ -1257,19 +1256,19 @@ struct BtorWorker if (!wire->port_id || !wire->port_output) continue; - btorf_push(stringf("output %s", log_id(wire))); + btorf_push(stringf("output %s", wire)); int nid = get_sig_nid(wire); btorf("%d output %d%s\n", next_nid++, nid, getinfo(wire)); - btorf_pop(stringf("output %s", log_id(wire))); + btorf_pop(stringf("output %s", wire)); } for (auto cell : module->cells()) { if (cell->type == ID($assume)) { - btorf_push(log_id(cell)); + btorf_push(cell->name.unescape()); int sid = get_bv_sid(1); int nid_a = get_sig_nid(cell->getPort(ID::A)); @@ -1284,12 +1283,12 @@ struct BtorWorker if (ywmap_json.active()) ywmap_assumes.emplace_back(cell); - btorf_pop(log_id(cell)); + btorf_pop(cell->name.unescape()); } if (cell->type == ID($assert)) { - btorf_push(log_id(cell)); + btorf_push(cell->name.unescape()); int sid = get_bv_sid(1); int nid_a = get_sig_nid(cell->getPort(ID::A)); @@ -1313,12 +1312,12 @@ struct BtorWorker } } - btorf_pop(log_id(cell)); + btorf_pop(cell->name.unescape()); } if (cell->type == ID($cover) && cover_mode) { - btorf_push(log_id(cell)); + btorf_push(cell->name.unescape()); int sid = get_bv_sid(1); int nid_a = get_sig_nid(cell->getPort(ID::A)); @@ -1334,7 +1333,7 @@ struct BtorWorker btorf("%d bad %d%s\n", nid, nid_en_and_a, getinfo(cell, true)); } - btorf_pop(log_id(cell)); + btorf_pop(cell->name.unescape()); } } @@ -1343,7 +1342,7 @@ struct BtorWorker if (wire->port_id || wire->name[0] == '$') continue; - btorf_push(stringf("wire %s", log_id(wire))); + btorf_push(stringf("wire %s", wire)); int sid = get_bv_sid(GetSize(wire)); int nid = get_sig_nid(sigmap(wire)); @@ -1356,7 +1355,7 @@ struct BtorWorker if (info_clocks.count(nid)) info_clocks[this_nid] |= info_clocks[nid]; - btorf_pop(stringf("wire %s", log_id(wire))); + btorf_pop(stringf("wire %s", wire)); continue; } @@ -1370,14 +1369,14 @@ struct BtorWorker int nid = it.first; Cell *cell = it.second; - btorf_push(stringf("next %s", log_id(cell))); + btorf_push(stringf("next %s", cell)); SigSpec sig = sigmap(cell->getPort(ID::D)); int nid_q = get_sig_nid(sig); int sid = get_bv_sid(GetSize(sig)); btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell)); - btorf_pop(stringf("next %s", log_id(cell))); + btorf_pop(stringf("next %s", cell)); } vector> mtodo; @@ -1388,7 +1387,7 @@ struct BtorWorker int nid = it.first; Mem *mem = it.second; - btorf_push(stringf("next %s", log_id(mem->memid))); + btorf_push(stringf("next %s", mem->memid.unescape())); int abits = ceil_log2(mem->size); @@ -1436,7 +1435,7 @@ struct BtorWorker int nid2 = next_nid++; btorf("%d next %d %d %d%s\n", nid2, sid, nid, nid_head, (mem->cell ? getinfo(mem->cell) : getinfo(mem->mem))); - btorf_pop(stringf("next %s", log_id(mem->memid))); + btorf_pop(stringf("next %s", mem->memid.unescape())); } } @@ -1630,7 +1629,7 @@ struct BtorBackend : public Backend { log_cmd_error("No top module found.\n"); *f << stringf("; BTOR description generated by %s for module %s.\n", - yosys_maybe_version(), log_id(topmod)); + yosys_maybe_version(), topmod); BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename, ywmap_filename); diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index ab5576e43..3ebe62b90 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -251,7 +251,7 @@ CxxrtlPortType cxxrtl_port_type(RTLIL::Module *module, RTLIL::IdString port) bool is_sync = output_wire->get_bool_attribute(ID(cxxrtl_sync)); if (is_comb && is_sync) log_cmd_error("Port `%s.%s' is marked as both `cxxrtl_comb` and `cxxrtl_sync`.\n", - log_id(module), log_signal(output_wire)); + module, log_signal(output_wire)); else if (is_comb) return CxxrtlPortType::COMB; else if (is_sync) @@ -851,7 +851,7 @@ struct CxxrtlWorker { return {}; if (!(module->attributes.at(ID(cxxrtl_template)).flags & RTLIL::CONST_FLAG_STRING)) - log_cmd_error("Attribute `cxxrtl_template' of module `%s' is not a string.\n", log_id(module)); + log_cmd_error("Attribute `cxxrtl_template' of module `%s' is not a string.\n", module); std::vector param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t"); for (const auto ¶m_name : param_names) { @@ -861,7 +861,7 @@ struct CxxrtlWorker { if (!isupper(param_name[0])) log_cmd_error("Attribute `cxxrtl_template' of module `%s' includes a parameter `%s', " "which does not start with an uppercase letter.\n", - log_id(module), param_name.c_str()); + module, param_name.c_str()); } return param_names; } @@ -907,12 +907,12 @@ struct CxxrtlWorker { RTLIL::IdString id_param_name = '\\' + param_name; if (!cell->hasParam(id_param_name)) log_cmd_error("Cell `%s.%s' does not have a parameter `%s', which is required by the templated module `%s'.\n", - log_id(cell->module), log_id(cell), param_name.c_str(), log_id(cell_module)); + cell->module, cell, param_name.c_str(), cell_module); RTLIL::Const param_value = cell->getParam(id_param_name); if (((param_value.flags & ~RTLIL::CONST_FLAG_SIGNED) != 0) || param_value.as_int() < 0) log_cmd_error("Parameter `%s' of cell `%s.%s', which is required by the templated module `%s', " "is not a positive integer.\n", - param_name.c_str(), log_id(cell->module), log_id(cell), log_id(cell_module)); + param_name.c_str(), cell->module, cell, cell_module); params += std::to_string(cell->getParam(id_param_name).as_int()); } params += ">"; @@ -2576,7 +2576,7 @@ struct CxxrtlWorker { } dec_indent(); - log_debug("Debug information statistics for module `%s':\n", log_id(module)); + log_debug("Debug information statistics for module `%s':\n", module); log_debug(" Scopes: %zu", count_scopes); log_debug(" Public wires: %zu, of which:\n", count_public_wires); log_debug(" Member wires: %zu, of which:\n", count_member_wires); @@ -2940,7 +2940,7 @@ struct CxxrtlWorker { RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)]; if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire)) log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' is not a string with one character per bit.\n", - log_id(module), log_signal(wire)); + module, log_signal(wire)); std::string edges = wire->get_string_attribute(ID(cxxrtl_edge)); for (int i = 0; i < GetSize(wire); i++) { @@ -2953,7 +2953,7 @@ struct CxxrtlWorker { default: log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' contains specifiers " "other than '-', 'p', 'n', or 'a'.\n", - log_id(module), log_signal(wire)); + module, log_signal(wire)); } } } @@ -2978,7 +2978,7 @@ struct CxxrtlWorker { for (auto cell : module->cells()) { if (!cell->known()) - log_cmd_error("Unknown cell `%s'.\n", log_id(cell->type)); + log_cmd_error("Unknown cell `%s'.\n", cell->type.unescape()); if (cell->is_mem_cell()) continue; @@ -2987,7 +2987,7 @@ struct CxxrtlWorker { if (cell_module && cell_module->get_blackbox_attribute() && !cell_module->get_bool_attribute(ID(cxxrtl_blackbox))) - log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", log_id(cell->type)); + log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", cell->type.unescape()); if (cell_module && cell_module->get_bool_attribute(ID(cxxrtl_blackbox)) && @@ -3116,9 +3116,9 @@ struct CxxrtlWorker { } if (!feedback_wires.empty()) { has_feedback_arcs = true; - log("Module `%s' contains feedback arcs through wires:\n", log_id(module)); + log("Module `%s' contains feedback arcs through wires:\n", module); for (auto wire : feedback_wires) - log(" %s\n", log_id(wire)); + log(" %s\n", wire); } // Conservatively assign wire types. Assignment of types BUFFERED and MEMBER is final, but assignment @@ -3189,7 +3189,7 @@ struct CxxrtlWorker { if (wire->name.isPublic() && !inline_public) continue; if (flow.is_inlinable(wire, live_wires[wire])) { if (flow.wire_comb_defs[wire].size() > 1) - log_cmd_error("Wire %s.%s has multiple drivers!\n", log_id(module), log_id(wire)); + log_cmd_error("Wire %s.%s has multiple drivers!\n", module, wire); log_assert(flow.wire_comb_defs[wire].size() == 1); FlowGraph::Node *node = *flow.wire_comb_defs[wire].begin(); switch (node->type) { @@ -3237,9 +3237,9 @@ struct CxxrtlWorker { buffered_comb_wires.insert(wire); if (!buffered_comb_wires.empty()) { has_buffered_comb_wires = true; - log("Module `%s' contains buffered combinatorial wires:\n", log_id(module)); + log("Module `%s' contains buffered combinatorial wires:\n", module); for (auto wire : buffered_comb_wires) - log(" %s\n", log_id(wire)); + log(" %s\n", wire); } // Record whether eval() requires only one delta cycle in this module. diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 145477b6b..180c3739b 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -207,9 +207,9 @@ struct EdifBackend : public Backend { top_module_name = module->name.str(); if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", log_id(module->name)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", module->name.unescape()); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", log_id(module->name)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", module->name.unescape()); for (auto cell : module->cells()) { @@ -317,12 +317,12 @@ struct EdifBackend : public Backend { for (auto &dep : it.second) if (module_deps.count(dep) > 0) goto not_ready_yet; - // log("Next in topological sort: %s\n", log_id(it.first->name)); + // log("Next in topological sort: %s\n", it.first->name.unescape()); sorted_modules.push_back(it.first); not_ready_yet:; } if (sorted_modules_idx == sorted_modules.size()) - log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name)); + log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", module_deps.begin()->first->name.unescape()); while (sorted_modules_idx < sorted_modules.size()) module_deps.erase(sorted_modules.at(sorted_modules_idx++)); } @@ -486,7 +486,7 @@ struct EdifBackend : public Backend { for (int i = 0; i < GetSize(sig); i++) if (sig[i].wire == NULL && sig[i] != RTLIL::State::S0 && sig[i] != RTLIL::State::S1) log_warning("Bit %d of cell port %s.%s.%s driven by %s will be left unconnected in EDIF output.\n", - i, log_id(module), log_id(cell), log_id(p.first), log_signal(sig[i])); + i, module, cell, p.first.unescape(), log_signal(sig[i])); else { int member_idx = lsbidx ? i : GetSize(sig)-i-1; auto m = design->module(cell->type); diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 577d95ad7..db5036552 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -82,7 +82,7 @@ const char *make_id(IdString id) if (namecache.count(id) != 0) return namecache.at(id).c_str(); - string new_id = log_id(id); + string new_id = id.unescape(); for (int i = 0; i < GetSize(new_id); i++) { @@ -263,7 +263,7 @@ void emit_extmodule(RTLIL::Cell *cell, RTLIL::Module *mod_instance, std::ostream if (wire->port_input && wire->port_output) { - log_error("Module port %s.%s is inout!\n", log_id(mod_instance), log_id(wire)); + log_error("Module port %s.%s is inout!\n", mod_instance, wire); } const std::string portDecl = stringf("%s%s %s: UInt<%d> %s\n", @@ -559,12 +559,12 @@ struct FirrtlWorker if (wire->attributes.count(ID::init)) { log_warning("Initial value (%s) for (%s.%s) not supported\n", wire->attributes.at(ID::init).as_string().c_str(), - log_id(module), log_id(wire)); + module, wire); } if (wire->port_id) { if (wire->port_input && wire->port_output) - log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); + log_error("Module port %s.%s is inout!\n", module, wire); port_decls.push_back(stringf("%s%s %s: UInt<%d> %s\n", indent, wire->port_input ? "input" : "output", wireName, wire->width, wireFileinfo.c_str())); } @@ -833,7 +833,7 @@ struct FirrtlWorker primop = "shl"; int shiftAmount = b_sig.as_int(); if (shiftAmount < 0) { - log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, log_id(module), log_id(cell)); + log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, module, cell); } b_expr = std::to_string(shiftAmount); firrtl_width = a_width + shiftAmount; @@ -844,7 +844,7 @@ struct FirrtlWorker firrtl_width = a_width + (1 << b_width) - 1; } } else { - log_error("Non power 2: %s.%s\n", log_id(module), log_id(cell)); + log_error("Non power 2: %s.%s\n", module, cell); } } @@ -905,7 +905,7 @@ struct FirrtlWorker { bool clkpol = cell->parameters.at(ID::CLK_POLARITY).as_bool(); if (clkpol == false) - log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell)); + log_error("Negative edge clock on FF %s.%s.\n", module, cell); int width = cell->parameters.at(ID::WIDTH).as_int(); string expr = make_expr(cell->getPort(ID::D)); @@ -983,7 +983,7 @@ struct FirrtlWorker if (cell->type == ID($scopeinfo)) continue; - log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); + log_error("Cell type not supported: %s (%s.%s)\n", cell->type.unescape(), module, cell); } for (auto &mem : memories) { @@ -991,10 +991,10 @@ struct FirrtlWorker Const init_data = mem.get_init_data(); if (!init_data.is_fully_undef()) - log_error("Memory with initialization data: %s.%s\n", log_id(module), log_id(mem.memid)); + log_error("Memory with initialization data: %s.%s\n", module, mem.memid.unescape()); if (mem.start_offset != 0) - log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(mem.memid)); + log_error("Memory with nonzero offset: %s.%s\n", module, mem.memid.unescape()); for (int i = 0; i < GetSize(mem.rd_ports); i++) { @@ -1002,7 +1002,7 @@ struct FirrtlWorker string port_name(stringf("%s.r%d", mem_id, i)); if (port.clk_enable) - log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid)); + log_error("Clocked read port %d on memory %s.%s.\n", i, module, mem.memid.unescape()); std::ostringstream rpe; @@ -1023,12 +1023,12 @@ struct FirrtlWorker string port_name(stringf("%s.w%d", mem_id, i)); if (!port.clk_enable) - log_error("Unclocked write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid)); + log_error("Unclocked write port %d on memory %s.%s.\n", i, module, mem.memid.unescape()); if (!port.clk_polarity) - log_error("Negedge write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid)); + log_error("Negedge write port %d on memory %s.%s.\n", i, module, mem.memid.unescape()); for (int i = 1; i < GetSize(port.en); i++) if (port.en[0] != port.en[i]) - log_error("Complex write enable on port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid)); + log_error("Complex write enable on port %d on memory %s.%s.\n", i, module, mem.memid.unescape()); std::ostringstream wpe; diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index ad16d50ab..5e1a3fc8d 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -133,26 +133,26 @@ struct IntersynthBackend : public Backend { if (selected && !design->selected_whole_module(module->name)) { if (design->selected_module(module->name)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name)); + log_cmd_error("Can't handle partially selected module %s!\n", module->name.unescape()); continue; } - log("Generating netlist %s.\n", log_id(module->name)); + log("Generating netlist %s.\n", module->name.unescape()); if (module->memories.size() != 0 || module->processes.size() != 0) log_error("Can't generate a netlist for a module with unprocessed memories or processes!\n"); std::set constcells_code; - netlists_code += stringf("# Netlist of module %s\n", log_id(module->name)); - netlists_code += stringf("netlist %s\n", log_id(module->name)); + netlists_code += stringf("# Netlist of module %s\n", module->name.unescape()); + netlists_code += stringf("netlist %s\n", module->name.unescape()); // Module Ports: "std::set celltypes_code" prevents duplicate top level ports for (auto wire : module->wires()) { if (wire->port_input || wire->port_output) { celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n", - log_id(wire->name), wire->width, wire->port_input ? "*" : "", - wire->port_input ? "input" : "output", log_id(wire->name), wire->width, log_id(wire->name))); - netlists_code += stringf("node %s %s PORT %s\n", log_id(wire->name), log_id(wire->name), + wire->name.unescape(), wire->width, wire->port_input ? "*" : "", + wire->port_input ? "input" : "output", wire->name.unescape(), wire->width, wire->name.unescape())); + netlists_code += stringf("node %s %s PORT %s\n", wire->name.unescape(), wire->name.unescape(), netname(conntypes_code, celltypes_code, constcells_code, sigmap(wire)).c_str()); } } @@ -163,26 +163,26 @@ struct IntersynthBackend : public Backend { std::string celltype_code, node_code; if (!ct.cell_known(cell->type)) - log_error("Found unknown cell type %s in module!\n", log_id(cell->type)); + log_error("Found unknown cell type %s in module!\n", cell->type.unescape()); - celltype_code = stringf("celltype %s", log_id(cell->type)); - node_code = stringf("node %s %s", log_id(cell->name), log_id(cell->type)); + celltype_code = stringf("celltype %s", cell->type.unescape()); + node_code = stringf("node %s %s", cell->name.unescape(), cell->type.unescape()); for (auto &port : cell->connections()) { RTLIL::SigSpec sig = sigmap(port.second); if (sig.size() != 0) { conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size())); - celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", log_id(port.first)); - node_code += stringf(" %s %s", log_id(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig)); + celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", port.first.unescape()); + node_code += stringf(" %s %s", port.first.unescape(), netname(conntypes_code, celltypes_code, constcells_code, sig)); } } for (auto ¶m : cell->parameters) { - celltype_code += stringf(" cfg:%d %s", int(param.second.size()), log_id(param.first)); + celltype_code += stringf(" cfg:%d %s", int(param.second.size()), param.first.unescape()); if (param.second.size() != 32) { - node_code += stringf(" %s '", log_id(param.first)); + node_code += stringf(" %s '", param.first.unescape()); for (int i = param.second.size()-1; i >= 0; i--) node_code += param.second[i] == State::S1 ? "1" : "0"; } else - node_code += stringf(" %s 0x%x", log_id(param.first), param.second.as_int()); + node_code += stringf(" %s 0x%x", param.first.unescape(), param.second.as_int()); } celltypes_code.insert(celltype_code + "\n"); diff --git a/backends/json/json.cc b/backends/json/json.cc index b04083622..234574ed1 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -152,7 +152,7 @@ struct JsonWriter sigidcounter = 2; if (module->has_processes()) { - log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", log_id(module)); + log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", module); } f << stringf(" %s: {\n", get_name(module->name)); @@ -316,13 +316,13 @@ struct JsonWriter f << stringf(" /* %3d */ [ ", node_idx); if (node.portbit >= 0) f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "", - log_id(node.portname), node.portbit); + node.portname.unescape(), node.portbit); else if (node.left_parent < 0 && node.right_parent < 0) f << stringf("\"%s\"", node.inverter ? "true" : "false"); else f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent); for (auto &op : node.outports) - f << stringf(", \"%s\", %d", log_id(op.first), op.second); + f << stringf(", \"%s\", %d", op.first.unescape(), op.second); f << stringf(" ]"); node_idx++; } diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index 8ebc685f0..baf5aa006 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -78,7 +78,7 @@ struct HierDirtyFlags for (Cell *cell : module->cells()) { Module *mod = module->design->module(cell->type); if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this, - prefix + cid(cell->name) + ".", log_prefix + "." + prefix + log_id(cell->name)); + prefix + cid(cell->name) + ".", log_prefix + "." + prefix + cell->name.unescape()); } } @@ -354,23 +354,23 @@ struct SimplecWorker struct_declarations.push_back(" // Input Ports"); for (Wire *w : mod->wires()) if (w->port_input) - struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w))); + struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w)); struct_declarations.push_back(""); struct_declarations.push_back(" // Output Ports"); for (Wire *w : mod->wires()) if (!w->port_input && w->port_output) - struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w))); + struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w)); struct_declarations.push_back(""); struct_declarations.push_back(" // Internal Wires"); for (Wire *w : mod->wires()) if (!w->port_input && !w->port_output) - struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w))); + struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w)); for (Cell *c : mod->cells()) if (design->module(c->type)) - struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type), cid(c->name), log_id(c))); + struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type), cid(c->name), c)); struct_declarations.push_back(stringf("};")); struct_declarations.push_back("#endif"); @@ -391,7 +391,7 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; @@ -418,7 +418,7 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; @@ -441,7 +441,7 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; @@ -466,7 +466,7 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; @@ -490,13 +490,13 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; } - log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type)); + log_error("No C model for %s available at the moment (FIXME).\n", cell->type.unescape()); } void eval_dirty(HierDirtyFlags *work) @@ -517,7 +517,7 @@ struct SimplecWorker if (chunk.wire == nullptr) continue; if (verbose) - log(" Propagating %s.%s[%d:%d].\n", work->log_prefix, log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset); + log(" Propagating %s.%s[%d:%d].\n", work->log_prefix, chunk.wire, chunk.offset+chunk.width-1, chunk.offset); funct_declarations.push_back(stringf(" // Updated signal in %s: %s", work->log_prefix, log_signal(chunk))); } @@ -539,8 +539,8 @@ struct SimplecWorker work->parent->set_dirty(parent_bit); if (verbose) - log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix, log_id(bit.wire), bit.offset, - work->parent->log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset); + log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix, bit.wire, bit.offset, + work->parent->log_prefix.c_str(), parent_bit.wire, parent_bit.offset); } for (auto &port : bit2cell[work->module][bit]) @@ -556,12 +556,12 @@ struct SimplecWorker child->set_dirty(child_bit); if (verbose) - log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix, log_id(bit.wire), bit.offset, - work->log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset); + log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix, bit.wire, bit.offset, + work->log_prefix.c_str(), std::get<0>(port), child_bit.wire, child_bit.offset); } else { if (verbose) - log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix, log_id(std::get<0>(port)), - work->log_prefix.c_str(), log_id(bit.wire), bit.offset); + log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix, std::get<0>(port), + work->log_prefix.c_str(), bit.wire, bit.offset); work->set_dirty(std::get<0>(port)); } } @@ -576,10 +576,10 @@ struct SimplecWorker if (cell == nullptr || topoidx.at(cell) < topoidx.at(c)) cell = c; - string hiername = work->log_prefix + "." + log_id(cell); + string hiername = work->log_prefix + "." + cell->name.unescape(); if (verbose) - log(" Evaluating %s (%s, best of %d).\n", hiername, log_id(cell->type), GetSize(work->dirty_cells)); + log(" Evaluating %s (%s, best of %d).\n", hiername, cell->type.unescape(), GetSize(work->dirty_cells)); if (activated_cells.count(hiername)) reactivated_cells.insert(hiername); @@ -618,8 +618,8 @@ struct SimplecWorker if (verbose) log(" Propagating alias %s.%s[%d] -> %s.%s[%d].\n", - work->log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset, - work->log_prefix.c_str(), log_id(bit.wire), bit.offset); + work->log_prefix.c_str(), canonical_bit.wire, canonical_bit.offset, + work->log_prefix.c_str(), bit.wire, bit.offset); } work->sticky_dirty_bits.clear(); @@ -716,7 +716,7 @@ struct SimplecWorker { create_module_struct(mod); - HierDirtyFlags work(mod, IdString(), nullptr, "state->", log_id(mod->name)); + HierDirtyFlags work(mod, IdString(), nullptr, "state->", mod->name.unescape()); make_init_func(&work); make_eval_func(&work); diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 9d0ebc2aa..a9030e18a 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -60,7 +60,7 @@ struct Smt2Worker const char *get_id(IdString n) { if (ids.count(n) == 0) { - std::string str = log_id(n); + std::string str = n.unescape(); for (int i = 0; i < GetSize(str); i++) { if (str[i] == '\\') str[i] = '/'; @@ -207,7 +207,7 @@ struct Smt2Worker } else if (is_output || !is_input) 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)); + conn.first.unescape(), module, cell, cell->type.unescape()); if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_)) && conn.first.in(ID::CLK, ID::C)) { @@ -448,7 +448,7 @@ struct Smt2Worker } if (verbose) - log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell)); + log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell); decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n", get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(bit))); @@ -498,7 +498,7 @@ struct Smt2Worker processed_expr = stringf("((_ extract %d 0) %s)", GetSize(sig_y)-1, processed_expr); if (verbose) - log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell)); + log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell); if (type == 'b') { decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n", @@ -529,7 +529,7 @@ struct Smt2Worker processed_expr += ch; if (verbose) - log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell)); + log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell); decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n", get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(sig_y))); @@ -541,7 +541,7 @@ struct Smt2Worker { if (verbose) log("%*s=> export_cell %s (%s) [%s]\n", 2+2*GetSize(recursive_cells), "", - log_id(cell), log_id(cell->type), exported_cells.count(cell) ? "old" : "new"); + cell, cell->type.unescape(), exported_cells.count(cell) ? "old" : "new"); if (recursive_cells.count(cell)) log_error("Found logic loop in module %s! See cell %s.\n", get_id(module), get_id(cell)); @@ -750,7 +750,7 @@ struct Smt2Worker get_bv(sig_b.extract(i*width, width)).c_str(), processed_expr.c_str()); if (verbose) - log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell)); + log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell); RTLIL::SigSpec sig = sigmap(cell->getPort(ID::Y)); decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", @@ -786,9 +786,9 @@ struct Smt2Worker has_async_wr = true; } if (has_async_wr && has_sync_wr) - log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module)); + log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", cell, module); - decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", get_id(mem->memid), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync")); + decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", mem->memid.unescape(), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync")); decls.push_back(witness_memory(get_id(mem->memid), cell, mem)); string memstate; @@ -813,7 +813,7 @@ struct Smt2Worker if (port.clk_enable) log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " - "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module)); + "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), mem->memid.unescape(), module); decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); @@ -857,7 +857,7 @@ struct Smt2Worker if (port.clk_enable) log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " - "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module)); + "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), mem->memid.unescape(), module); decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); @@ -928,30 +928,30 @@ struct Smt2Worker if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) { log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smt2`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") { log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smt2`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") { log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smt2`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type, module, cell); } log_error("Unsupported cell type %s for cell %s.%s.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type, module, cell); } void verify_smtlib2_module() { if (!module->get_blackbox_attribute()) - log_error("Module %s with smtlib2_module attribute must also have blackbox attribute.\n", log_id(module)); + log_error("Module %s with smtlib2_module attribute must also have blackbox attribute.\n", module); if (module->cells().size() > 0) - log_error("Module %s with smtlib2_module attribute must not have any cells inside it.\n", log_id(module)); + log_error("Module %s with smtlib2_module attribute must not have any cells inside it.\n", module); for (auto wire : module->wires()) if (!wire->port_id) - log_error("Wire %s.%s must be input or output since module has smtlib2_module attribute.\n", log_id(module), - log_id(wire)); + log_error("Wire %s.%s must be input or output since module has smtlib2_module attribute.\n", module, + wire); } void run() @@ -991,8 +991,8 @@ struct Smt2Worker } bool is_smtlib2_comb_expr = wire->has_attribute(ID::smtlib2_comb_expr); if (is_smtlib2_comb_expr && !is_smtlib2_module) - log_error("smtlib2_comb_expr is only valid in a module with the smtlib2_module attribute: wire %s.%s", log_id(module), - log_id(wire)); + log_error("smtlib2_comb_expr is only valid in a module with the smtlib2_module attribute: wire %s.%s", module, + wire); if (wire->port_id || is_register || contains_clock || wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name.isPublic())) { RTLIL::SigSpec sig = sigmap(wire); std::vector comments; @@ -1023,10 +1023,10 @@ struct Smt2Worker smtlib2_comb_expr = "(let (\n" + smtlib2_inputs + ")\n" + wire->get_string_attribute(ID::smtlib2_comb_expr) + "\n)"; if (wire->port_input || !wire->port_output) - log_error("smtlib2_comb_expr is only valid on output: wire %s.%s", log_id(module), log_id(wire)); + log_error("smtlib2_comb_expr is only valid on output: wire %s.%s", module, wire); if (!bvmode && GetSize(sig) > 1) log_error("smtlib2_comb_expr is unsupported on multi-bit wires when -nobv is specified: wire %s.%s", - log_id(module), log_id(wire)); + module, wire); comments.push_back(witness_signal("blackbox", wire->width, 0, get_id(wire), -1, wire)); } @@ -1075,7 +1075,7 @@ struct Smt2Worker if (wire->attributes.count(ID::init)) { if (is_smtlib2_module) log_error("init attribute not allowed on wires in module with smtlib2_module attribute: wire %s.%s", - log_id(module), log_id(wire)); + module, wire); RTLIL::SigSpec sig = sigmap(wire); Const val = wire->attributes.at(ID::init); @@ -1381,7 +1381,7 @@ struct Smt2Worker } } - if (verbose) log("=> finalizing SMT2 representation of %s.\n", log_id(module)); + if (verbose) log("=> finalizing SMT2 representation of %s.\n", module); for (auto c : hiercells) { assert_list.push_back(stringf("(|%s_a| (|%s_h %s| state))", get_id(c->type), get_id(module), get_id(c->name))); @@ -1867,12 +1867,12 @@ struct Smt2Backend : public Backend { for (auto &dep : it.second) if (module_deps.count(dep) > 0) goto not_ready_yet; - // log("Next in topological sort: %s\n", log_id(it.first->name)); + // log("Next in topological sort: %s\n", it.first->name.unescape()); sorted_modules.push_back(it.first); not_ready_yet:; } if (sorted_modules_idx == sorted_modules.size()) - log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name)); + log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", module_deps.begin()->first->name.unescape()); while (sorted_modules_idx < sorted_modules.size()) module_deps.erase(sorted_modules.at(sorted_modules_idx++)); } @@ -1902,7 +1902,7 @@ struct Smt2Backend : public Backend { if (module->has_processes_warn()) continue; - log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); + log("Creating SMT-LIBv2 representation of module %s.\n", module); Smt2Worker worker(module, bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode, mod_stbv_width, mod_clk_cache); worker.run(); diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index acefad060..01f95ef45 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -217,7 +217,7 @@ struct SmvWorker partial_assignment_wires.insert(wire); if (wire->port_input) - inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, log_id(wire))); + inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, wire)); if (wire->attributes.count(ID::init)) assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at(ID::init)))); @@ -579,18 +579,18 @@ struct SmvWorker if (cell->type[0] == '$') { if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) { log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smv`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") { log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smv`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") { log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smv`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } log_error("Unsupported cell type %s for cell %s.%s.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } // f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type)); @@ -799,7 +799,7 @@ struct SmvBackend : public Backend { *f << stringf("-- SMV description generated by %s\n", yosys_maybe_version()); - log("Creating SMV representation of module %s.\n", log_id(module)); + log("Creating SMV representation of module %s.\n", module); SmvWorker worker(module, verbose, *f); worker.run(); @@ -819,7 +819,7 @@ struct SmvBackend : public Backend { *f << stringf("-- SMV description generated by %s\n", yosys_maybe_version()); for (auto module : modules) { - log("Creating SMV representation of module %s.\n", log_id(module)); + log("Creating SMV representation of module %s.\n", module); SmvWorker worker(module, verbose, *f); worker.run(); } diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index 16458d647..36caf6359 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -82,7 +82,7 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De if (design->module(cell->type) == nullptr) { log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = sigmap(conn.second); port_sigs.push_back(sig); @@ -224,9 +224,9 @@ struct SpiceBackend : public Backend { continue; if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", log_id(module)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", module); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", log_id(module)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", module); if (module->name == RTLIL::escape_id(top_module_name)) { top_module = module; diff --git a/backends/table/table.cc b/backends/table/table.cc index 2bf64e7b1..bbb533965 100644 --- a/backends/table/table.cc +++ b/backends/table/table.cc @@ -77,8 +77,8 @@ struct TableBackend : public Backend { if (wire->port_id == 0) continue; - *f << log_id(module) << "\t"; - *f << log_id(wire) << "\t"; + *f << module->name.unescape() << "\t"; + *f << wire->name.unescape() << "\t"; *f << "-" << "\t"; *f << "-" << "\t"; @@ -97,10 +97,10 @@ struct TableBackend : public Backend { for (auto cell : module->cells()) for (auto conn : cell->connections()) { - *f << log_id(module) << "\t"; - *f << log_id(cell) << "\t"; - *f << log_id(cell->type) << "\t"; - *f << log_id(conn.first) << "\t"; + *f << module->name.unescape() << "\t"; + *f << cell->name.unescape() << "\t"; + *f << cell->type.unescape() << "\t"; + *f << conn.first.unescape() << "\t"; if (cell->input(conn.first) && cell->output(conn.first)) *f << "inout" << "\t"; diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 73ffcbf3e..473918264 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -2388,7 +2388,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) log_warning("Module %s contains RTLIL processes with sync rules. Such RTLIL " "processes can't always be mapped directly to Verilog always blocks. " "unintended changes in simulation behavior are possible! Use \"proc\" " - "to convert processes to logic networks and registers.\n", log_id(module)); + "to convert processes to logic networks and registers.\n", module); f << stringf("\n"); for (auto it = module->processes.begin(); it != module->processes.end(); ++it) @@ -2714,7 +2714,7 @@ struct VerilogBackend : public Backend { continue; if (selected && !design->selected_whole_module(module->name)) { if (design->selected_module(module->name)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name)); + log_cmd_error("Can't handle partially selected module %s!\n", module->name.unescape()); continue; } log("Dumping module `%s'.\n", module->name); diff --git a/docs/source/_images/Makefile b/docs/source/_images/Makefile index 71f52c578..dc75c97c9 100644 --- a/docs/source/_images/Makefile +++ b/docs/source/_images/Makefile @@ -32,8 +32,9 @@ FORCE: TEX_FILES := $(shell find . -name *.tex) all_tex: $(TEX_FILES:.tex=.pdf) $(TEX_FILES:.tex=.svg) +# limit output size to US letter (same as latexpdf output) to avoid oversize error %.pdf: %.dot - $(FAKETIME) dot -Tpdf -o $@ $< + $(FAKETIME) dot -Tpdf -Gsize="8.5,11" -o $@ $< %.pdf: %.tex cd $(@D) && $(FAKETIME) pdflatex $(modules()) - log(" %s (%d wires, %d cells)\n", log_id(mod), + log(" %s (%d wires, %d cells)\n", mod, GetSize(mod->wires()), GetSize(mod->cells())); } } MyPass; @@ -28,7 +28,7 @@ struct Test1Pass : public Pass { log_error("A module with the name absval already exists!\n"); RTLIL::Module *module = design->addModule("\\absval"); - log("Name of this module: %s\n", log_id(module)); + log("Name of this module: %s\n", module); RTLIL::Wire *a = module->addWire("\\a", 4); a->port_input = true; diff --git a/docs/source/code_examples/macro_commands/synth_ice40.ys b/docs/source/code_examples/macro_commands/synth_ice40.ys index 443b8e0b0..07d960a64 100644 --- a/docs/source/code_examples/macro_commands/synth_ice40.ys +++ b/docs/source/code_examples/macro_commands/synth_ice40.ys @@ -6,6 +6,7 @@ begin: proc flatten: + check flatten tribuf -logic deminout diff --git a/docs/source/conf.py b/docs/source/conf.py index 9520948cf..b85c391db 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -6,7 +6,7 @@ import os project = 'YosysHQ Yosys' author = 'YosysHQ GmbH' copyright ='2026 YosysHQ GmbH' -yosys_ver = "0.64" +yosys_ver = "0.65" # select HTML theme html_theme = 'furo-ys' diff --git a/docs/source/getting_started/example_synth.rst b/docs/source/getting_started/example_synth.rst index ccf0d252b..ebfaa542b 100644 --- a/docs/source/getting_started/example_synth.rst +++ b/docs/source/getting_started/example_synth.rst @@ -291,7 +291,10 @@ In `synth_ice40` we get these: :name: synth_flatten :caption: ``flatten`` section -First off is `flatten`. Flattening the design like this can allow for +We start by runnning `check`. This doesn't affect the design, but it can +identify a few obvious problems which will cause errors later. Calling it here +lets us fail faster rather than wasting time on something we know is impossible. +Next up is `flatten`. Flattening the design like this can allow for optimizations between modules which would otherwise be missed. Let's run :yoscrypt:`flatten;;` on our design. @@ -363,17 +366,14 @@ In the iCE40 flow, we start with the following commands: :caption: ``coarse`` section (part 1) :name: synth_coarse1 -We've already come across `opt_expr`, and `opt_clean` is the same as `clean` but -with more verbose output. The `check` pass identifies a few obvious problems -which will cause errors later. Calling it here lets us fail faster rather than -wasting time on something we know is impossible. - -Next up is :yoscrypt:`opt -nodffe -nosdff` performing a set of simple -optimizations on the design. This command also ensures that only a specific -subset of FF types are included, in preparation for the next command: -:cmd:title:`fsm`. Both `opt` and `fsm` are macro commands which are explored in -more detail in :doc:`/using_yosys/synthesis/opt` and -:doc:`/using_yosys/synthesis/fsm` respectively. +We've already come across `opt_expr` and `check`, and `opt_clean` is the same as +`clean` but with more verbose output. Next up is :yoscrypt:`opt -nodffe +-nosdff` performing a set of simple optimizations on the design. This command +also ensures that only a specific subset of FF types are included, in +preparation for the next command: :cmd:title:`fsm`. Both `opt` and `fsm` are +macro commands which are explored in more detail in +:doc:`/using_yosys/synthesis/opt` and :doc:`/using_yosys/synthesis/fsm` +respectively. Up until now, the data path for ``rdata`` has remained the same since :ref:`rdata_flat`. However the next call to `opt` does cause a change. diff --git a/docs/source/getting_started/installation.rst b/docs/source/getting_started/installation.rst index 43b996353..2a90a8071 100644 --- a/docs/source/getting_started/installation.rst +++ b/docs/source/getting_started/installation.rst @@ -87,7 +87,7 @@ not regularly tested: Build prerequisites ^^^^^^^^^^^^^^^^^^^ -A C++ compiler with C++17 support is required as well as some standard tools +A C++ compiler with C++20 support is required as well as some standard tools such as GNU Flex, GNU Bison (>=3.8), Make, and Python (>=3.11). Some additional tools: readline, libffi, Tcl and zlib; are optional but enabled by default (see :makevar:`ENABLE_*` settings in Makefile). Graphviz and Xdot are used by the diff --git a/docs/source/using_yosys/bugpoint.rst b/docs/source/using_yosys/bugpoint.rst index c524470af..71ec3b68d 100644 --- a/docs/source/using_yosys/bugpoint.rst +++ b/docs/source/using_yosys/bugpoint.rst @@ -293,7 +293,7 @@ is still valid. :caption: Example test.sh for C-Reduce :name: egtest - #!/bin/bash + #!/usr/bin/env bash verilator --lint-only test.v &&/ yosys -p 'logger -expect error "unsupported" 1; read_verilog test.v' @@ -333,7 +333,7 @@ an input argument: ``sv-bugpoint outDir/ test.sh test.v`` .. code-block:: bash :caption: Example test.sh for sv-bugpoint - #!/bin/bash + #!/usr/bin/env bash verilator --lint-only $1 &&/ yosys -p "logger -expect error \"unsupported\" 1; read_verilog $1" diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index 458d7dc36..8d90d2cbe 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -4,8 +4,10 @@ Contributing to Yosys Reporting bugs -------------- -A good bug report includes the following information: +We fix well-reported bugs the fastest. A good bug report is an issue on the `issue tracker`_ +and includes the following information: +.. _`issue tracker`: https://github.com/YosysHQ/yosys/issues Title ~~~~~ @@ -27,8 +29,10 @@ The reproduction steps should be a minimal, complete and verifiable example `MVCE`_. Providing an MVCE with your bug report drastically increases the likelihood that someone will be able to help resolve your issue. -One way to minimize a design is to use the `bugpoint_` command. -You can learn more in the `how-to guide for bugpoint_`. +Make sure that your report input is free of any problems as reported by the +`check` command. +One way to minimize a design is to use the `bugpoint` command. +You can learn more in the :doc:`how-to guide for bugpoint `. The reproduction steps are ideally a code-block (starting and ending with triple backquotes) containing @@ -85,7 +89,6 @@ Don't forget to mention: reproduction steps to just the Yosys part. .. _MVCE: https://stackoverflow.com/help/minimal-reproducible-example -.. _bugpoint: https://yosys.readthedocs.io/en/latest/cmd/bugpoint.html .. _how-to guide for bugpoint: https://yosys.readthedocs.io/en/latest/using_yosys/bugpoint.html Expected Behaviour @@ -176,6 +179,12 @@ based on their descriptions first, code second. Before you build or fix something, also search for existing `issues`_. +We have open `developer 'jour fixe' (Dev JF) meetings`_ +where developers from YosysHQ and the +community come together to discuss open issues and PRs. This is also a good +place to talk to us about how to implement larger PRs. + +.. _`developer 'jour fixe' (Dev JF) meetings`: https://docs.google.com/document/d/1SapA6QAsJcsgwsdKJDgnGR2mr97pJjV4eeXg_TVJhRU/edit?usp=sharing .. _`Discourse forum`: https://yosyshq.discourse.group/ .. _`issues`: https://github.com/YosysHQ/yosys/issues @@ -277,7 +286,7 @@ have incorrect results in unusual situations. Coding style ~~~~~~~~~~~~ -Yosys is written in C++17. +Yosys is written in C++20. In general Yosys uses ``int`` instead of ``size_t``. To avoid compiler warnings for implicit type casts, always use ``GetSize(foobar)`` instead of @@ -297,6 +306,26 @@ Otherwise stick to the `Linux Kernel Coding Style`_. .. _Linux Kernel Coding Style: https://www.kernel.org/doc/Documentation/process/coding-style.rst +Pull requests (PRs) +~~~~~~~~~~~~~~~~~~~ + +If you are working on something to add to Yosys, or fix something that isn't +working quite right, +make a `pull request (PR)`_. + +An open PR, even as a draft, tells everyone that you're working on it and they +don't have to. It can also be a useful way to solicit feedback on in-progress +changes. + +We use `labels`_ to help categorise +issues and PRs. If a label seems relevant to your work, please do add it; this +also includes the labels beginning with 'status-'. The 'merge-' labels are used +by maintainers for tracking and communicating which PRs are ready and pending +merge; please do not use these labels if you are not a maintainer. + +.. _`pull request (PR)`: https://github.com/YosysHQ/yosys/pulls +.. _`labels`: https://github.com/YosysHQ/yosys/labels + Git style ~~~~~~~~~ @@ -317,10 +346,12 @@ Reviewing PRs is a totally valid form of external contributing to the project! Who's the reviewer? ~~~~~~~~~~~~~~~~~~~ -Yosys HQ is a company with the inherited mandate to make decisions on behalf -of the open source project. As such, we at HQ are collectively the maintainers. -Within HQ, we allocate reviews based on expertise with the topic at hand -as well as member time constraints. +YosysHQ GmbH is a company with a mandate to make decisions for the good +of YosysHQ open source software. It was co-founded by Claire Xenia Wolf, +the original author of Yosys. +Within it, we allocate reviews based on expertise with the topic at hand +as well as member time constraints. However, decisions including reviews +are also contributed by people external to the company. If you're intimately acquainted with a part of the codebase, we will be happy to defer to your experience and have you review PRs. The official way we like @@ -339,7 +370,8 @@ and stop being responsive, in the future, we might decide to remove such code if convenient and costly to maintain. It's simply more respectful of the users' time to explicitly cut something out than let it "bitrot". Larger projects like LLVM or linux could not survive without such things, but Yosys is far smaller, -and there are expectations +and there are implicit expectations of stability we aim to +respect within reason. .. TODO this deserves its own section elsewhere I think? But it would be distracting elsewhere @@ -375,3 +407,5 @@ they just are good enough to merge as-is. The CI is required to go green for merging. New contributors need a CI run to be triggered by a maintainer before their PRs take up computing resources. It's a single click from the github web interface. +We test on various platforms and compilers. Sanitizer builds are only +tested on the main branch. diff --git a/docs/source/yosys_internals/index.rst b/docs/source/yosys_internals/index.rst index 483cc2bf8..217b88e36 100644 --- a/docs/source/yosys_internals/index.rst +++ b/docs/source/yosys_internals/index.rst @@ -25,7 +25,7 @@ wide range of real-world designs, including the `OpenRISC 1200 CPU`_, the .. _k68 CPU: http://opencores.org/projects/k68 -Yosys is written in C++, targeting C++17 at minimum. This chapter describes some +Yosys is written in C++, targeting C++20 at minimum. This chapter describes some of the fundamental Yosys data structures. For the sake of simplicity the C++ type names used in the Yosys implementation are used in this chapter, even though the chapter only explains the conceptual idea behind it and can be used diff --git a/examples/aiger/README b/examples/aiger/README index 4e7694e95..13dce2035 100644 --- a/examples/aiger/README +++ b/examples/aiger/README @@ -14,7 +14,7 @@ in the PATH. E.g. extract the release to /usr/local/libexec/super_prove and then create a /usr/local/bin/super_prove file with the following contents (and "chmod +x" that file): - #!/bin/bash + #!/usr/bin/env bash exec /usr/local/libexec/super_prove/bin/super_prove.sh "$@" The "demo.sh" script also expects the "z3" SMT2 solver in the PATH for diff --git a/examples/aiger/demo.sh b/examples/aiger/demo.sh index 8728b6722..a1217bbd2 100644 --- a/examples/aiger/demo.sh +++ b/examples/aiger/demo.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex yosys -p ' read_verilog -formal demo.v diff --git a/examples/anlogic/build.sh b/examples/anlogic/build.sh index e0f6b4cfe..9b6e8c479 100755 --- a/examples/anlogic/build.sh +++ b/examples/anlogic/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex yosys demo.ys $TD_HOME/bin/td build.tcl diff --git a/examples/basys3/run.sh b/examples/basys3/run.sh index 10f059103..deb68d432 100644 --- a/examples/basys3/run.sh +++ b/examples/basys3/run.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash yosys run_yosys.ys vivado -nolog -nojournal -mode batch -source run_vivado.tcl vivado -nolog -nojournal -mode batch -source run_prog.tcl diff --git a/examples/cmos/testbench.sh b/examples/cmos/testbench.sh index 061704b64..856169ab9 100644 --- a/examples/cmos/testbench.sh +++ b/examples/cmos/testbench.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex diff --git a/examples/cmos/testbench_digital.sh b/examples/cmos/testbench_digital.sh index d7ab0fe1f..2e70e874c 100644 --- a/examples/cmos/testbench_digital.sh +++ b/examples/cmos/testbench_digital.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex diff --git a/examples/cxx-api/scopeinfo_example.cc b/examples/cxx-api/scopeinfo_example.cc index fd5d2a781..edbd1533f 100644 --- a/examples/cxx-api/scopeinfo_example.cc +++ b/examples/cxx-api/scopeinfo_example.cc @@ -61,7 +61,7 @@ struct ScopeinfoExamplePass : public Pass { if (do_wires) { for (auto module : design->selected_modules()) { - log("Source hierarchy for all selected wires within %s:\n", log_id(module)); + log("Source hierarchy for all selected wires within %s:\n", module); ModuleHdlnameIndex index(module); index.index_scopeinfo_cells(); @@ -73,11 +73,11 @@ struct ScopeinfoExamplePass : public Pass { auto wire_scope = index.containing_scope(wire); if (!wire_scope.first.valid()) { - log_warning("Couldn't find containing scope for %s in index\n", log_id(wire)); + log_warning("Couldn't find containing scope for %s in index\n", wire); continue; } - log("%s %s\n", wire_scope.first.path_str(), log_id(wire_scope.second)); + log("%s %s\n", wire_scope.first.path_str(), wire_scope.second.unescape()); for (auto src : index.sources(wire)) log(" - %s\n", src); } @@ -127,9 +127,9 @@ struct ScopeinfoExamplePass : public Pass { continue; log("common_ancestor(%s %s%s%s, %s %s%s%s) = %s %s\n", - log_id(module), scope_i.first.path_str().c_str(), scope_i.first.is_root() ? "" : " ", log_id(scope_i.second), - log_id(module), scope_j.first.path_str().c_str(), scope_j.first.is_root() ? "" : " ", log_id(scope_j.second), - log_id(module), common.path_str().c_str() + module, scope_i.first.path_str().c_str(), scope_i.first.is_root() ? "" : " ", scope_i.second.unescape(), + module, scope_j.first.path_str().c_str(), scope_j.first.is_root() ? "" : " ", scope_j.second.unescape(), + module, common.path_str().c_str() ); if (++limit == 10) diff --git a/examples/gowin/run.sh b/examples/gowin/run.sh index cd260101e..960624464 100644 --- a/examples/gowin/run.sh +++ b/examples/gowin/run.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex yosys -p "synth_gowin -top demo -vout demo_syn.v" demo.v $GOWIN_HOME/bin/gowin -d demo_syn.v -cst demo.cst -sdc demo.sdc -p GW1NR-9-QFN88-6 -pn GW1NR-LV9QN88C6/I5 -cfg device.cfg -bit -tr -ph -timing -gpa -rpt -warning_all diff --git a/examples/igloo2/runme.sh b/examples/igloo2/runme.sh index a08894e0a..7349ff603 100644 --- a/examples/igloo2/runme.sh +++ b/examples/igloo2/runme.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v export LM_LICENSE_FILE=${LM_LICENSE_FILE:-1702@localhost} diff --git a/examples/intel/DE2i-150/quartus_compile/runme_quartus b/examples/intel/DE2i-150/quartus_compile/runme_quartus index 83aa3b609..2bc29582c 100644 --- a/examples/intel/DE2i-150/quartus_compile/runme_quartus +++ b/examples/intel/DE2i-150/quartus_compile/runme_quartus @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash export REV="de2i" diff --git a/examples/intel/MAX10/runme_postsynth b/examples/intel/MAX10/runme_postsynth index f16210540..657c05fa8 100644 --- a/examples/intel/MAX10/runme_postsynth +++ b/examples/intel/MAX10/runme_postsynth @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash iverilog -D POST_IMPL -o verif_post -s tb_top tb_top.v top.vqm $(yosys-config --datdir/altera_intel/max10/cells_comb_max10.v) vvp -N verif_post diff --git a/examples/intel/asicworld_lfsr/run_cycloneiv b/examples/intel/asicworld_lfsr/run_cycloneiv index c7498bded..077b7fbde 100755 --- a/examples/intel/asicworld_lfsr/run_cycloneiv +++ b/examples/intel/asicworld_lfsr/run_cycloneiv @@ -1,2 +1,2 @@ -#!/bin/env bash +#!/usr/bin/env bash yosys -p "synth_intel -family cycloneiv -top lfsr_updown -vqm top.vqm" lfsr_updown.v diff --git a/examples/intel/asicworld_lfsr/run_max10 b/examples/intel/asicworld_lfsr/run_max10 index b75d552bb..8fccb57f8 100755 --- a/examples/intel/asicworld_lfsr/run_max10 +++ b/examples/intel/asicworld_lfsr/run_max10 @@ -1,2 +1,2 @@ -#!/bin/env bash +#!/usr/bin/env bash yosys -p "synth_intel -family max10 -top lfsr_updown -vqm top.vqm" lfsr_updown.v diff --git a/examples/intel/asicworld_lfsr/runme_postsynth b/examples/intel/asicworld_lfsr/runme_postsynth index c3b26b034..ad5ca39d4 100755 --- a/examples/intel/asicworld_lfsr/runme_postsynth +++ b/examples/intel/asicworld_lfsr/runme_postsynth @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash iverilog -D POST_IMPL -o verif_post -s tb lfsr_updown_tb.v top.vqm $(yosys-config --datdir/altera_intel/max10/cells_comb_max10.v) vvp -N verif_post diff --git a/examples/intel/asicworld_lfsr/runme_presynth b/examples/intel/asicworld_lfsr/runme_presynth index 51118bb4b..3ed6618d3 100755 --- a/examples/intel/asicworld_lfsr/runme_presynth +++ b/examples/intel/asicworld_lfsr/runme_presynth @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash iverilog -o presynth lfsr_updown_tb.v lfsr_updown.v &&\ diff --git a/examples/mimas2/run.sh b/examples/mimas2/run.sh index aafde78ed..b16341ece 100644 --- a/examples/mimas2/run.sh +++ b/examples/mimas2/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env sh set -e yosys run_yosys.ys edif2ngd example.edif diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 9931ef78f..b2cc613f2 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -224,7 +224,7 @@ AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module = new RTLIL::Module; module->name = module_name; if (design->module(module->name)) - log_error("Duplicate definition of module %s!\n", log_id(module->name)); + log_error("Duplicate definition of module %s!\n", module->name.unescape()); } void AigerReader::parse_aiger() @@ -821,7 +821,7 @@ void AigerReader::post_process() RTLIL::Wire* wire = inputs[variable]; log_assert(wire); log_assert(wire->port_input); - log_debug("Renaming input %s", log_id(wire)); + log_debug("Renaming input %s", wire); RTLIL::Wire *existing = nullptr; if (index == 0) { @@ -835,7 +835,7 @@ void AigerReader::post_process() wire->port_input = false; module->connect(wire, existing); } - log_debug(" -> %s\n", log_id(escaped_s)); + log_debug(" -> %s\n", escaped_s.unescape()); } else { RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index); @@ -846,7 +846,7 @@ void AigerReader::post_process() module->connect(wire, existing); wire->port_input = false; } - log_debug(" -> %s\n", log_id(indexed_name)); + log_debug(" -> %s\n", indexed_name.unescape()); } if (wideports && !existing) { @@ -866,7 +866,7 @@ void AigerReader::post_process() RTLIL::Wire* wire = outputs[variable + co_count]; log_assert(wire); log_assert(wire->port_output); - log_debug("Renaming output %s", log_id(wire)); + log_debug("Renaming output %s", wire); RTLIL::Wire *existing; if (index == 0) { @@ -882,7 +882,7 @@ void AigerReader::post_process() module->connect(wire, existing); wire = existing; } - log_debug(" -> %s\n", log_id(escaped_s)); + log_debug(" -> %s\n", escaped_s.unescape()); } else { RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index); @@ -894,7 +894,7 @@ void AigerReader::post_process() existing->port_output = true; module->connect(wire, existing); } - log_debug(" -> %s\n", log_id(indexed_name)); + log_debug(" -> %s\n", indexed_name.unescape()); } if (wideports && !existing) { @@ -912,7 +912,7 @@ void AigerReader::post_process() else if (type == "box") { RTLIL::Cell* cell = module->cell(stringf("$box%d", variable)); if (!cell) - log_debug("Box %d (%s) no longer exists.\n", variable, log_id(escaped_s)); + log_debug("Box %d (%s) no longer exists.\n", variable, escaped_s.unescape()); else module->rename(cell, escaped_s); } diff --git a/frontends/aiger2/xaiger.cc b/frontends/aiger2/xaiger.cc index 510da0be8..a62c52169 100644 --- a/frontends/aiger2/xaiger.cc +++ b/frontends/aiger2/xaiger.cc @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN uint32_t read_be32(std::istream &f) { return ((uint32_t) f.get() << 24) | - ((uint32_t) f.get() << 16) | + ((uint32_t) f.get() << 16) | ((uint32_t) f.get() << 8) | (uint32_t) f.get(); } @@ -80,13 +80,13 @@ struct Xaiger2Frontend : public Frontend { extra_args(f, filename, args, argidx, true); if (map_filename.empty()) - log_error("A '-map2' argument required\n"); + log_error("A '-map2' argument is required\n"); if (module_name.empty()) - log_error("A '-module_name' argument required\n"); + log_error("A '-module_name' argument is required\n"); Module *module = design->module(module_name); if (!module) - log_error("Module '%s' not found\n", log_id(module_name)); + log_error("Module '%s' not found\n", module_name.unescape()); std::ifstream map_file; map_file.open(map_filename); @@ -128,10 +128,10 @@ struct Xaiger2Frontend : public Frontend { int woffset; std::string name; if (!(map_file >> pi_idx >> woffset >> name)) - log_error("Bad map file (1)\n"); + log_error("Bad map file: couldn't read 'pi' line\n"); int lit = (2 * pi_idx) + 2; if (lit < 0 || lit >= (int) bits.size()) - log_error("Bad map file (2)\n"); + log_error("Bad map file: primary input literal out of range\n"); Wire *w = module->wire(name); if (!w || woffset < 0 || woffset >= w->width) log_error("Map file references non-existent signal bit %s[%d]\n", @@ -141,9 +141,9 @@ struct Xaiger2Frontend : public Frontend { int box_seq; std::string name; if (!(map_file >> box_seq >> name)) - log_error("Bad map file (20)\n"); + log_error("Bad map file: couldn't read 'box' line\n"); if (box_seq < 0) - log_error("Bad map file (21)\n"); + log_error("Bad map file: box out of range\n"); Cell *box = module->cell(RTLIL::escape_id(name)); if (!box) @@ -158,7 +158,7 @@ struct Xaiger2Frontend : public Frontend { } if (!def) - log_error("Bad map file (22)\n"); + log_error("Bad map file: no module found for box type '%s'\n", box->type.unescape()); if (box_seq >= (int) boxes.size()) { boxes.resize(box_seq + 1); @@ -276,9 +276,9 @@ struct Xaiger2Frontend : public Frontend { uint32_t nins = read_be32(*f); for (uint32_t j = 0; j < nins; j++) cell.ins.push_back(read_idstring(*f)); - log_debug("M: Cell %s (out %s, ins", log_id(cell.type), log_id(cell.out)); + log_debug("M: Cell %s (out %s, ins", cell.type.unescape(), cell.out.unescape()); for (auto in : cell.ins) - log_debug(" %s", log_id(in)); + log_debug(" %s", in.unescape()); log_debug(")\n"); } @@ -403,15 +403,15 @@ struct Xaiger2Frontend : public Frontend { int woffset; std::string name; if (!(map_file >> po_idx >> woffset >> name)) - log_error("Bad map file (3)\n"); + log_error("Bad map file: couldn't read 'po' line\n"); po_idx += co_counter; if (po_idx < 0 || po_idx >= (int) outputs.size()) - log_error("Bad map file (4)\n"); + log_error("Bad map file: primary output index out of range\n"); int lit = outputs[po_idx]; if (lit < 0 || lit >= (int) bits.size()) - log_error("Bad map file (5)\n"); + log_error("Bad map file: primary output literal out of range\n"); if (bits[lit] == RTLIL::Sm) - log_error("Bad map file (6)\n"); + log_error("Bad map file: primary output literal is a marker\n"); Wire *w = module->wire(name); if (!w || woffset < 0 || woffset >= w->width) log_error("Map file references non-existent signal bit %s[%d]\n", @@ -423,15 +423,15 @@ struct Xaiger2Frontend : public Frontend { std::string box_name; std::string box_port; if (!(map_file >> po_idx >> poffset >> box_name >> box_port)) - log_error("Bad map file (7)\n"); + log_error("Bad map file: couldn't read 'pseudopo' line\n"); po_idx += co_counter; if (po_idx < 0 || po_idx >= (int) outputs.size()) - log_error("Bad map file (8)\n"); + log_error("Bad map file: pseudo primary output index out of range\n"); int lit = outputs[po_idx]; if (lit < 0 || lit >= (int) bits.size()) - log_error("Bad map file (9)\n"); + log_error("Bad map file: pseudo primary output literal out of range\n"); if (bits[lit] == RTLIL::Sm) - log_error("Bad map file (10)\n"); + log_error("Bad map file: pseudo primary output literal is a marker\n"); Cell *cell = module->cell(box_name); if (!cell || !cell->hasPort(box_port)) log_error("Map file references non-existent box port %s/%s\n", diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 984c4294c..f5a601c3a 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -100,6 +100,7 @@ std::string AST::type2str(AstNodeType type) X(AST_CAST_SIZE) X(AST_CONCAT) X(AST_REPLICATE) + X(AST_ASSIGN_PATTERN) X(AST_BIT_NOT) X(AST_BIT_AND) X(AST_BIT_OR) @@ -696,6 +697,16 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const fprintf(f, "}}"); break; + case AST_ASSIGN_PATTERN: + fprintf(f, "'{"); + for (int i = 0; i < GetSize(children); i++) { + if (i != 0) + fprintf(f, ", "); + children[i]->dumpVlog(f, ""); + } + fprintf(f, "}"); + break; + if (0) { case AST_BIT_NOT: txt = "~"; } if (0) { case AST_REDUCE_AND: txt = "&"; } if (0) { case AST_REDUCE_OR: txt = "|"; } @@ -1533,7 +1544,7 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule for (auto w : intfmodule->wires()){ auto loc = module_ast->location; auto wire = std::make_unique(loc, AST_WIRE, std::make_unique(loc, AST_RANGE, AstNode::mkconst_int(loc, w->width -1, true), AstNode::mkconst_int(loc, 0, true))); - std::string origname = log_id(w->name); + std::string origname = w->name.unescape(); std::string newname = intfname + "." + origname; wire->str = newname; if (modport != NULL) { @@ -1573,7 +1584,7 @@ bool AstModule::reprocess_if_necessary(RTLIL::Design *design) continue; if (design->module(modname) || design->module("$abstract" + modname)) { log("Reprocessing module %s because instantiated module %s has become available.\n", - log_id(name), log_id(modname)); + name.unescape(), RTLIL::unescape_id(modname)); loadconfig(); process_and_replace_module(design, this, ast.get(), NULL); return true; @@ -1595,7 +1606,7 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dictwires()){ auto wire = std::make_unique(loc, AST_WIRE, std::make_unique(loc, AST_RANGE, AstNode::mkconst_int(loc, w->width -1, true), AstNode::mkconst_int(loc, 0, true))); - std::string newname = log_id(w->name); + std::string newname = w->name.unescape(); newname = intfname + "." + newname; wire->str = newname; new_ast->children.push_back(std::move(wire)); @@ -1668,7 +1679,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dictname); + interf_info += intf.second->name.unescape(); has_interfaces = true; } @@ -1724,7 +1735,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dictset_bool_attribute(ID::is_interface); } else { - log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname); + log_error("No port with matching name found (%s) in %s. Stopping\n", intf.first, modname); } } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index fd8ecddd7..f92b4a5b8 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -78,6 +78,7 @@ namespace AST AST_CAST_SIZE, AST_CONCAT, AST_REPLICATE, + AST_ASSIGN_PATTERN, AST_BIT_NOT, AST_BIT_AND, AST_BIT_OR, diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 5e0356fd3..718d5aa23 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -798,7 +798,7 @@ struct AST_INTERNAL::ProcessGenerator break; case AST_ASSIGN: - ast->input_error("Found continous assignment in always/initial block!\n"); + ast->input_error("Found continuous assignment in always/initial block!\n"); break; case AST_PARAMETER: @@ -1212,6 +1212,15 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun sign_hint = false; break; + case AST_ASSIGN_PATTERN: + for (auto& child : children) { + sub_width_hint = 0; + sub_sign_hint = true; + child->detectSignWidthWorker(sub_width_hint, sub_sign_hint); + } + sign_hint = false; + break; + case AST_NEG: case AST_BIT_NOT: case AST_POS: @@ -1824,6 +1833,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) return sig; } + case AST_ASSIGN_PATTERN: + input_error("Assignment pattern is only supported for whole unpacked array assignments.\n"); + // generate cells for unary operations: $not, $pos, $neg if (0) { case AST_BIT_NOT: type_name = ID($not); } if (0) { case AST_POS: type_name = ID($pos); } @@ -2185,10 +2197,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) const auto* value = child->children[0].get(); if (value->type == AST_REALVALUE) log_file_warning(*location.begin.filename, location.begin.line, "Replacing floating point parameter %s.%s = %f with string.\n", - log_id(cell), log_id(paraname), value->realvalue); + cell, paraname.unescape(), value->realvalue); else if (value->type != AST_CONSTANT) input_error("Parameter %s.%s with non-constant value!\n", - log_id(cell), log_id(paraname)); + cell, paraname.unescape()); cell->parameters[paraname] = value->asParaConst(); continue; } diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index f314ff3d5..95dca27d8 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -91,6 +91,11 @@ void AstNode::fixup_hierarchy_flags(bool force_descend) children[0]->set_in_param_flag(true, force_descend); break; + case AST_ASSIGN_PATTERN: + for (auto& child : children) + child->set_in_param_flag(in_param, force_descend); + break; + case AST_GENFOR: case AST_FOR: for (auto& child : children) { @@ -297,6 +302,23 @@ static bool arrays_have_compatible_dims(AstNode *mem_a, AstNode *mem_b) return a_width == b_width; } +// Check if mem_b matches mem_a's unpacked dimensions starting at first_dim. +static bool arrays_have_compatible_dims_from(AstNode *mem_a, int first_dim, AstNode *mem_b) +{ + if (mem_b->unpacked_dimensions != mem_a->unpacked_dimensions - first_dim) + return false; + for (int i = 0; i < mem_b->unpacked_dimensions; i++) { + if (mem_a->dimensions[first_dim + i].range_width != mem_b->dimensions[i].range_width) + return false; + } + // Also check packed dimensions (element width) + int a_width, a_size, a_bits; + int b_width, b_size, b_bits; + mem_a->meminfo(a_width, a_size, a_bits); + mem_b->meminfo(b_width, b_size, b_bits); + return a_width == b_width; +} + // Convert per-dimension element positions to declared index values. // Position 0 is the first declared element for each unpacked dimension. static std::vector array_indices_from_position(AstNode *mem, const std::vector &position) @@ -1470,7 +1492,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin const RTLIL::Wire *ref = module->wire(port_name); if (ref == nullptr) input_error("Cell instance refers to port %s which does not exist in module %s!.\n", - log_id(port_name), log_id(module->name)); + port_name.unescape(), module->name.unescape()); // select the argument, if present log_assert(child->children.size() <= 1); @@ -1730,6 +1752,12 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin children_are_self_determined = true; break; + case AST_ASSIGN_PATTERN: + // Assignment pattern elements are context-determined by the target element type. + // Keep child width context intact until whole-array assignment expansion creates scalar assignments. + detect_width_simple = true; + break; + case AST_NEG: case AST_BIT_NOT: case AST_POS: @@ -3222,7 +3250,7 @@ skip_dynamic_range_lvalue_expansion:; if (stage > 1 && type == AST_IDENTIFIER && id2ast != nullptr && id2ast->type == AST_MEMORY && !in_lvalue && children.size() == 1 && children[0]->type == AST_RANGE && children[0]->children.size() == 1) { if (integer < (unsigned)id2ast->unpacked_dimensions) - input_error("Insufficient number of array indices for %s.\n", log_id(str)); + input_error("Insufficient number of array indices for %s.\n", RTLIL::unescape_id(str)); newNode = std::make_unique(location, AST_MEMRD, children[0]->children[0]->clone()); newNode->str = str; newNode->id2ast = id2ast; @@ -3277,7 +3305,7 @@ skip_dynamic_range_lvalue_expansion:; } } - // Expand array assignment: arr_out = arr_in OR arr_out = cond ? arr_a : arr_b + // Expand array assignment: arr_out = arr_in OR arr_out = cond ? arr_a : arr_b OR arr_out = '{a, b} // Supports multi-dimensional unpacked arrays if ((type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE || type == AST_ASSIGN) && is_unexpanded_array_ref(children[0].get())) @@ -3294,30 +3322,27 @@ skip_dynamic_range_lvalue_expansion:; is_unexpanded_array_ref(rhs->children[1].get()) && is_unexpanded_array_ref(rhs->children[2].get())); - if (is_direct_assign || is_ternary_assign) + // Case 3: Positional assignment pattern (out = '{a, b}) + bool is_pattern_assign = rhs->type == AST_ASSIGN_PATTERN; + + if (is_direct_assign || is_ternary_assign || is_pattern_assign) { AstNode *direct_rhs_mem = nullptr; AstNode *true_mem = nullptr; AstNode *false_mem = nullptr; - // Validate array compatibility - if (is_direct_assign) { - direct_rhs_mem = rhs->id2ast; - if (!arrays_have_compatible_dims(lhs_mem, direct_rhs_mem)) - input_error("Array dimension mismatch in assignment\n"); - } else { - true_mem = rhs->children[1]->id2ast; - false_mem = rhs->children[2]->id2ast; - if (!arrays_have_compatible_dims(lhs_mem, true_mem) || - !arrays_have_compatible_dims(lhs_mem, false_mem)) - input_error("Array dimension mismatch in ternary expression\n"); - } - int num_dims = lhs_mem->unpacked_dimensions; + int total_elements = 1; + for (int d = 0; d < num_dims; d++) + total_elements *= lhs_mem->dimensions[d].range_width; + int element_width, mem_size, addr_bits; + lhs_mem->meminfo(element_width, mem_size, addr_bits); + bool pattern_is_flat = false; - // Helper to add index to an identifier clone + // Helper to add indices to an array identifier clone. auto add_indices_to_id = [&](std::unique_ptr id, const std::vector& indices) { - if (num_dims == 1) { + int indexed_dims = GetSize(indices); + if (indexed_dims == 1) { // Single dimension: use AST_RANGE id->children.push_back(std::make_unique(location, AST_RANGE, mkconst_int(location, indices[0], true))); @@ -3330,44 +3355,139 @@ skip_dynamic_range_lvalue_expansion:; } id->children.push_back(std::move(multirange)); } - id->integer = num_dims; + id->integer = indexed_dims; // Reset basic_prep so multirange gets resolved during subsequent simplify passes id->basic_prep = false; return id; }; - // Calculate total number of elements and warn if large - int total_elements = 1; - for (int d = 0; d < num_dims; d++) - total_elements *= lhs_mem->dimensions[d].range_width; + auto add_position_to_id = [&](std::unique_ptr id, AstNode *mem, const std::vector& position) { + return add_indices_to_id(std::move(id), array_indices_from_position(mem, position)); + }; + + // Validate nested assignment pattern shape against unpacked dimensions. + std::function validate_pattern_shape = [&](AstNode *pattern, int dim) { + log_assert(pattern->type == AST_ASSIGN_PATTERN); + + int expected = lhs_mem->dimensions[dim].range_width; + if (GetSize(pattern->children) != expected) + input_error("Assignment pattern element count mismatch at dimension %d: got %d, expected %d\n", + dim + 1, GetSize(pattern->children), expected); + + if (dim + 1 == num_dims) + return; + + for (auto& child : pattern->children) { + if (child->type == AST_ASSIGN_PATTERN) { + validate_pattern_shape(child.get(), dim + 1); + } else if (is_unexpanded_array_ref(child.get()) && + arrays_have_compatible_dims_from(lhs_mem, dim + 1, child->id2ast)) { + continue; + } else { + input_error("Nested assignment pattern or compatible array expression required for dimension %d\n", dim + 2); + } + } + }; + + // Select the assignment pattern element for an unpacked array position. + auto pattern_element_at_position = [&](const std::vector& position, int flat_index) { + if (pattern_is_flat) + return rhs->children[flat_index]->clone(); + + AstNode *pattern = rhs; + for (int d = 0; d < num_dims; d++) { + log_assert(pattern->type == AST_ASSIGN_PATTERN); + AstNode *element = pattern->children[position[d]].get(); + + if (d + 1 == num_dims) + return element->clone(); + + if (element->type == AST_ASSIGN_PATTERN) { + pattern = element; + } else { + std::vector subposition(position.begin() + d + 1, position.end()); + return add_position_to_id(element->clone(), element->id2ast, subposition); + } + } + log_abort(); + }; + + // Validate array compatibility + if (is_direct_assign) { + direct_rhs_mem = rhs->id2ast; + if (!arrays_have_compatible_dims(lhs_mem, direct_rhs_mem)) + input_error("Array dimension mismatch in assignment\n"); + } else if (is_ternary_assign) { + true_mem = rhs->children[1]->id2ast; + false_mem = rhs->children[2]->id2ast; + if (!arrays_have_compatible_dims(lhs_mem, true_mem) || + !arrays_have_compatible_dims(lhs_mem, false_mem)) + input_error("Array dimension mismatch in ternary expression\n"); + } else { + if (num_dims > 1 && GetSize(rhs->children) == lhs_mem->dimensions[0].range_width) { + validate_pattern_shape(rhs, 0); + } else if (num_dims == 1 && GetSize(rhs->children) == total_elements) { + pattern_is_flat = true; + } else { + if (num_dims > 1 && GetSize(rhs->children) == lhs_mem->dimensions[0].range_width) + validate_pattern_shape(rhs, 0); + int expected = num_dims > 1 ? lhs_mem->dimensions[0].range_width : total_elements; + input_error("Assignment pattern element count mismatch: got %d, expected %d\n", GetSize(rhs->children), expected); + } + } + + // Warn if array assignment expansion is large. if (total_elements > 10000) log_warning("Expanding array assignment with %d elements at %s, this may be slow.\n", total_elements, location.to_string().c_str()); // Collect all assignments std::vector> assignments; + std::vector> pattern_temp_assignments; foreach_array_position(lhs_mem, [&](const std::vector& position) { - auto lhs_indices = array_indices_from_position(lhs_mem, position); - auto lhs_idx = add_indices_to_id(lhs->clone(), lhs_indices); + auto lhs_idx = add_position_to_id(lhs->clone(), lhs_mem, position); std::unique_ptr rhs_expr; if (is_direct_assign) { - auto rhs_indices = array_indices_from_position(direct_rhs_mem, position); - rhs_expr = add_indices_to_id(rhs->clone(), rhs_indices); - } else { + rhs_expr = add_position_to_id(rhs->clone(), direct_rhs_mem, position); + } else if (is_ternary_assign) { // Ternary case AstNode *cond = rhs->children[0].get(); AstNode *true_val = rhs->children[1].get(); AstNode *false_val = rhs->children[2].get(); - auto true_indices = array_indices_from_position(true_mem, position); - auto false_indices = array_indices_from_position(false_mem, position); - auto true_idx = add_indices_to_id(true_val->clone(), true_indices); - auto false_idx = add_indices_to_id(false_val->clone(), false_indices); + auto true_idx = add_position_to_id(true_val->clone(), true_mem, position); + auto false_idx = add_position_to_id(false_val->clone(), false_mem, position); rhs_expr = std::make_unique(location, AST_TERNARY, cond->clone(), std::move(true_idx), std::move(false_idx)); + } else { + auto pattern_rhs = pattern_element_at_position(position, GetSize(assignments)); + + if (type == AST_ASSIGN_EQ) { + auto wire_tmp_owned = std::make_unique(location, AST_WIRE, + std::make_unique(location, AST_RANGE, + mkconst_int(location, element_width - 1, true), + mkconst_int(location, 0, true))); + auto wire_tmp = wire_tmp_owned.get(); + wire_tmp->str = stringf("$assignpattern$%s:%d$%d", + RTLIL::encode_filename(*location.begin.filename), location.begin.line, autoidx++); + current_scope[wire_tmp->str] = wire_tmp; + current_ast_mod->children.push_back(std::move(wire_tmp_owned)); + wire_tmp->set_attribute(ID::nosync, AstNode::mkconst_int(location, 1, false)); + while (wire_tmp->simplify(true, 1, -1, false)) { } + wire_tmp->is_logic = true; + wire_tmp->is_signed = lhs_mem->is_signed; + + auto tmp_id = std::make_unique(location, AST_IDENTIFIER); + tmp_id->str = wire_tmp->str; + pattern_temp_assignments.push_back(std::make_unique(location, AST_ASSIGN_EQ, + tmp_id->clone(), std::move(pattern_rhs))); + rhs_expr = std::move(tmp_id); + } else { + rhs_expr = std::move(pattern_rhs); + } } auto assign = std::make_unique(location, type, @@ -3386,6 +3506,8 @@ skip_dynamic_range_lvalue_expansion:; } else { // Wrap in AST_BLOCK for procedural newNode = std::make_unique(location, AST_BLOCK); + for (auto& assign : pattern_temp_assignments) + newNode->children.push_back(std::move(assign)); for (auto& assign : assignments) newNode->children.push_back(std::move(assign)); } @@ -3401,7 +3523,7 @@ skip_dynamic_range_lvalue_expansion:; (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE) { if (children[0]->integer < (unsigned)children[0]->id2ast->unpacked_dimensions) - input_error("Insufficient number of array indices for %s.\n", log_id(str)); + input_error("Insufficient number of array indices for %s.\n", RTLIL::unescape_id(str)); std::stringstream sstr; sstr << "$memwr$" << children[0]->str << "$" << RTLIL::encode_filename(*location.begin.filename) << ":" << location.begin.line << "$" << (autoidx++); @@ -4652,6 +4774,8 @@ replace_fcall_later:; tmp_bits.insert(tmp_bits.end(), children.at(1)->bits.begin(), children.at(1)->bits.end()); newNode = children.at(1)->is_string ? mkconst_str(location, tmp_bits) : mkconst_bits(location, tmp_bits, false); break; + case AST_ASSIGN_PATTERN: + goto not_const; default: not_const: break; @@ -5149,7 +5273,7 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg AstNode *mem = id2ast; if (integer < (unsigned)mem->unpacked_dimensions) - input_error("Insufficient number of array indices for %s.\n", log_id(str)); + input_error("Insufficient number of array indices for %s.\n", RTLIL::unescape_id(str)); // flag if used after blocking assignment (in same proc) if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) { diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 350d7cafe..2eae64fa1 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -175,7 +175,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool obj_attributes = &module->attributes; obj_parameters = nullptr; if (design->module(module->name)) - log_error("Duplicate definition of module %s in line %d!\n", log_id(module->name), line_count); + log_error("Duplicate definition of module %s in line %d!\n", module->name.unescape(), line_count); design->add(module); continue; } diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index 803931f32..0fac902b5 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -295,7 +295,7 @@ void json_import(Design *design, string &modname, JsonNode *node) module->name = RTLIL::escape_id(modname.c_str()); if (design->module(module->name)) - log_error("Re-definition of module %s.\n", log_id(module->name)); + log_error("Re-definition of module %s.\n", module->name.unescape()); design->add(module); @@ -320,22 +320,22 @@ void json_import(Design *design, string &modname, JsonNode *node) JsonNode *port_node = ports_node->data_dict.at(ports_node->data_dict_keys[port_id-1]); if (port_node->type != 'D') - log_error("JSON port node '%s' is not a dictionary.\n", log_id(port_name)); + log_error("JSON port node '%s' is not a dictionary.\n", port_name.unescape()); if (port_node->data_dict.count("direction") == 0) - log_error("JSON port node '%s' has no direction attribute.\n", log_id(port_name)); + log_error("JSON port node '%s' has no direction attribute.\n", port_name.unescape()); if (port_node->data_dict.count("bits") == 0) - log_error("JSON port node '%s' has no bits attribute.\n", log_id(port_name)); + log_error("JSON port node '%s' has no bits attribute.\n", port_name.unescape()); JsonNode *port_direction_node = port_node->data_dict.at("direction"); JsonNode *port_bits_node = port_node->data_dict.at("bits"); if (port_direction_node->type != 'S') - log_error("JSON port node '%s' has non-string direction attribute.\n", log_id(port_name)); + log_error("JSON port node '%s' has non-string direction attribute.\n", port_name.unescape()); if (port_bits_node->type != 'A') - log_error("JSON port node '%s' has non-array bits attribute.\n", log_id(port_name)); + log_error("JSON port node '%s' has non-array bits attribute.\n", port_name.unescape()); Wire *port_wire = module->wire(port_name); @@ -370,7 +370,7 @@ void json_import(Design *design, string &modname, JsonNode *node) port_wire->port_input = true; port_wire->port_output = true; } else - log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", log_id(port_name), port_direction_node->data_string); + log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", port_name.unescape(), port_direction_node->data_string); port_wire->port_id = port_id; @@ -390,7 +390,7 @@ void json_import(Design *design, string &modname, JsonNode *node) module->connect(sigbit, State::Sz); else log_error("JSON port node '%s' has invalid '%s' bit string value on bit %d.\n", - log_id(port_name), bitval_node->data_string.c_str(), i); + port_name.unescape(), bitval_node->data_string.c_str(), i); } else if (bitval_node->type == 'N') { int bitidx = bitval_node->data_number; @@ -405,7 +405,7 @@ void json_import(Design *design, string &modname, JsonNode *node) signal_bits[bitidx] = sigbit; } } else - log_error("JSON port node '%s' has invalid bit value on bit %d.\n", log_id(port_name), i); + log_error("JSON port node '%s' has invalid bit value on bit %d.\n", port_name.unescape(), i); } } @@ -425,15 +425,15 @@ void json_import(Design *design, string &modname, JsonNode *node) JsonNode *net_node = net.second; if (net_node->type != 'D') - log_error("JSON netname node '%s' is not a dictionary.\n", log_id(net_name)); + log_error("JSON netname node '%s' is not a dictionary.\n", net_name.unescape()); if (net_node->data_dict.count("bits") == 0) - log_error("JSON netname node '%s' has no bits attribute.\n", log_id(net_name)); + log_error("JSON netname node '%s' has no bits attribute.\n", net_name.unescape()); JsonNode *bits_node = net_node->data_dict.at("bits"); if (bits_node->type != 'A') - log_error("JSON netname node '%s' has non-array bits attribute.\n", log_id(net_name)); + log_error("JSON netname node '%s' has non-array bits attribute.\n", net_name.unescape()); Wire *wire = module->wire(net_name); @@ -468,7 +468,7 @@ void json_import(Design *design, string &modname, JsonNode *node) module->connect(sigbit, State::Sz); else log_error("JSON netname node '%s' has invalid '%s' bit string value on bit %d.\n", - log_id(net_name), bitval_node->data_string.c_str(), i); + net_name.unescape(), bitval_node->data_string.c_str(), i); } else if (bitval_node->type == 'N') { int bitidx = bitval_node->data_number; @@ -479,7 +479,7 @@ void json_import(Design *design, string &modname, JsonNode *node) signal_bits[bitidx] = sigbit; } } else - log_error("JSON netname node '%s' has invalid bit value on bit %d.\n", log_id(net_name), i); + log_error("JSON netname node '%s' has invalid bit value on bit %d.\n", net_name.unescape(), i); } if (net_node->data_dict.count("attributes")) @@ -500,27 +500,27 @@ void json_import(Design *design, string &modname, JsonNode *node) JsonNode *cell_node = cell_node_it.second; if (cell_node->type != 'D') - log_error("JSON cells node '%s' is not a dictionary.\n", log_id(cell_name)); + log_error("JSON cells node '%s' is not a dictionary.\n", cell_name.unescape()); if (cell_node->data_dict.count("type") == 0) - log_error("JSON cells node '%s' has no type attribute.\n", log_id(cell_name)); + log_error("JSON cells node '%s' has no type attribute.\n", cell_name.unescape()); JsonNode *type_node = cell_node->data_dict.at("type"); if (type_node->type != 'S') - log_error("JSON cells node '%s' has a non-string type.\n", log_id(cell_name)); + log_error("JSON cells node '%s' has a non-string type.\n", cell_name.unescape()); IdString cell_type = RTLIL::escape_id(type_node->data_string.c_str()); Cell *cell = module->addCell(cell_name, cell_type); if (cell_node->data_dict.count("connections") == 0) - log_error("JSON cells node '%s' has no connections attribute.\n", log_id(cell_name)); + log_error("JSON cells node '%s' has no connections attribute.\n", cell_name.unescape()); JsonNode *connections_node = cell_node->data_dict.at("connections"); if (connections_node->type != 'D') - log_error("JSON cells node '%s' has non-dictionary connections attribute.\n", log_id(cell_name)); + log_error("JSON cells node '%s' has non-dictionary connections attribute.\n", cell_name.unescape()); for (auto &conn_it : connections_node->data_dict) { @@ -528,7 +528,7 @@ void json_import(Design *design, string &modname, JsonNode *node) JsonNode *conn_node = conn_it.second; if (conn_node->type != 'A') - log_error("JSON cells node '%s' connection '%s' is not an array.\n", log_id(cell_name), log_id(conn_name)); + log_error("JSON cells node '%s' connection '%s' is not an array.\n", cell_name.unescape(), conn_name.unescape()); SigSpec sig; @@ -547,7 +547,7 @@ void json_import(Design *design, string &modname, JsonNode *node) sig.append(State::Sz); else log_error("JSON cells node '%s' connection '%s' has invalid '%s' bit string value on bit %d.\n", - log_id(cell_name), log_id(conn_name), bitval_node->data_string.c_str(), i); + cell_name.unescape(), conn_name.unescape(), bitval_node->data_string.c_str(), i); } else if (bitval_node->type == 'N') { int bitidx = bitval_node->data_number; @@ -556,7 +556,7 @@ void json_import(Design *design, string &modname, JsonNode *node) sig.append(signal_bits.at(bitidx)); } else log_error("JSON cells node '%s' connection '%s' has invalid bit value on bit %d.\n", - log_id(cell_name), log_id(conn_name), i); + cell_name.unescape(), conn_name.unescape(), i); } @@ -587,20 +587,20 @@ void json_import(Design *design, string &modname, JsonNode *node) mem->name = memory_name; if (memory_node->type != 'D') - log_error("JSON memory node '%s' is not a dictionary.\n", log_id(memory_name)); + log_error("JSON memory node '%s' is not a dictionary.\n", memory_name.unescape()); if (memory_node->data_dict.count("width") == 0) - log_error("JSON memory node '%s' has no width attribute.\n", log_id(memory_name)); + log_error("JSON memory node '%s' has no width attribute.\n", memory_name.unescape()); JsonNode *width_node = memory_node->data_dict.at("width"); if (width_node->type != 'N') - log_error("JSON memory node '%s' has a non-number width.\n", log_id(memory_name)); + log_error("JSON memory node '%s' has a non-number width.\n", memory_name.unescape()); mem->width = width_node->data_number; if (memory_node->data_dict.count("size") == 0) - log_error("JSON memory node '%s' has no size attribute.\n", log_id(memory_name)); + log_error("JSON memory node '%s' has no size attribute.\n", memory_name.unescape()); JsonNode *size_node = memory_node->data_dict.at("size"); if (size_node->type != 'N') - log_error("JSON memory node '%s' has a non-number size.\n", log_id(memory_name)); + log_error("JSON memory node '%s' has a non-number size.\n", memory_name.unescape()); mem->size = size_node->data_number; mem->start_offset = 0; diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index c21867b30..bc5ef013d 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -212,7 +212,7 @@ struct RpcModule : RTLIL::Module { for (auto module : derived_design->modules_) { std::string mangled_name = name_mangling[module.first.str()]; - log("Importing `%s' as `%s'.\n", log_id(module.first), log_id(mangled_name)); + log("Importing `%s' as `%s'.\n", module.first.unescape(), mangled_name); module.second->name = mangled_name; module.second->design = design; diff --git a/frontends/rtlil/rtlil_frontend.cc b/frontends/rtlil/rtlil_frontend.cc index 7e2ec5460..4709c76ed 100644 --- a/frontends/rtlil/rtlil_frontend.cc +++ b/frontends/rtlil/rtlil_frontend.cc @@ -332,7 +332,7 @@ struct RTLILFrontendWorker { error("No wires found for legalization"); int hash = hash_ops::hash(id).yield(); RTLIL::Wire *wire = current_module->wire_at(abs(hash % wires_size)); - log("Legalizing wire `%s' to `%s'.\n", log_id(id), log_id(wire->name)); + log("Legalizing wire `%s' to `%s'.\n", id.unescape(), wire->name.unescape()); return wire; } diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 6a1c81aa4..ec3d21ccd 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1392,13 +1392,13 @@ void VerificImporter::merge_past_ffs_clock(pool &candidates, SigBi RTLIL::Cell *new_ff = module->addDff(NEW_ID, clock, sig_d, sig_q, clock_pol); if (verific_verbose) - log(" merging single-bit past_ffs into new %d-bit ff %s.\n", GetSize(sig_d), log_id(new_ff)); + log(" merging single-bit past_ffs into new %d-bit ff %s.\n", GetSize(sig_d), new_ff); for (int i = 0; i < GetSize(sig_d); i++) for (auto old_ff : dbits_db[sig_d[i]]) { if (verific_verbose) - log(" replacing old ff %s on bit %d.\n", log_id(old_ff), i); + log(" replacing old ff %s on bit %d.\n", old_ff, i); SigBit old_q = old_ff->getPort(ID::Q); SigBit new_q = sig_q[i]; @@ -1736,7 +1736,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : new_verific_id(net)); if (verific_verbose) - log(" importing net %s as %s.\n", net->Name(), log_id(wire_name)); + log(" importing net %s as %s.\n", net->Name(), wire_name.unescape()); RTLIL::Wire *wire = module->addWire(wire_name); import_attributes(wire->attributes, net, nl, 1); @@ -1760,7 +1760,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : new_verific_id(netbus)); if (verific_verbose) - log(" importing netbus %s as %s.\n", netbus->Name(), log_id(wire_name)); + log(" importing netbus %s as %s.\n", netbus->Name(), wire_name.unescape()); RTLIL::Wire *wire = module->addWire(wire_name, netbus->Size()); wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex()); @@ -1894,7 +1894,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : new_verific_id(inst)); if (verific_verbose) - log(" importing cell %s (%s) as %s.\n", inst->Name(), inst->View()->Owner()->Name(), log_id(inst_name)); + log(" importing cell %s (%s) as %s.\n", inst->Name(), inst->View()->Owner()->Name(), inst_name.unescape()); if (mode_verific) goto import_verific_cells; @@ -2258,7 +2258,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma for (auto &it : cell_port_conns) { if (verific_verbose) - log(" .%s(%s)\n", log_id(it.first), log_signal(it.second)); + log(" .%s(%s)\n", it.first.unescape(), log_signal(it.second)); cell->setPort(it.first, it.second); } } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 148a6cc63..b394ce074 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -546,7 +546,7 @@ %token TOK_z "'z'" %type range range_or_multirange non_opt_range non_opt_multirange -%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type +%type wire_type expr basic_expr concat_list assignment_pattern_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type %type opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number %type type_name %type opt_enum_init enum_type struct_type enum_struct_type func_return_type typedef_base_type @@ -3349,6 +3349,11 @@ basic_expr: TOK_LCURL concat_list TOK_RCURL { $$ = std::move($2); } | + OP_CAST TOK_LCURL assignment_pattern_list optional_comma TOK_RCURL { + if (!mode->sv) + err_at_loc(@1, "Assignment patterns are only supported in SystemVerilog mode."); + $$ = std::move($3); + } | TOK_LCURL expr TOK_LCURL concat_list TOK_RCURL TOK_RCURL { $$ = std::make_unique(@$, AST_REPLICATE, std::move($2), std::move($4)); } | @@ -3580,6 +3585,16 @@ concat_list: $$->children.push_back(std::move($1)); }; +assignment_pattern_list: + expr { + $$ = std::make_unique(@$, AST_ASSIGN_PATTERN); + $$->children.push_back(std::move($1)); + } | + assignment_pattern_list TOK_COMMA expr { + $$ = std::move($1); + $$->children.push_back(std::move($3)); + }; + integral_number: TOK_CONSTVAL { $$ = std::move($1); } | TOK_UNBASED_UNSIZED_CONSTVAL { $$ = std::move($1); } | diff --git a/guidelines/GettingStarted b/guidelines/GettingStarted index 17fe32523..ea15df93f 100644 --- a/guidelines/GettingStarted +++ b/guidelines/GettingStarted @@ -5,7 +5,7 @@ Getting Started Outline of a Yosys command -------------------------- -Here is a the C++ code for a "hello_world" Yosys command (hello.cc): +Here is the C++ code for a "hello_world" Yosys command (hello.cc): #include "kernel/yosys.h" @@ -85,7 +85,7 @@ the declarations for the following types in kernel/rtlil.h: The module is a container with connected cells and wires in it. The design is a container with modules in it. -All this types are also available without the RTLIL:: prefix in the Yosys +All these types are also available without the RTLIL:: prefix in the Yosys namespace. 4. SigMap and other Helper Classes @@ -204,4 +204,4 @@ Notes on the existing codebase For historical reasons not all parts of Yosys adhere to the current coding style. When adding code to existing parts of the system, adhere to this guide -for the new code instead of trying to mimic the style of the surrounding code. \ No newline at end of file +for the new code instead of trying to mimic the style of the surrounding code. diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 50dee573e..ceff0bd1a 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -103,7 +103,7 @@ struct CellTypes setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}); setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, pool()); setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool()); - setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool()); + setup_type(ID($specrule), {ID::SRC_EN, ID::DST_EN, ID::SRC, ID::DST}, pool()); setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, pool()); setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, pool()); setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y}); diff --git a/kernel/constids.inc b/kernel/constids.inc index c99aa788d..cfd12e3fb 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -459,9 +459,7 @@ X(EDGE_POL) X(EFX_ADD) X(EN) X(ENPOL) -X(EN_DST) X(EN_POLARITY) -X(EN_SRC) X(EQN) X(F) X(FDCE) @@ -835,6 +833,7 @@ X(abcgroup) X(acc_fir) X(acc_fir_i) X(add_carry) +X(aiger2_zbuf) X(allconst) X(allseq) X(always_comb) diff --git a/kernel/cost.cc b/kernel/cost.cc index 4942823d3..230afdeb1 100644 --- a/kernel/cost.cc +++ b/kernel/cost.cc @@ -210,6 +210,6 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) // TODO: $fsm // ignored: $pow $memrd $memwr $meminit (and v2 counterparts) - log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters)); + log_warning("Can't determine cost of %s cell (%d parameters).\n", cell->type.unescape(), GetSize(cell->parameters)); return 1; } diff --git a/kernel/driver.cc b/kernel/driver.cc index d76841909..73b687f80 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -144,19 +144,6 @@ int yosys_history_offset = 0; std::string yosys_history_file; #endif -#if defined(__wasm) -extern "C" { - // FIXME: WASI does not currently support exceptions. - void* __cxa_allocate_exception(size_t thrown_size) throw() { - return malloc(thrown_size); - } - bool __cxa_uncaught_exception() throw(); - void __cxa_throw(void* thrown_exception, struct std::type_info * tinfo, void (*dest)(void*)) { - std::terminate(); - } -} -#endif - void yosys_atexit() { #if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE) @@ -677,6 +664,7 @@ int main(int argc, char **argv) #ifdef _WIN32 log("End of script. Logfile hash: %s\n", hash); + (void)wall_clock_start; #else std::string meminfo; std::string stats_divider = ", "; diff --git a/kernel/drivertools.cc b/kernel/drivertools.cc index 90bfb0ee7..55616dea1 100644 --- a/kernel/drivertools.cc +++ b/kernel/drivertools.cc @@ -866,7 +866,7 @@ DriveSpec DriverMap::operator()(DriveSpec spec) std::string log_signal(DriveChunkWire const &chunk) { - const char *id = log_id(chunk.wire->name); + std::string id = chunk.wire->name.unescape(); if (chunk.is_whole()) return id; if (chunk.width == 1) @@ -877,8 +877,8 @@ std::string log_signal(DriveChunkWire const &chunk) std::string log_signal(DriveChunkPort const &chunk) { - const char *cell_id = log_id(chunk.cell->name); - const char *port_id = log_id(chunk.port); + std::string cell_id = chunk.cell->name.unescape(); + std::string port_id = chunk.port.unescape(); if (chunk.is_whole()) return stringf("%s <%s>", cell_id, port_id); if (chunk.width == 1) diff --git a/kernel/ff.cc b/kernel/ff.cc index 7dd5e24ac..727a9d9cb 100644 --- a/kernel/ff.cc +++ b/kernel/ff.cc @@ -792,7 +792,7 @@ void FfData::flip_bits(const pool &bits) { Wire *new_q = module->addWire(NEW_ID, width); if (has_sr && cell) { - log_warning("Flipping D/Q/init and inserting priority fixup to legalize %s.%s [%s].\n", log_id(module->name), log_id(cell->name), log_id(cell->type)); + log_warning("Flipping D/Q/init and inserting priority fixup to legalize %s.%s [%s].\n", module->name.unescape(), cell->name.unescape(), cell->type.unescape()); } if (is_fine) { diff --git a/kernel/fmt.cc b/kernel/fmt.cc index 200e7e5ce..15179a75a 100644 --- a/kernel/fmt.cc +++ b/kernel/fmt.cc @@ -804,8 +804,10 @@ std::string Fmt::render() const buf += 'X'; else if (has_z) buf += 'Z'; - else - buf += (part.hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[subvalue.as_int()]; + else { + const char *digits = part.hex_upper ? "0123456789ABCDEF" : "0123456789abcdef"; + buf += digits[subvalue.as_int()]; + } } } else if (part.base == 10) { if (part.show_base) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index f0f00181c..8b724e69b 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -45,8 +45,7 @@ FstData::FstData(std::string filename) : ctx(nullptr) ctx = (fstReaderContext *)fstReaderOpen(filename.c_str()); if (!ctx) log_error("Error opening '%s' as FST file\n", filename); - int scale = (int)fstReaderGetTimescale(ctx); - timescale = pow(10.0, scale); + scale = (int)fstReaderGetTimescale(ctx); timescale_str = ""; int unit = 0; int zeros = 0; diff --git a/kernel/fstdata.h b/kernel/fstdata.h index a8ae40301..43f779cb5 100644 --- a/kernel/fstdata.h +++ b/kernel/fstdata.h @@ -55,7 +55,7 @@ class FstData std::string valueOf(fstHandle signal); fstHandle getHandle(std::string name); dict getMemoryHandles(std::string name); - double getTimescale() { return timescale; } + int getScale() { return scale; } const char *getTimescaleString() { return timescale_str.c_str(); } private: void extractVarNames(); @@ -69,7 +69,7 @@ private: uint64_t last_time; std::map past_data; uint64_t past_time; - double timescale; + int scale; // exponent of 10, e.g. -6 = us, -9 = ns std::string timescale_str; uint64_t start_time; uint64_t end_time; diff --git a/kernel/functional.cc b/kernel/functional.cc index 2a1bf598a..4d1423b28 100644 --- a/kernel/functional.cc +++ b/kernel/functional.cc @@ -572,7 +572,7 @@ private: const auto &wr = mem->wr_ports[i]; if (wr.clk_enable) log_error("Write port %zd of memory %s.%s is clocked. This is not supported by the functional backend. " - "Call async2sync or clk2fflogic to avoid this error.\n", i, log_id(mem->module), log_id(mem->memid)); + "Call async2sync or clk2fflogic to avoid this error.\n", i, mem->module, mem->memid.unescape()); Node en = enqueue(driver_map(DriveSpec(wr.en))); Node addr = enqueue(driver_map(DriveSpec(wr.addr))); Node new_data = enqueue(driver_map(DriveSpec(wr.data))); @@ -582,12 +582,12 @@ private: } if (mem->rd_ports.empty()) log_error("Memory %s.%s has no read ports. This is not supported by the functional backend. " - "Call opt_clean to remove it.", log_id(mem->module), log_id(mem->memid)); + "Call opt_clean to remove it.", mem->module, mem->memid.unescape()); for (size_t i = 0; i < mem->rd_ports.size(); i++) { const auto &rd = mem->rd_ports[i]; if (rd.clk_enable) log_error("Read port %zd of memory %s.%s is clocked. This is not supported by the functional backend. " - "Call memory_nordff to avoid this error.\n", i, log_id(mem->module), log_id(mem->memid)); + "Call memory_nordff to avoid this error.\n", i, mem->module, mem->memid.unescape()); Node addr = enqueue(driver_map(DriveSpec(rd.addr))); read_results.push_back(factory.memory_read(node, addr)); } @@ -609,7 +609,7 @@ private: FfData ff(&ff_initvals, cell); if (!ff.has_gclk) log_error("The design contains a %s flip-flop at %s. This is not supported by the functional backend. " - "Call async2sync or clk2fflogic to avoid this error.\n", log_id(cell->type), log_id(cell)); + "Call async2sync or clk2fflogic to avoid this error.\n", cell->type.unescape(), cell); auto &state = factory.add_state(ff.name, ID($state), Sort(ff.width)); Node q_value = factory.value(state); factory.suggest_name(q_value, ff.name); diff --git a/kernel/hashlib.h b/kernel/hashlib.h index b43a68abf..937116178 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -55,6 +55,12 @@ namespace hashlib { * instead of pointers. */ +#if defined(__GNUC__) || defined(__clang__) +# define HASHLIB_ATTRIBUTE_WARN_UNUSED __attribute__((warn_unused)) +#else +# define HASHLIB_ATTRIBUTE_WARN_UNUSED +#endif + const int hashtable_size_trigger = 2; const int hashtable_size_factor = 3; @@ -402,7 +408,7 @@ private: }; template -class dict { +class HASHLIB_ATTRIBUTE_WARN_UNUSED dict { struct entry_t { std::pair udata; @@ -877,7 +883,7 @@ public: }; template -class pool +class HASHLIB_ATTRIBUTE_WARN_UNUSED pool { template friend class idict; @@ -1257,7 +1263,7 @@ public: }; template -class idict +class HASHLIB_ATTRIBUTE_WARN_UNUSED idict { pool database; @@ -1360,7 +1366,7 @@ public: * i-prefixed methods operate on indices in parents */ template -class mfp +class HASHLIB_ATTRIBUTE_WARN_UNUSED mfp { idict database; class AtomicParent { diff --git a/kernel/io.h b/kernel/io.h index 171f47a80..e15194e79 100644 --- a/kernel/io.h +++ b/kernel/io.h @@ -197,6 +197,28 @@ check_format(std::string_view fmt, int fmt_start, bool *has_escapes, FoundFormat ensure_no_format_spec(fmt, fmt_start, has_escapes); } +template +static auto has_name_member_imp(int) + -> decltype(static_cast(std::declval().name), std::true_type{}); + +template +static auto has_name_member_imp(long) + -> std::false_type; + +template +struct has_name_member : decltype(has_name_member_imp(0)){}; + +template +static auto ptr_has_name_member_imp(int) + -> decltype(static_cast(std::declval()->name), std::true_type{}); + +template +static auto ptr_has_name_member_imp(long) + -> std::false_type; + +template +struct ptr_has_name_member : decltype(ptr_has_name_member_imp(0)){}; + // Check that the format string `fmt.substr(fmt_start)` is valid for the given type arguments. // Fills `specs` with the FoundFormatSpecs found in the format string. // `int_args_consumed` is the number of int arguments already consumed to satisfy the @@ -245,7 +267,9 @@ constexpr void check_format(std::string_view fmt, int fmt_start, bool *has_escap if constexpr (!std::is_convertible_v && !std::is_convertible_v && !std::is_convertible_v && - !std::is_convertible_v) { + !std::is_convertible_v && + !has_name_member() && + !ptr_has_name_member()) { YOSYS_ABORT("Expected type convertible to char *"); } *specs = found; @@ -343,6 +367,16 @@ inline void format_emit_one(std::string &result, std::string_view fmt, const Fou format_emit_idstring(result, spec, dynamic_ints, num_dynamic_ints, s); return; } + if constexpr (has_name_member()) { + const std::string &s = arg.name.unescape(); + format_emit_string(result, spec, dynamic_ints, num_dynamic_ints, s); + return; + } + if constexpr (ptr_has_name_member()) { + const std::string &s = arg->name.unescape(); + format_emit_string(result, spec, dynamic_ints, num_dynamic_ints, s); + return; + } break; case CONVSPEC_VOID_PTR: if constexpr (std::is_convertible_v) { @@ -441,7 +475,8 @@ public: private: std::string_view fmt; bool has_escapes = false; - FoundFormatSpec specs[sizeof...(Args)] = {}; + // Making array at least size of one to make MSVC happy and strict to standards + FoundFormatSpec specs[sizeof...(Args) ? sizeof...(Args) : 1] = {}; }; template struct WrapType { using type = T; }; diff --git a/kernel/log.cc b/kernel/log.cc index b114f1eaf..fd3f75502 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -586,7 +586,7 @@ void log_flush() } void log_dump_val_worker(RTLIL::IdString v) { - log("%s", log_id(v)); + log("%s", v.unescape()); } void log_dump_val_worker(RTLIL::SigSpec v) { diff --git a/kernel/mem.cc b/kernel/mem.cc index 02d12dea4..2f7f16c7a 100644 --- a/kernel/mem.cc +++ b/kernel/mem.cc @@ -663,15 +663,15 @@ namespace { auto addr = cell->getPort(ID::ADDR); auto data = cell->getPort(ID::DATA); if (!addr.is_fully_const()) - log_error("Non-constant address %s in memory initialization %s.\n", log_signal(addr), log_id(cell)); + log_error("Non-constant address %s in memory initialization %s.\n", log_signal(addr), cell); if (!data.is_fully_const()) - log_error("Non-constant data %s in memory initialization %s.\n", log_signal(data), log_id(cell)); + log_error("Non-constant data %s in memory initialization %s.\n", log_signal(data), cell); init.addr = addr.as_const(); init.data = data.as_const(); if (cell->type == ID($meminit_v2)) { auto en = cell->getPort(ID::EN); if (!en.is_fully_const()) - log_error("Non-constant enable %s in memory initialization %s.\n", log_signal(en), log_id(cell)); + log_error("Non-constant enable %s in memory initialization %s.\n", log_signal(en), cell); init.en = en.as_const(); } else { init.en = RTLIL::Const(State::S1, mem->width); @@ -1022,7 +1022,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) { if (c) log("Extracted %s FF from read port %d of %s.%s: %s\n", trans_use_addr ? "addr" : "data", - idx, log_id(module), log_id(memid), log_id(c)); + idx, module, memid.unescape(), c); port.en = State::S1; port.clk = State::S0; diff --git a/kernel/modtools.h b/kernel/modtools.h index 285f22b2a..bdcb0f108 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -320,8 +320,8 @@ struct ModIndex : public RTLIL::Monitor if (it.second.is_output) log(" PRIMARY OUTPUT\n"); for (auto &port : it.second.ports) - log(" PORT: %s.%s[%d] (%s)\n", log_id(port.cell), - log_id(port.port), port.offset, log_id(port.cell->type)); + log(" PORT: %s.%s[%d] (%s)\n", port.cell, + port.port.unescape(), port.offset, port.cell->type.unescape()); } } }; diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index bb14293a3..eb42019af 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -80,7 +80,7 @@ struct CellTableBuilder { setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}, features); setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, {}, features); setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, {}, features); - setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, {}, features); + setup_type(ID($specrule), {ID::SRC_EN, ID::DST_EN, ID::SRC, ID::DST}, {}, features); setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, {}, features); setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, {}, features); setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y}, features); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 2badd20c3..020a4ec0c 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1226,7 +1226,7 @@ void RTLIL::Design::add(RTLIL::Module *module) mon->notify_module_add(module); if (yosys_xtrace) { - log("#X# New Module: %s\n", log_id(module)); + log("#X# New Module: %s\n", module); log_backtrace("-X- ", yosys_xtrace-1); } } @@ -1252,7 +1252,7 @@ RTLIL::Module *RTLIL::Design::addModule(RTLIL::IdString name) mon->notify_module_add(module); if (yosys_xtrace) { - log("#X# New Module: %s\n", log_id(module)); + log("#X# New Module: %s\n", module); log_backtrace("-X- ", yosys_xtrace-1); } @@ -1330,7 +1330,7 @@ void RTLIL::Design::remove(RTLIL::Module *module) mon->notify_module_del(module); if (yosys_xtrace) { - log("#X# Remove Module: %s\n", log_id(module)); + log("#X# Remove Module: %s\n", module); log_backtrace("-X- ", yosys_xtrace-1); } @@ -1472,22 +1472,22 @@ std::vector RTLIL::Design::selected_modules(RTLIL::SelectPartial switch (boxes) { case RTLIL::SB_UNBOXED_WARN: - log_warning("Ignoring boxed module %s.\n", log_id(it.first)); + log_warning("Ignoring boxed module %s.\n", it.first.unescape()); break; case RTLIL::SB_EXCL_BB_WARN: - log_warning("Ignoring blackbox module %s.\n", log_id(it.first)); + log_warning("Ignoring blackbox module %s.\n", it.first.unescape()); break; case RTLIL::SB_UNBOXED_ERR: - log_error("Unsupported boxed module %s.\n", log_id(it.first)); + log_error("Unsupported boxed module %s.\n", it.first.unescape()); break; case RTLIL::SB_EXCL_BB_ERR: - log_error("Unsupported blackbox module %s.\n", log_id(it.first)); + log_error("Unsupported blackbox module %s.\n", it.first.unescape()); break; case RTLIL::SB_UNBOXED_CMDERR: - log_cmd_error("Unsupported boxed module %s.\n", log_id(it.first)); + log_cmd_error("Unsupported boxed module %s.\n", it.first.unescape()); break; case RTLIL::SB_EXCL_BB_CMDERR: - log_cmd_error("Unsupported blackbox module %s.\n", log_id(it.first)); + log_cmd_error("Unsupported blackbox module %s.\n", it.first.unescape()); break; default: break; @@ -1496,13 +1496,13 @@ std::vector RTLIL::Design::selected_modules(RTLIL::SelectPartial switch(partials) { case RTLIL::SELECT_WHOLE_WARN: - log_warning("Ignoring partially selected module %s.\n", log_id(it.first)); + log_warning("Ignoring partially selected module %s.\n", it.first.unescape()); break; case RTLIL::SELECT_WHOLE_ERR: - log_error("Unsupported partially selected module %s.\n", log_id(it.first)); + log_error("Unsupported partially selected module %s.\n", it.first.unescape()); break; case RTLIL::SELECT_WHOLE_CMDERR: - log_cmd_error("Unsupported partially selected module %s.\n", log_id(it.first)); + log_cmd_error("Unsupported partially selected module %s.\n", it.first.unescape()); break; default: break; @@ -2796,14 +2796,14 @@ bool RTLIL::Module::has_processes() const bool RTLIL::Module::has_memories_warn() const { if (!memories.empty()) - log_warning("Ignoring module %s because it contains memories (run 'memory' command first).\n", log_id(this)); + log_warning("Ignoring module %s because it contains memories (run 'memory' command first).\n", this); return !memories.empty(); } bool RTLIL::Module::has_processes_warn() const { if (!processes.empty()) - log_warning("Ignoring module %s because it contains processes (run 'proc' command first).\n", log_id(this)); + log_warning("Ignoring module %s because it contains processes (run 'proc' command first).\n", this); return !processes.empty(); } @@ -3095,7 +3095,7 @@ void RTLIL::Module::connect(const RTLIL::SigSig &conn) } if (yosys_xtrace) { - log("#X# Connect (SigSig) in %s: %s = %s (%d bits)\n", log_id(this), log_signal(conn.first), log_signal(conn.second), GetSize(conn.first)); + log("#X# Connect (SigSig) in %s: %s = %s (%d bits)\n", this, log_signal(conn.first), log_signal(conn.second), GetSize(conn.first)); log_backtrace("-X- ", yosys_xtrace-1); } @@ -3118,7 +3118,7 @@ void RTLIL::Module::new_connections(const std::vector &new_conn) mon->notify_connect(this, new_conn); if (yosys_xtrace) { - log("#X# New connections vector in %s:\n", log_id(this)); + log("#X# New connections vector in %s:\n", this); for (auto &conn: new_conn) log("#X# %s = %s (%d bits)\n", log_signal(conn.first), log_signal(conn.second), GetSize(conn.first)); log_backtrace("-X- ", yosys_xtrace-1); @@ -5272,26 +5272,32 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const log_assert(length >= 0); log_assert(offset + length <= size()); - SigSpec extracted; - Chunks cs = chunks(); - auto it = cs.begin(); - for (; offset; offset -= it->width, ++it) { - if (offset < it->width) { - int chunk_length = min(it->width - offset, length); - extracted.append(it->extract(offset, chunk_length)); - length -= chunk_length; - ++it; - break; - } - } - for (; length; length -= it->width, ++it) { - if (length >= it->width) { - extracted.append(*it); + std::vector extracted; + SigBit first; + bool is_packing = true; + for (int i = offset; i < offset + length; i++) { + bool was_packing_before = is_packing; + SigBit bit = (*this)[i]; + if (i == offset) { + first = bit; + if (!bit.wire) + is_packing = false; } else { - extracted.append(it->extract(0, length)); - break; + if (bit.wire != first.wire) + is_packing = false; + if (bit.wire) + if (bit.offset != first.offset + (i - offset)) + is_packing = false; } + if (was_packing_before && !is_packing) + for (int j = offset; j < i; j++) + extracted.push_back((*this)[j]); + if (!is_packing) + extracted.push_back((*this)[i]); } + if (is_packing) + return SigChunk(first.wire, first.offset, length); + return extracted; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index b9d86b91c..b32f9ea76 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1400,6 +1400,8 @@ struct RTLIL::SigSpecConstIterator struct RTLIL::SigSpec { private: + friend class SigSpecRepTest; + FRIEND_TEST(SigSpecRepTest, Extract); enum Representation : char { CHUNK, BITS, diff --git a/kernel/rtlil_bufnorm.cc b/kernel/rtlil_bufnorm.cc index 5f74b3380..19474b565 100644 --- a/kernel/rtlil_bufnorm.cc +++ b/kernel/rtlil_bufnorm.cc @@ -146,7 +146,7 @@ void RTLIL::Module::bufNormalize() // already enqueued or becomes reachable when denormalizing $buf or // $connect cells. auto enqueue_cell_port = [&](Cell *cell, IdString port) { - xlog("processing cell port %s.%s\n", log_id(cell), log_id(port)); + xlog("processing cell port %s.%s\n", cell, port.unescape()); // An empty cell type means the cell got removed if (cell->type.empty()) @@ -270,7 +270,7 @@ void RTLIL::Module::bufNormalize() // normalized mode). while (wire_queue_pos < GetSize(wire_queue_entries)) { auto wire = wire_queue_entries[wire_queue_pos++]; - xlog("processing wire %s\n", log_id(wire)); + xlog("processing wire %s\n", wire); if (wire->driverCell_) { Cell *cell = wire->driverCell_; @@ -287,7 +287,7 @@ void RTLIL::Module::bufNormalize() log_assert(connect_cell->type == ID($connect)); SigSpec const &sig_a = connect_cell->getPort(ID::A); SigSpec const &sig_b = connect_cell->getPort(ID::B); - xlog("found $connect cell %s: %s <-> %s\n", log_id(connect_cell), log_signal(sig_a), log_signal(sig_b)); + xlog("found $connect cell %s: %s <-> %s\n", connect_cell, log_signal(sig_a), log_signal(sig_b)); for (auto &side : {sig_a, sig_b}) for (auto chunk : side.chunks()) if (chunk.wire) @@ -452,7 +452,7 @@ void RTLIL::Module::bufNormalize() } if (wire->driverCell_ == nullptr) { - xlog("wire %s drivers %s\n", log_id(wire), log_signal(wire_drivers)); + xlog("wire %s drivers %s\n", wire, log_signal(wire_drivers)); addBuf(NEW_ID, wire_drivers, wire); } } @@ -541,7 +541,7 @@ void RTLIL::Cell::unsetPort(RTLIL::IdString portname) mon->notify_connect(this, conn_it->first, conn_it->second, signal); if (yosys_xtrace) { - log("#X# Unconnect %s.%s.%s\n", log_id(this->module), log_id(this), log_id(portname)); + log("#X# Unconnect %s.%s.%s\n", this->module, this, portname.unescape()); log_backtrace("-X- ", yosys_xtrace-1); } @@ -601,7 +601,7 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) mon->notify_connect(this, conn_it->first, conn_it->second, signal); if (yosys_xtrace) { - log("#X# Connect %s.%s.%s = %s (%d)\n", log_id(this->module), log_id(this), log_id(portname), log_signal(signal), GetSize(signal)); + log("#X# Connect %s.%s.%s = %s (%d)\n", this->module, this, portname.unescape(), log_signal(signal), GetSize(signal)); log_backtrace("-X- ", yosys_xtrace-1); } diff --git a/kernel/satgen.cc b/kernel/satgen.cc index 7fbcba1b2..9fddc303e 100644 --- a/kernel/satgen.cc +++ b/kernel/satgen.cc @@ -1395,9 +1395,9 @@ void report_missing_model(bool warn_only, RTLIL::Cell* cell) { std::string s; if (cell->is_builtin_ff()) - s = stringf("No SAT model available for async FF cell %s (%s). Consider running `async2sync` or `clk2fflogic` first.\n", log_id(cell), log_id(cell->type)); + s = stringf("No SAT model available for async FF cell %s (%s). Consider running `async2sync` or `clk2fflogic` first.\n", cell, cell->type.unescape()); else - s = stringf("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type)); + s = stringf("No SAT model available for cell %s (%s).\n", cell, cell->type.unescape()); if (warn_only) { log_formatted_warning_noprefix(s); diff --git a/kernel/scopeinfo.h b/kernel/scopeinfo.h index a3939b903..e06beb1dc 100644 --- a/kernel/scopeinfo.h +++ b/kernel/scopeinfo.h @@ -328,7 +328,7 @@ struct ModuleItem { [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(ptr); return h; } }; -static inline void log_dump_val_worker(typename IdTree::Cursor cursor ) { log("%p %s", cursor.target, log_id(cursor.scope_name)); } +static inline void log_dump_val_worker(typename IdTree::Cursor cursor ) { log("%p %s", cursor.target, cursor.scope_name.unescape()); } template static inline void log_dump_val_worker(const typename std::unique_ptr &cursor ) { log("unique %p", cursor.get()); } diff --git a/kernel/threading.cc b/kernel/threading.cc index 817a48df0..eda6bb4cb 100644 --- a/kernel/threading.cc +++ b/kernel/threading.cc @@ -45,9 +45,12 @@ int ThreadPool::pool_size(int reserved_cores, int max_worker_threads) #ifdef YOSYS_ENABLE_THREADS int available_threads = std::min(std::thread::hardware_concurrency(), get_max_threads()); int num_threads = std::min(available_threads - reserved_cores, max_worker_threads); - return std::max(0, num_threads); + return std::max(0, num_threads); #else - return 0; + (void)reserved_cores; + (void)max_worker_threads; + (void)get_max_threads(); + return 0; #endif } @@ -146,6 +149,8 @@ void ParallelDispatchThreadPool::run_worker(int thread_num) signal_worker_done(); } signal_worker_done(); +#else + (void)current_work; #endif } diff --git a/kernel/threading.h b/kernel/threading.h index 1aded4931..3a31b0633 100644 --- a/kernel/threading.h +++ b/kernel/threading.h @@ -570,7 +570,7 @@ public: // Call this for each shard to implement parallel destruction. For very large `ShardedHashtable`s, // deleting all elements of all shards on a single thread can be a performance bottleneck. void clear(const ThreadIndex &shard) { - AccumulatedValueEquality equality = shards[0].key_eq(); + AccumulatedValueEquality equality = shards[shard.thread_num].key_eq(); shards[shard.thread_num] = Shard(0, AccumulatedValueHashOp(), equality); } private: diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h index ff60415bd..e2e094b62 100644 --- a/kernel/timinginfo.h +++ b/kernel/timinginfo.h @@ -105,21 +105,21 @@ struct TimingInfo auto dst = cell->getPort(ID::DST); for (const auto &c : src.chunks()) if (!c.wire || !c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", module, cell, log_signal(src)); for (const auto &c : dst.chunks()) if (!c.wire || !c.wire->port_output) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", module, cell, log_signal(dst)); int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); int max = std::max(rise_max,fall_max); if (max < 0) - log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell)); + log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", module, cell); if (cell->getParam(ID::FULL).as_bool()) { for (const auto &s : src) for (const auto &d : dst) { auto r = t.comb.insert(BitBit(s,d)); if (!r.second) - log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); + log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", module, log_signal(s), log_signal(d)); r.first->second = max; } } @@ -130,7 +130,7 @@ struct TimingInfo const auto &d = dst[i]; auto r = t.comb.insert(BitBit(s,d)); if (!r.second) - log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); + log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", module, log_signal(s), log_signal(d)); r.first->second = max; } } @@ -139,15 +139,15 @@ struct TimingInfo auto src = cell->getPort(ID::SRC).as_bit(); auto dst = cell->getPort(ID::DST); if (!src.wire || !src.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", module, cell, log_signal(src)); for (const auto &c : dst.chunks()) if (!c.wire->port_output) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", module, cell, log_signal(dst)); int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); int max = std::max(rise_max,fall_max); if (max < 0) { - log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", module, cell); max = 0; } for (const auto &d : dst) { @@ -167,12 +167,12 @@ struct TimingInfo auto dst = cell->getPort(ID::DST).as_bit(); for (const auto &c : src.chunks()) if (!c.wire || !c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", module, cell, log_signal(src)); if (!dst.wire || !dst.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", module, cell, log_signal(dst)); int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); if (max < 0) { - log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", module, cell); max = 0; } for (const auto &s : src) { diff --git a/kernel/wallace_tree.h b/kernel/wallace_tree.h new file mode 100644 index 000000000..eb3513803 --- /dev/null +++ b/kernel/wallace_tree.h @@ -0,0 +1,112 @@ +/** + * Wallace tree utilities for multi-operand addition using carry-save adders + * + * Terminology: + * - compressor: $fa viewed as reducing 3 inputs to 2 outputs (sum + shifted carry) (3:2 compressor) + * - level: A stage of parallel compression operations + * - depth: Maximum number of 3:2 compressor levels from any input to a signal + * + * References: + * - "Binary Adder Architectures for Cell-Based VLSI and their Synthesis" (https://iis-people.ee.ethz.ch/~zimmi/publications/adder_arch.pdf) + * - "A Suggestion for a Fast Multiplier" (https://www.ece.ucdavis.edu/~vojin/CLASSES/EEC280/Web-page/papers/Arithmetic/Wallace_mult.pdf) + */ + +#ifndef WALLACE_TREE_H +#define WALLACE_TREE_H + +#include "kernel/sigtools.h" +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +inline std::pair emit_fa(Module *module, SigSpec a, SigSpec b, SigSpec c, int width) +{ + SigSpec sum = module->addWire(NEW_ID, width); + SigSpec cout = module->addWire(NEW_ID, width); + + module->addFa(NEW_ID, a, b, c, cout, sum); + + SigSpec carry; + carry.append(State::S0); + carry.append(cout.extract(0, width - 1)); + return {sum, carry}; +} + +/** + * wallace_reduce_scheduled() - Reduce multiple operands to two using a Wallace tree + * @module: The Yosys module to which the compressors will be added + * @sigs: Vector of input signals (operands) to be reduced + * @width: Target bit-width to which all operands will be zero-extended + * @compressor_count: Optional pointer to return the number of $fa cells emitted + * + * Return: The final two reduced operands, that are to be fed into an adder + */ +inline std::pair wallace_reduce_scheduled(Module *module, std::vector &sigs, int width, int *compressor_count = nullptr) +{ + struct DepthSig { + SigSpec sig; + int depth; + }; + + for (auto &s : sigs) + s.extend_u0(width); + + std::vector operands; + operands.reserve(sigs.size()); + for (auto &s : sigs) + operands.push_back({s, 0}); + + // Number of $fa's emitted + if (compressor_count) + *compressor_count = 0; + + // Only compress operands ready at current level + for (int level = 0; operands.size() > 2; level++) { + // Partition operands into ready and waiting + std::vector ready, waiting; + for (auto &op : operands) { + if (op.depth <= level) + ready.push_back(op); + else + waiting.push_back(op); + } + + if (ready.size() < 3) + continue; + + // Apply compressors to ready operands + std::vector compressed; + size_t i = 0; + while (i + 2 < ready.size()) { + auto [sum, carry] = emit_fa(module, ready[i].sig, ready[i + 1].sig, ready[i + 2].sig, width); + int new_depth = std::max({ready[i].depth, ready[i + 1].depth, ready[i + 2].depth}) + 1; + compressed.push_back({sum, new_depth}); + compressed.push_back({carry, new_depth}); + if (compressor_count) + (*compressor_count)++; + i += 3; + } + // Uncompressed operands pass through to next level + for (; i < ready.size(); i++) + compressed.push_back(ready[i]); + // Merge compressed with waiting operands + for (auto &op : waiting) + compressed.push_back(op); + + operands = std::move(compressed); + } + + if (operands.size() == 0) + return {SigSpec(State::S0, width), SigSpec(State::S0, width)}; + else if (operands.size() == 1) + return {operands[0].sig, SigSpec(State::S0, width)}; + else { + log_assert(operands.size() == 2); + log(" Wallace tree depth: %d levels of $fa + 1 final $add\n", std::max(operands[0].depth, operands[1].depth)); + return {operands[0].sig, operands[1].sig}; + } +} + +YOSYS_NAMESPACE_END + +#endif diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 29fcd48d8..5643ed7b0 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -471,17 +471,30 @@ struct TclPass : public Pass { #endif -#if defined(__linux__) || defined(__CYGWIN__) +#if defined(__linux__) || defined(__CYGWIN__) || defined(__gnu_hurd__) std::string proc_self_dirname() { - char path[PATH_MAX]; - ssize_t buflen = readlink("/proc/self/exe", path, sizeof(path)); + std::string path(4096, '\0'); + ssize_t buflen = -1; + // Double until sucess, while avoiding endless loop. Give up + // when symlink is longer than 4096*(2^30) = 4398046511104 + // bytes. + for (int tries = 30; 0 < tries; tries--) { + buflen = readlink("/proc/self/exe", path.data(), path.size()); + if (buflen < (ssize_t)path.size()) + break; + else + path.resize(path.size() * 2); + } if (buflen < 0) { log_error("readlink(\"/proc/self/exe\") failed: %s\n", strerror(errno)); + path.resize(0); + } else { + while (buflen > 0 && path[buflen-1] != '/') + buflen--; + path.resize(buflen); } - while (buflen > 0 && path[buflen-1] != '/') - buflen--; - return std::string(path, buflen); + return path; } #elif defined(__FreeBSD__) || defined(__NetBSD__) std::string proc_self_dirname() @@ -941,7 +954,7 @@ static char *readline_obj_generator(const char *text, int state) { for (auto mod : design->modules()) if (RTLIL::unescape_id(mod->name).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(mod->name))); + obj_names.push_back(strdup(mod->name.unescape().c_str())); } else if (design->module(design->selected_active_module) != nullptr) { @@ -949,19 +962,19 @@ static char *readline_obj_generator(const char *text, int state) for (auto w : module->wires()) if (RTLIL::unescape_id(w->name).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(w->name))); + obj_names.push_back(strdup(w->name.unescape().c_str())); for (auto &it : module->memories) if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(it.first))); + obj_names.push_back(strdup(it.first.unescape().c_str())); for (auto cell : module->cells()) if (RTLIL::unescape_id(cell->name).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(cell->name))); + obj_names.push_back(strdup(cell->name.unescape().c_str())); for (auto &it : module->processes) if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(it.first))); + obj_names.push_back(strdup(it.first.unescape().c_str())); } std::sort(obj_names.begin(), obj_names.end()); @@ -1166,7 +1179,7 @@ struct ScriptCmdPass : public Pass { if (!mod->selected(w)) continue; if (!c.second.is_fully_const()) - log_error("RHS of selected wire %s.%s is not constant.\n", log_id(mod), log_id(w)); + log_error("RHS of selected wire %s.%s is not constant.\n", mod, w); auto v = c.second.as_const(); Pass::call_on_module(design, mod, v.decode_string()); } diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index 47dae5473..062036dba 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -120,10 +120,10 @@ # define YS_MAYBE_UNUSED #endif -#if __cplusplus >= 201703L +#if __cplusplus >= 202002L # define YS_FALLTHROUGH [[fallthrough]]; #else -# error "C++17 or later compatible compiler is required" +# error "C++20 or later compatible compiler is required" #endif #if defined(__has_cpp_attribute) && __has_cpp_attribute(gnu::cold) diff --git a/misc/create_vcxsrc.sh b/misc/create_vcxsrc.sh index 42a690ce6..dccc31fac 100644 --- a/misc/create_vcxsrc.sh +++ b/misc/create_vcxsrc.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex vcxsrc="$1" @@ -25,6 +25,7 @@ if [ -f "/usr/include/FlexLexer.h" ] ; then cp /usr/include/FlexLexer.h libs/flex/FlexLexer.h ls libs/flex/*.h >> ../../srcfiles.txt fi +sed -i '\#libs/../kernel/yosys.h#d' ../../srcfiles.txt popd { @@ -35,7 +36,7 @@ popd tail -n +$((n+1)) "$vcxsrc"/YosysVS/YosysVS.vcxproj } > "$vcxsrc"/YosysVS/YosysVS.vcxproj.new -sed -i 's,,\n stdcpp17\n /Zc:__cplusplus %(AdditionalOptions),g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new +sed -i 's,,\n stdcpp20\n /Zc:__cplusplus %(AdditionalOptions),g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new sed -i 's,,YOSYS_ENABLE_THREADS;,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new if [ -f "/usr/include/FlexLexer.h" ] ; then sed -i 's,,;..\\yosys\\libs\\flex,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new diff --git a/passes/cmds/abstract.cc b/passes/cmds/abstract.cc index 2ea71268b..2519daf5c 100644 --- a/passes/cmds/abstract.cc +++ b/passes/cmds/abstract.cc @@ -67,7 +67,7 @@ struct Slice { int wire_offset(RTLIL::Wire *wire, int index) const { int rtl_offset = indices == RtlilSlice ? index : wire->from_hdl_index(index); if (rtl_offset < 0 || rtl_offset >= wire->width) { - log_error("Slice %s is out of bounds for wire %s in module %s", to_string(), log_id(wire), log_id(wire->module)); + log_error("Slice %s is out of bounds for wire %s in module %s", to_string(), wire, wire->module); } return rtl_offset; } @@ -187,7 +187,7 @@ unsigned int abstract_state(Module* mod, EnableLogic enable, const std::vector& wire_score) for (auto bit : conn.second) if (bit.wire != nullptr && bit.wire->name[0] != '$') { if (suffix.empty()) - suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first)); + suffix = stringf("_%s_%s", cell->type.unescape(), conn.first.unescape()); name_proposal proposed_name( bit.wire->name.str() + suffix, cell->output(conn.first) ? 0 : wire_score.at(bit.wire) @@ -66,7 +66,7 @@ int autoname_worker(Module *module, const dict& wire_score) for (auto bit : conn.second) if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) { if (suffix.empty()) - suffix = stringf("_%s", log_id(conn.first)); + suffix = stringf("_%s", conn.first.unescape()); name_proposal proposed_name( cell->name.str() + suffix, cell->output(conn.first) ? 0 : wire_score.at(bit.wire) @@ -90,7 +90,7 @@ int autoname_worker(Module *module, const dict& wire_score) if (best_name < it.second) continue; IdString n = module->uniquify(IdString(it.second.name)); - log_debug("Rename cell %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); + log_debug("Rename cell %s in %s to %s.\n", it.first, module, n.unescape()); module->rename(it.first, n); count++; } @@ -99,7 +99,7 @@ int autoname_worker(Module *module, const dict& wire_score) if (best_name < it.second) continue; IdString n = module->uniquify(IdString(it.second.name)); - log_debug("Rename wire %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); + log_debug("Rename wire %s in %s to %s.\n", it.first, module, n.unescape()); module->rename(it.first, n); count++; } @@ -151,7 +151,7 @@ struct AutonamePass : public Pass { count += n; } if (count > 0) - log("Renamed %d objects in module %s (%d iterations).\n", count, log_id(module), iter); + log("Renamed %d objects in module %s (%d iterations).\n", count, module, iter); } } } AutonamePass; diff --git a/passes/cmds/box_derive.cc b/passes/cmds/box_derive.cc index 2590baa93..2d5ee2440 100644 --- a/passes/cmds/box_derive.cc +++ b/passes/cmds/box_derive.cc @@ -79,7 +79,7 @@ struct BoxDerivePass : Pass { if (!base_name.empty()) { base_override = d->module(base_name); if (!base_override) - log_cmd_error("Base module %s not found.\n", log_id(base_name)); + log_cmd_error("Base module %s not found.\n", base_name.unescape()); } dict>, Module*> done; @@ -109,7 +109,7 @@ struct BoxDerivePass : Pass { IdString new_name = RTLIL::escape_id(derived->get_string_attribute(naming_attr)); if (!new_name.isPublic()) log_error("Derived module %s cannot be renamed to private name %s.\n", - log_id(derived), log_id(new_name)); + derived, new_name.unescape()); derived->attributes.erase(naming_attr); d->rename(derived, new_name); } diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index 0ced09dd9..6a630ca4b 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -212,7 +212,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove module %s.\n", log_id(module)); + log_header(design, "Trying to remove module %s.\n", module); removed_module = module; break; } @@ -242,7 +242,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove module port %s.\n", log_id(wire)); + log_header(design, "Trying to remove module port %s.\n", wire); wire->port_input = wire->port_output = false; mod->fixup_ports(); return design_copy; @@ -265,7 +265,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove cell %s.%s.\n", log_id(mod), log_id(cell)); + log_header(design, "Trying to remove cell %s.%s.\n", mod, cell); removed_cell = cell; break; } @@ -296,7 +296,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove cell port %s.%s.%s.\n", log_id(mod), log_id(cell), log_id(it.first)); + log_header(design, "Trying to remove cell port %s.%s.%s.\n", mod, cell, it.first.unescape()); RTLIL::SigSpec port_x(State::Sx, port.size()); cell->unsetPort(it.first); cell->setPort(it.first, port_x); @@ -305,7 +305,7 @@ struct BugpointPass : public Pass { if (!stage2 && (cell->input(it.first) || cell->output(it.first)) && index++ == seed) { - log_header(design, "Trying to expose cell port %s.%s.%s as module port.\n", log_id(mod), log_id(cell), log_id(it.first)); + log_header(design, "Trying to expose cell port %s.%s.%s as module port.\n", mod, cell, it.first.unescape()); RTLIL::Wire *wire = mod->addWire(NEW_ID, port.size()); wire->set_bool_attribute(ID($bugpoint)); wire->port_input = cell->input(it.first); @@ -334,7 +334,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove process %s.%s.\n", log_id(mod), log_id(process.first)); + log_header(design, "Trying to remove process %s.%s.\n", mod, process.first.unescape()); removed_process = process.second; break; } @@ -363,7 +363,7 @@ struct BugpointPass : public Pass { { if (index++ == seed) { - log_header(design, "Trying to remove assign %s %s in %s.%s.\n", log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first)); + log_header(design, "Trying to remove assign %s %s in %s.%s.\n", log_signal(it->first), log_signal(it->second), mod, pr.first.unescape()); cs->actions.erase(it); return design_copy; } @@ -389,7 +389,7 @@ struct BugpointPass : public Pass { { if (index++ == seed) { - log_header(design, "Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first)); + log_header(design, "Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal(it->first), log_signal(it->second), mod, pr.first.unescape()); sy->actions.erase(it); return design_copy; } @@ -399,7 +399,7 @@ struct BugpointPass : public Pass { { if (index++ == seed) { - log_header(design, "Trying to remove sync %s memwr %s %s %s %s in %s.%s.\n", log_signal(sy->signal), log_id(it->memid), log_signal(it->address), log_signal(it->data), log_signal(it->enable), log_id(mod), log_id(pr.first)); + log_header(design, "Trying to remove sync %s memwr %s %s %s %s in %s.%s.\n", log_signal(sy->signal), it->memid.unescape(), log_signal(it->address), log_signal(it->data), log_signal(it->enable), mod, pr.first.unescape()); sy->mem_write_actions.erase(it); // Remove the bit for removed action from other actions' priority masks. for (auto it2 = sy->mem_write_actions.begin(); it2 != sy->mem_write_actions.end(); ++it2) { @@ -437,7 +437,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove wire %s.%s.\n", log_id(mod), log_id(wire)); + log_header(design, "Trying to remove wire %s.%s.\n", mod, wire); removed_wire = wire; break; } diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index 1019c2955..6e0d65297 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -117,7 +117,7 @@ struct CheckPass : public Pass { for (auto module : design->selected_whole_modules_warn()) { - log("Checking module %s...\n", log_id(module)); + log("Checking module %s...\n", module); SigMap sigmap(module); dict> wire_drivers; @@ -133,7 +133,7 @@ struct CheckPass : public Pass { for (auto bit : sigmap(action.first)) wire_drivers[bit].push_back( stringf("action %s <= %s (case rule) in process %s", - log_signal(action.first), log_signal(action.second), log_id(proc_it.first))); + log_signal(action.first), log_signal(action.second), proc_it.first.unescape())); for (auto bit : sigmap(action.second)) if (bit.wire) used_wires.insert(bit); @@ -154,7 +154,7 @@ struct CheckPass : public Pass { for (auto bit : sigmap(action.first)) wire_drivers[bit].push_back( stringf("action %s <= %s (sync rule) in process %s", - log_signal(action.first), log_signal(action.second), log_id(proc_it.first))); + log_signal(action.first), log_signal(action.second), proc_it.first.unescape())); for (auto bit : sigmap(action.second)) if (bit.wire) used_wires.insert(bit); } @@ -259,7 +259,7 @@ struct CheckPass : public Pass { { if (mapped && cell->type.begins_with("$") && design->module(cell->type) == nullptr) { if (allow_tbuf && cell->type == ID($_TBUF_)) goto cell_allowed; - log_warning("Cell %s.%s is an unmapped internal cell of type %s.\n", log_id(module), log_id(cell), log_id(cell->type)); + log_warning("Cell %s.%s is an unmapped internal cell of type %s.\n", module, cell, cell->type.unescape()); counter++; cell_allowed:; } @@ -275,10 +275,10 @@ struct CheckPass : public Pass { if (input && bit.wire) used_wires.insert(bit); if (output && !input && bit.wire) - wire_drivers_count[bit]++; + wire_drivers_count[bit]++; if (output && (bit.wire || !input)) - wire_drivers[bit].push_back(stringf("port %s[%d] of cell %s (%s)", log_id(conn.first), i, - log_id(cell), log_id(cell->type))); + wire_drivers[bit].push_back(stringf("port %s[%d] of cell %s (%s)", conn.first.unescape(), i, + cell, cell->type.unescape())); if (output) driver_cells[bit] = cell; } @@ -298,7 +298,7 @@ struct CheckPass : public Pass { SigSpec sig = sigmap(wire); for (int i = 0; i < GetSize(sig); i++) if (sig[i].wire || !wire->port_output) - wire_drivers[sig[i]].push_back(stringf("module input %s[%d]", log_id(wire), i)); + wire_drivers[sig[i]].push_back(stringf("module input %s[%d]", wire, i)); } if (wire->port_output) for (auto bit : sigmap(wire)) @@ -312,7 +312,7 @@ struct CheckPass : public Pass { if (initval[i] == State::S0 || initval[i] == State::S1) init_bits.insert(sigmap(SigBit(wire, i))); if (noinit) { - log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", log_id(module), log_id(wire)); + log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", module, wire); counter++; } } @@ -329,7 +329,7 @@ struct CheckPass : public Pass { for (auto it : wire_drivers) if (wire_drivers_count[it.first] > 1) { - string message = stringf("multiple conflicting drivers for %s.%s:\n", log_id(module), log_signal(it.first)); + string message = stringf("multiple conflicting drivers for %s.%s:\n", module, log_signal(it.first)); for (auto str : it.second) message += stringf(" %s\n", str); log_warning("%s", message); @@ -338,13 +338,13 @@ struct CheckPass : public Pass { for (auto bit : used_wires) if (!wire_drivers.count(bit)) { - log_warning("Wire %s.%s is used but has no driver.\n", log_id(module), log_signal(bit)); + log_warning("Wire %s.%s is used but has no driver.\n", module, log_signal(bit)); counter++; } topo.sort(); for (auto &loop : topo.loops) { - string message = stringf("found logic loop in module %s:\n", log_id(module)); + string message = stringf("found logic loop in module %s:\n", module); // `loop` only contains wire bits, or an occasional special helper node for cells for // which we have done the edges fallback. The cell and its ports that led to an edge are @@ -378,8 +378,8 @@ struct CheckPass : public Pass { SigBit edge_to = sigmap(cell->getPort(to_port))[to_bit]; if (edge_from == from && edge_to == to && nhits++ < HITS_LIMIT) - message += stringf(" %s[%d] --> %s[%d]\n", log_id(from_port), from_bit, - log_id(to_port), to_bit); + message += stringf(" %s[%d] --> %s[%d]\n", from_port.unescape(), from_bit, + to_port.unescape(), to_bit); if (nhits == HITS_LIMIT) message += " ...\n"; } @@ -397,7 +397,7 @@ struct CheckPass : public Pass { driver_src = stringf(" source: %s", src_attr); } - message += stringf(" cell %s (%s)%s\n", log_id(driver), log_id(driver->type), driver_src); + message += stringf(" cell %s (%s)%s\n", driver, driver->type.unescape(), driver_src); if (!coarsened_cells.count(driver)) { MatchingEdgePrinter printer(message, sigmap, prev, bit); @@ -437,7 +437,7 @@ struct CheckPass : public Pass { init_sig.sort_and_unify(); for (auto chunk : init_sig.chunks()) { - log_warning("Wire %s.%s has 'init' attribute and is not driven by an FF cell.\n", log_id(module), log_signal(chunk)); + log_warning("Wire %s.%s has 'init' attribute and is not driven by an FF cell.\n", module, log_signal(chunk)); counter++; } } diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc index ccda023c0..fca943d86 100644 --- a/passes/cmds/chformal.cc +++ b/passes/cmds/chformal.cc @@ -330,7 +330,7 @@ struct ChformalPass : public Pass { for (auto cell : constr_cells) { if (is_triggered_check_cell(cell)) - log_error("Cannot delay edge triggered $check cell %s, run async2sync or clk2fflogic first.\n", log_id(cell)); + log_error("Cannot delay edge triggered $check cell %s, run async2sync or clk2fflogic first.\n", cell); for (int i = 0; i < mode_arg; i++) { @@ -411,7 +411,7 @@ struct ChformalPass : public Pass { continue; if (is_triggered_check_cell(cell)) - log_error("Cannot lower edge triggered $check cell %s, run async2sync or clk2fflogic first.\n", log_id(cell)); + log_error("Cannot lower edge triggered $check cell %s, run async2sync or clk2fflogic first.\n", cell); Cell *plain_cell = module->addCell(NEW_ID, formal_flavor(cell)); diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc index c6d3320ea..b8a61d532 100644 --- a/passes/cmds/connect.cc +++ b/passes/cmds/connect.cc @@ -122,7 +122,7 @@ struct ConnectPass : public Pass { RTLIL::Module *module = nullptr; for (auto mod : design->selected_modules()) { if (module != nullptr) - log_cmd_error("Multiple modules selected: %s, %s\n", log_id(module->name), log_id(mod->name)); + log_cmd_error("Multiple modules selected: %s, %s\n", module->name.unescape(), mod->name.unescape()); module = mod; } if (module == nullptr) diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc index 5677c666d..dcc6f0004 100644 --- a/passes/cmds/connwrappers.cc +++ b/passes/cmds/connwrappers.cc @@ -134,8 +134,8 @@ struct ConnwrappersWorker } if (old_sig.size()) - log("Connected extended bits of %s.%s:%s: %s -> %s\n", log_id(module->name), log_id(cell->name), - log_id(conn.first), log_signal(old_sig), log_signal(conn.second)); + log("Connected extended bits of %s.%s:%s: %s -> %s\n", module->name.unescape(), cell->name.unescape(), + conn.first.unescape(), log_signal(old_sig), log_signal(conn.second)); } } } diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index ddbd98bfd..cfd5d8af8 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -266,7 +266,7 @@ struct DesignPass : public Pass { for (auto mod : copy_src_modules) { - log("Importing %s as %s.\n", log_id(mod), log_id(prefix)); + log("Importing %s as %s.\n", mod, RTLIL::unescape_id(prefix)); RTLIL::Module *t = mod->clone(); t->name = prefix; @@ -295,7 +295,7 @@ struct DesignPass : public Pass { { std::string trg_name = prefix + "." + (cell->type.c_str() + (*cell->type.c_str() == '\\')); - log("Importing %s as %s.\n", log_id(fmod), log_id(trg_name)); + log("Importing %s as %s.\n", fmod, RTLIL::unescape_id(trg_name)); if (copy_to_design->module(trg_name) != nullptr) copy_to_design->remove(copy_to_design->module(trg_name)); diff --git a/passes/cmds/design_equal.cc b/passes/cmds/design_equal.cc index d5f0d617a..1912a823e 100644 --- a/passes/cmds/design_equal.cc +++ b/passes/cmds/design_equal.cc @@ -38,9 +38,9 @@ public: [[noreturn]] void formatted_error(std::string err) { - log("Module A: %s\n", log_id(mod_a->name)); + log("Module A: %s\n", mod_a->name.unescape()); log_module(mod_a, " "); - log("Module B: %s\n", log_id(mod_b->name)); + log("Module B: %s\n", mod_b->name.unescape()); log_module(mod_b, " "); log_cmd_error("Designs are different: %s\n", err); } @@ -68,20 +68,20 @@ public: { for (const auto &it : a->attributes) { if (b->attributes.count(it.first) == 0) - return "missing attribute " + std::string(log_id(it.first)) + " in second design"; + return "missing attribute " + std::string(it.first.unescape()) + " in second design"; if (it.second != b->attributes.at(it.first)) - return "attribute " + std::string(log_id(it.first)) + " mismatch: " + log_const(it.second) + " != " + log_const(b->attributes.at(it.first)); + return "attribute " + std::string(it.first.unescape()) + " mismatch: " + log_const(it.second) + " != " + log_const(b->attributes.at(it.first)); } for (const auto &it : b->attributes) if (a->attributes.count(it.first) == 0) - return "missing attribute " + std::string(log_id(it.first)) + " in first design"; + return "missing attribute " + std::string(it.first.unescape()) + " in first design"; return ""; } std::string compare_wires(const RTLIL::Wire *a, const RTLIL::Wire *b) { if (a->name != b->name) - return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name); + return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (a->width != b->width) return "width mismatch: " + std::to_string(a->width) + " != " + std::to_string(b->width); if (a->start_offset != b->start_offset) @@ -105,19 +105,19 @@ public: { for (const auto &it : mod_a->wires_) { if (mod_b->wires_.count(it.first) == 0) - error("Module %s missing wire %s in second design.\n", log_id(mod_a->name), log_id(it.first)); + error("Module %s missing wire %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); if (std::string mismatch = compare_wires(it.second, mod_b->wires_.at(it.first)); !mismatch.empty()) - error("Module %s wire %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch); + error("Module %s wire %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch); } for (const auto &it : mod_b->wires_) if (mod_a->wires_.count(it.first) == 0) - error("Module %s missing wire %s in first design.\n", log_id(mod_b->name), log_id(it.first)); + error("Module %s missing wire %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } std::string compare_memories(const RTLIL::Memory *a, const RTLIL::Memory *b) { if (a->name != b->name) - return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name); + return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (a->width != b->width) return "width mismatch: " + std::to_string(a->width) + " != " + std::to_string(b->width); if (a->start_offset != b->start_offset) @@ -132,31 +132,31 @@ public: std::string compare_cells(const RTLIL::Cell *a, const RTLIL::Cell *b) { if (a->name != b->name) - return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name); + return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (a->type != b->type) - return "type mismatch: " + std::string(log_id(a->type)) + " != " + log_id(b->type); + return "type mismatch: " + std::string(a->type.unescape()) + " != " + b->type.unescape(); if (std::string mismatch = compare_attributes(a, b); !mismatch.empty()) return mismatch; for (const auto &it : a->parameters) { if (b->parameters.count(it.first) == 0) - return "parameter mismatch: missing parameter " + std::string(log_id(it.first)) + " in second design"; + return "parameter mismatch: missing parameter " + std::string(it.first.unescape()) + " in second design"; if (it.second != b->parameters.at(it.first)) - return "parameter mismatch: " + std::string(log_id(it.first)) + " mismatch: " + log_const(it.second) + " != " + log_const(b->parameters.at(it.first)); + return "parameter mismatch: " + std::string(it.first.unescape()) + " mismatch: " + log_const(it.second) + " != " + log_const(b->parameters.at(it.first)); } for (const auto &it : b->parameters) if (a->parameters.count(it.first) == 0) - return "parameter mismatch: missing parameter " + std::string(log_id(it.first)) + " in first design"; + return "parameter mismatch: missing parameter " + std::string(it.first.unescape()) + " in first design"; for (const auto &it : a->connections()) { if (b->connections().count(it.first) == 0) - return "connection mismatch: missing connection " + std::string(log_id(it.first)) + " in second design"; + return "connection mismatch: missing connection " + std::string(it.first.unescape()) + " in second design"; if (!compare_sigspec(it.second, b->connections().at(it.first))) - return "connection " + std::string(log_id(it.first)) + " mismatch: " + log_signal(it.second) + " != " + log_signal(b->connections().at(it.first)); + return "connection " + std::string(it.first.unescape()) + " mismatch: " + log_signal(it.second) + " != " + log_signal(b->connections().at(it.first)); } for (const auto &it : b->connections()) if (a->connections().count(it.first) == 0) - return "connection mismatch: missing connection " + std::string(log_id(it.first)) + " in first design"; + return "connection mismatch: missing connection " + std::string(it.first.unescape()) + " in first design"; return ""; } @@ -165,26 +165,26 @@ public: { for (const auto &it : mod_a->cells_) { if (mod_b->cells_.count(it.first) == 0) - error("Module %s missing cell %s in second design.\n", log_id(mod_a->name), log_id(it.first)); + error("Module %s missing cell %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); if (std::string mismatch = compare_cells(it.second, mod_b->cells_.at(it.first)); !mismatch.empty()) - error("Module %s cell %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch); + error("Module %s cell %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch); } for (const auto &it : mod_b->cells_) if (mod_a->cells_.count(it.first) == 0) - error("Module %s missing cell %s in first design.\n", log_id(mod_b->name), log_id(it.first)); + error("Module %s missing cell %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } void check_memories() { for (const auto &it : mod_a->memories) { if (mod_b->memories.count(it.first) == 0) - error("Module %s missing memory %s in second design.\n", log_id(mod_a->name), log_id(it.first)); + error("Module %s missing memory %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); if (std::string mismatch = compare_memories(it.second, mod_b->memories.at(it.first)); !mismatch.empty()) - error("Module %s memory %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch); + error("Module %s memory %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch); } for (const auto &it : mod_b->memories) if (mod_a->memories.count(it.first) == 0) - error("Module %s missing memory %s in first design.\n", log_id(mod_b->name), log_id(it.first)); + error("Module %s missing memory %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } std::string compare_case_rules(const RTLIL::CaseRule *a, const RTLIL::CaseRule *b) @@ -251,7 +251,7 @@ public: const auto &ma = a->mem_write_actions[i]; const auto &mb = b->mem_write_actions[i]; if (ma.memid != mb.memid) - return "mem_write_actions " + std::to_string(i) + " memid mismatch: " + log_id(ma.memid) + " != " + log_id(mb.memid); + return "mem_write_actions " + std::to_string(i) + " memid mismatch: " + ma.memid.unescape() + " != " + mb.memid.unescape(); if (!compare_sigspec(ma.address, mb.address)) return "mem_write_actions " + std::to_string(i) + " address mismatch: " + log_signal(ma.address) + " != " + log_signal(mb.address); if (!compare_sigspec(ma.data, mb.data)) @@ -268,7 +268,7 @@ public: std::string compare_processes(const RTLIL::Process *a, const RTLIL::Process *b) { - if (a->name != b->name) return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name); + if (a->name != b->name) return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (std::string mismatch = compare_attributes(a, b); !mismatch.empty()) return mismatch; if (std::string mismatch = compare_case_rules(&a->root_case, &b->root_case); !mismatch.empty()) @@ -285,13 +285,13 @@ public: { for (auto &it : mod_a->processes) { if (mod_b->processes.count(it.first) == 0) - error("Module %s missing process %s in second design.\n", log_id(mod_a->name), log_id(it.first)); + error("Module %s missing process %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); if (std::string mismatch = compare_processes(it.second, mod_b->processes.at(it.first)); !mismatch.empty()) - error("Module %s process %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch.c_str()); + error("Module %s process %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch.c_str()); } for (auto &it : mod_b->processes) if (mod_a->processes.count(it.first) == 0) - error("Module %s missing process %s in first design.\n", log_id(mod_b->name), log_id(it.first)); + error("Module %s missing process %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } void check_connections() @@ -299,13 +299,13 @@ public: const auto &conns_a = mod_a->connections(); const auto &conns_b = mod_b->connections(); if (conns_a.size() != conns_b.size()) { - error("Module %s connection count differs: %zu != %zu\n", log_id(mod_a->name), conns_a.size(), conns_b.size()); + error("Module %s connection count differs: %zu != %zu\n", mod_a->name.unescape(), conns_a.size(), conns_b.size()); } else { for (size_t i = 0; i < conns_a.size(); i++) { if (!compare_sigspec(conns_a[i].first, conns_b[i].first)) - error("Module %s connection %zu LHS %s != %s.\n", log_id(mod_a->name), i, log_signal(conns_a[i].first), log_signal(conns_b[i].first)); + error("Module %s connection %zu LHS %s != %s.\n", mod_a->name.unescape(), i, log_signal(conns_a[i].first), log_signal(conns_b[i].first)); if (!compare_sigspec(conns_a[i].second, conns_b[i].second)) - error("Module %s connection %zu RHS %s != %s.\n", log_id(mod_a->name), i, log_signal(conns_a[i].second), log_signal(conns_b[i].second)); + error("Module %s connection %zu RHS %s != %s.\n", mod_a->name.unescape(), i, log_signal(conns_a[i].second), log_signal(conns_b[i].second)); } } } @@ -313,9 +313,9 @@ public: void check() { if (mod_a->name != mod_b->name) - error("Modules have different names: %s != %s\n", log_id(mod_a->name), log_id(mod_b->name)); + error("Modules have different names: %s != %s\n", mod_a->name.unescape(), mod_b->name.unescape()); if (std::string mismatch = compare_attributes(mod_a, mod_b); !mismatch.empty()) - error("Module %s %s.\n", log_id(mod_a->name), mismatch); + error("Module %s %s.\n", mod_a->name.unescape(), mismatch); check_wires(); check_cells(); check_memories(); @@ -349,7 +349,7 @@ struct DesignEqualPass : public Pass { for (auto &it : design->modules_) { RTLIL::Module *mod = it.second; if (!other->has(mod->name)) - log_error("Second design missing module %s.\n", log_id(mod->name)); + log_error("Second design missing module %s.\n", mod->name.unescape()); ModuleComparator cmp(mod, other->module(mod->name)); cmp.check(); @@ -357,7 +357,7 @@ struct DesignEqualPass : public Pass { for (auto &it : other->modules_) { RTLIL::Module *mod = it.second; if (!design->has(mod->name)) - log_error("First design missing module %s.\n", log_id(mod->name)); + log_error("First design missing module %s.\n", mod->name.unescape()); } log("Designs are identical.\n"); diff --git a/passes/cmds/dft_tag.cc b/passes/cmds/dft_tag.cc index 0a306d113..216f66b2c 100644 --- a/passes/cmds/dft_tag.cc +++ b/passes/cmds/dft_tag.cc @@ -98,7 +98,7 @@ struct DftTagWorker { } for (auto cell : overwrite_cells) { - log_debug("Applying $overwrite_tag %s for signal %s\n", log_id(cell->name), log_signal(cell->getPort(ID::A))); + log_debug("Applying $overwrite_tag %s for signal %s\n", cell->name.unescape(), log_signal(cell->getPort(ID::A))); SigSpec orig_signal = cell->getPort(ID::A); SigSpec interposed_signal = divert_users(orig_signal); auto *set_tag_cell = module->addSetTag(NEW_ID, cell->getParam(ID::TAG).decode_string(), orig_signal, cell->getPort(ID::SET), cell->getPort(ID::CLR), interposed_signal); @@ -470,9 +470,9 @@ struct DftTagWorker { if (!warned_cells.insert(cell).second) return; if (cell->type.isPublic()) - log_warning("Unhandled cell %s (%s) during tag propagation\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled cell %s (%s) during tag propagation\n", cell, cell->type.unescape()); else - log_debug("Unhandled cell %s (%s) during tag propagation\n", log_id(cell), log_id(cell->type)); + log_debug("Unhandled cell %s (%s) during tag propagation\n", cell, cell->type.unescape()); } void process_cell(IdString tag, Cell *cell) @@ -691,7 +691,7 @@ struct DftTagWorker { // TODO handle some more variants if ((ff.has_clk || ff.has_gclk) && !ff.has_ce && !ff.has_aload && !ff.has_srst && !ff.has_arst && !ff.has_sr) { if (ff.has_clk && !tags(ff.sig_clk).empty()) - log_warning("Tags on CLK input ignored for %s (%s)\n", log_id(cell), log_id(cell->type)); + log_warning("Tags on CLK input ignored for %s (%s)\n", cell, cell->type.unescape()); int width = ff.width; @@ -709,7 +709,7 @@ struct DftTagWorker { emit_tag_signal(tag, sig_q, ff.sig_q); return; } else { - log_warning("Unhandled FF-cell %s (%s), consider running clk2fflogic, async2sync and/or dffunmap\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled FF-cell %s (%s), consider running clk2fflogic, async2sync and/or dffunmap\n", cell, cell->type.unescape()); // For unhandled FFs, the default propagation would cause combinational loops emit_tag_signal(tag, ff.sig_q, Const(0, ff.width)); @@ -739,7 +739,7 @@ struct DftTagWorker { // which is an over-approximation (unless the cell is a module that // generates tags itself in which case it could be arbitrary). if (warned_cells.insert(cell).second) - log_warning("Unhandled cell %s (%s) while emitting tag signals\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled cell %s (%s) while emitting tag signals\n", cell, cell->type.unescape()); } void emit_tags() diff --git a/passes/cmds/edgetypes.cc b/passes/cmds/edgetypes.cc index 9324cf630..2f100d724 100644 --- a/passes/cmds/edgetypes.cc +++ b/passes/cmds/edgetypes.cc @@ -92,12 +92,12 @@ struct EdgetypePass : public Pass { auto sink_bit_index = std::get<2>(sink); string source_str = multibit_ports.count(std::pair(source_cell_type, source_port_name)) ? - stringf("%s.%s[%d]", log_id(source_cell_type), log_id(source_port_name), source_bit_index) : - stringf("%s.%s", log_id(source_cell_type), log_id(source_port_name)); + stringf("%s.%s[%d]", source_cell_type.unescape(), source_port_name.unescape(), source_bit_index) : + stringf("%s.%s", source_cell_type.unescape(), source_port_name.unescape()); string sink_str = multibit_ports.count(std::pair(sink_cell_type, sink_port_name)) ? - stringf("%s.%s[%d]", log_id(sink_cell_type), log_id(sink_port_name), sink_bit_index) : - stringf("%s.%s", log_id(sink_cell_type), log_id(sink_port_name)); + stringf("%s.%s[%d]", sink_cell_type.unescape(), sink_port_name.unescape(), sink_bit_index) : + stringf("%s.%s", sink_cell_type.unescape(), sink_port_name.unescape()); edge_cache.insert(source_str + " " + sink_str); } diff --git a/passes/cmds/example_dt.cc b/passes/cmds/example_dt.cc index b10f50502..b18277010 100644 --- a/passes/cmds/example_dt.cc +++ b/passes/cmds/example_dt.cc @@ -226,13 +226,13 @@ struct ExampleDtPass : public Pass { auto ref = compute_graph[i]; log("n%d ", i); - log("%s", log_id(ref.function().name)); + log("%s", ref.function().name.unescape()); for (auto const ¶m : ref.function().parameters) { if (param.second.empty()) - log("[%s]", log_id(param.first)); + log("[%s]", param.first.unescape()); else - log("[%s=%s]", log_id(param.first), log_const(param.second)); + log("[%s=%s]", param.first.unescape(), log_const(param.second)); } log("("); @@ -244,13 +244,13 @@ struct ExampleDtPass : public Pass } log(")\n"); if (ref.has_sparse_attr()) - log("// wire %s\n", log_id(ref.sparse_attr())); + log("// wire %s\n", ref.sparse_attr().unescape()); log("// was #%d %s\n", ref.attr(), log_signal(queue[ref.attr()])); } for (auto const &key : compute_graph.keys()) { - log("return %d as %s \n", key.second, log_id(key.first)); + log("return %d as %s \n", key.second, key.first.unescape()); } } log("Plugin test passed!\n"); diff --git a/passes/cmds/future.cc b/passes/cmds/future.cc index 81cc86bff..15f4b8bd1 100644 --- a/passes/cmds/future.cc +++ b/passes/cmds/future.cc @@ -86,13 +86,13 @@ struct FutureWorker { log_error("Found multiple drivers for future_ff target signal %s\n", log_signal(bit)); auto driver = *found_driver->second.begin(); if (!driver.cell->is_builtin_ff() && driver.cell->type != ID($anyinit)) - log_error("Driver for future_ff target signal %s has non-FF cell type %s\n", log_signal(bit), log_id(driver.cell->type)); + log_error("Driver for future_ff target signal %s has non-FF cell type %s\n", log_signal(bit), driver.cell->type.unescape()); FfData ff(&initvals, driver.cell); if (!ff.has_clk && !ff.has_gclk) log_error("Driver for future_ff target signal %s has cell type %s, which is not clocked\n", log_signal(bit), - log_id(driver.cell->type)); + driver.cell->type.unescape()); ff.unmap_ce_srst(); diff --git a/passes/cmds/linecoverage.cc b/passes/cmds/linecoverage.cc index 26adcce76..2f77f6f21 100644 --- a/passes/cmds/linecoverage.cc +++ b/passes/cmds/linecoverage.cc @@ -93,9 +93,9 @@ struct CoveragePass : public Pass { for (auto module : design->modules()) { - log_debug("Module %s:\n", log_id(module)); + log_debug("Module %s:\n", module); for (auto wire: module->wires()) { - log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute(), log_id(wire->name)); + log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute(), wire->name.unescape()); for (auto src: wire->get_strpool_attribute(ID::src)) { auto filename = extract_src_filename(src); if (filename.empty()) continue; @@ -109,7 +109,7 @@ struct CoveragePass : public Pass { } } for (auto cell: module->cells()) { - log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute(), log_id(cell->name)); + log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute(), cell->name.unescape()); for (auto src: cell->get_strpool_attribute(ID::src)) { auto filename = extract_src_filename(src); if (filename.empty()) continue; diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc index b3134b110..303abea6c 100644 --- a/passes/cmds/ltp.cc +++ b/passes/cmds/ltp.cc @@ -90,7 +90,7 @@ struct LtpWorker return; if (busy.count(bit) > 0) { - log_warning("Detected loop at %s in %s\n", log_signal(bit), log_id(module)); + log_warning("Detected loop at %s in %s\n", log_signal(bit), module); return; } @@ -117,7 +117,7 @@ struct LtpWorker auto &bitinfo = bits.at(bit); if (get<2>(bitinfo)) { printpath(get<1>(bitinfo)); - log("%5d: %s (via %s)\n", get<0>(bitinfo), log_signal(bit), log_id(get<2>(bitinfo))); + log("%5d: %s (via %s)\n", get<0>(bitinfo), log_signal(bit), get<2>(bitinfo)); } else { log("%5d: %s\n", get<0>(bitinfo), log_signal(bit)); } @@ -130,13 +130,13 @@ struct LtpWorker runner(it.first, 0, State::Sx, nullptr); log("\n"); - log("Longest topological path in %s (length=%d):\n", log_id(module), maxlvl); + log("Longest topological path in %s (length=%d):\n", module, maxlvl); if (maxlvl >= 0) printpath(maxbit); if (bit2ff.count(maxbit)) - log("%5s: %s (via %s)\n", "ff", log_signal(get<0>(bit2ff.at(maxbit))), log_id(get<1>(bit2ff.at(maxbit)))); + log("%5s: %s (via %s)\n", "ff", log_signal(get<0>(bit2ff.at(maxbit))), get<1>(bit2ff.at(maxbit))); } }; diff --git a/passes/cmds/portarcs.cc b/passes/cmds/portarcs.cc index 4344d6cb2..581a8bebf 100644 --- a/passes/cmds/portarcs.cc +++ b/passes/cmds/portarcs.cc @@ -107,7 +107,7 @@ struct PortarcsPass : Pass { log_assert(w->port_input || w->port_output); if (w->port_input && w->port_output) { log_warning("Module '%s' with ambiguous direction on port %s ignored.\n", - log_id(m), log_id(w)); + m, w); ambiguous_ports = true; break; } @@ -128,7 +128,7 @@ struct PortarcsPass : Pass { if (!cell->type.in(ID($buf), ID($input_port), ID($connect), ID($tribuf))) { auto tdata = tinfo.find(cell->type); if (tdata == tinfo.end()) - log_cmd_error("Missing timing data for module '%s'.\n", log_id(cell->type)); + log_cmd_error("Missing timing data for module '%s'.\n", cell->type.unescape()); for (auto [edge, delay] : tdata->second.comb) { auto from = edge.first.get_connection(cell); auto to = edge.second.get_connection(cell); @@ -141,7 +141,7 @@ struct PortarcsPass : Pass { } if (!sort.sort()) - log_error("Failed to sort instances in module %s.\n", log_id(m)); + log_error("Failed to sort instances in module %s.\n", m); ordering = sort.sorted; } diff --git a/passes/cmds/portlist.cc b/passes/cmds/portlist.cc index b109ce22a..0804d3a68 100644 --- a/passes/cmds/portlist.cc +++ b/passes/cmds/portlist.cc @@ -71,9 +71,9 @@ struct PortlistPass : public Pass { ports.push_back(stringf("%s [%d:%d] %s", w->port_input ? w->port_output ? "inout" : "input" : "output", w->upto ? w->start_offset : w->start_offset + w->width - 1, w->upto ? w->start_offset + w->width - 1 : w->start_offset, - log_id(w))); + w)); } - log("module %s%s\n", log_id(module), m_mode ? " (" : ""); + log("module %s%s\n", module, m_mode ? " (" : ""); for (int i = 0; i < GetSize(ports); i++) log("%s%s\n", ports[i], m_mode && i+1 < GetSize(ports) ? "," : ""); if (m_mode) diff --git a/passes/cmds/printattrs.cc b/passes/cmds/printattrs.cc index 6a1fab072..6de2ffee3 100644 --- a/passes/cmds/printattrs.cc +++ b/passes/cmds/printattrs.cc @@ -47,9 +47,9 @@ struct PrintAttrsPass : public Pass { static void log_const(RTLIL::IdString s, const RTLIL::Const &x, const unsigned int indent) { if (x.flags & RTLIL::CONST_FLAG_STRING) - log("%s(* %s=\"%s\" *)\n", get_indent_str(indent), log_id(s), x.decode_string()); + log("%s(* %s=\"%s\" *)\n", get_indent_str(indent), s.unescape(), x.decode_string()); else if (x.flags == RTLIL::CONST_FLAG_NONE || x.flags == RTLIL::CONST_FLAG_SIGNED) - log("%s(* %s=%s *)\n", get_indent_str(indent), log_id(s), x.as_string()); + log("%s(* %s=%s *)\n", get_indent_str(indent), s.unescape(), x.as_string()); else log_assert(x.flags & RTLIL::CONST_FLAG_STRING || x.flags == RTLIL::CONST_FLAG_NONE); //intended to fail } @@ -63,14 +63,14 @@ struct PrintAttrsPass : public Pass { for (auto mod : design->selected_modules()) { if (design->selected_whole_module(mod)) { - log("%s%s\n", get_indent_str(indent), log_id(mod->name)); + log("%s%s\n", get_indent_str(indent), mod->name.unescape()); indent += 2; for (auto &it : mod->attributes) log_const(it.first, it.second, indent); } for (auto cell : mod->selected_cells()) { - log("%s%s\n", get_indent_str(indent), log_id(cell->name)); + log("%s%s\n", get_indent_str(indent), cell->name.unescape()); indent += 2; for (auto &it : cell->attributes) log_const(it.first, it.second, indent); @@ -78,7 +78,7 @@ struct PrintAttrsPass : public Pass { } for (auto wire : mod->selected_wires()) { - log("%s%s\n", get_indent_str(indent), log_id(wire->name)); + log("%s%s\n", get_indent_str(indent), wire->name.unescape()); indent += 2; for (auto &it : wire->attributes) log_const(it.first, it.second, indent); diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index a07d588c4..2f70126dd 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -31,13 +31,13 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: to_name = RTLIL::escape_id(to_name); if (module->count_id(to_name)) - log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name, module->name); + log_cmd_error("There is already an object `%s' in module `%s'.\n", RTLIL::unescape_id(to_name), module->name); RTLIL::Wire *wire_to_rename = module->wire(from_name); RTLIL::Cell *cell_to_rename = module->cell(from_name); if (wire_to_rename != nullptr) { - log("Renaming wire %s to %s in module %s.\n", log_id(wire_to_rename), log_id(to_name), log_id(module)); + log("Renaming wire %s to %s in module %s.\n", wire_to_rename, RTLIL::unescape_id(to_name), module); module->rename(wire_to_rename, to_name); if (wire_to_rename->port_id || flag_output) { if (flag_output) @@ -50,12 +50,12 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: if (cell_to_rename != nullptr) { if (flag_output) log_cmd_error("Called with -output but the specified object is a cell.\n"); - log("Renaming cell %s to %s in module %s.\n", log_id(cell_to_rename), log_id(to_name), log_id(module)); + log("Renaming cell %s to %s in module %s.\n", cell_to_rename, RTLIL::unescape_id(to_name), module); module->rename(cell_to_rename, to_name); return; } - log_cmd_error("Object `%s' not found!\n", from_name); + log_cmd_error("Object `%s' not found!\n", RTLIL::unescape_id(from_name)); } static std::string derive_name_from_src(const std::string &src, int counter) @@ -518,7 +518,7 @@ struct RenamePass : public Pass { if (module == nullptr) log_cmd_error("No top module found!\n"); - log("Renaming module %s to %s.\n", log_id(module), log_id(new_name)); + log("Renaming module %s to %s.\n", module, new_name.unescape()); design->rename(module, new_name); } else @@ -532,7 +532,7 @@ struct RenamePass : public Pass { for (auto module : design->selected_modules()) { if (module->memories.size() != 0 || module->processes.size() != 0) { - log_warning("Skipping module %s with unprocessed memories or processes\n", log_id(module)); + log_warning("Skipping module %s with unprocessed memories or processes\n", module); continue; } diff --git a/passes/cmds/sdc/sdc.cc b/passes/cmds/sdc/sdc.cc index 635aad016..cb0b074d5 100644 --- a/passes/cmds/sdc/sdc.cc +++ b/passes/cmds/sdc/sdc.cc @@ -168,7 +168,7 @@ struct SdcObjects { RTLIL::Wire *wire = top->wire(port); if (!wire) { // This should not be possible. See https://github.com/YosysHQ/yosys/pull/5594#issue-3791198573 - log_error("Port %s doesn't exist", log_id(port)); + log_error("Port %s doesn't exist", port.unescape()); } design_ports.push_back(std::make_pair(port.str().substr(1), wire)); } diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 2359efe03..bcb34d1d4 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -1817,7 +1817,7 @@ struct LsPass : public Pass { log("\n%d %s:\n", int(matches.size()), "modules"); std::sort(matches.begin(), matches.end(), RTLIL::sort_by_id_str()); for (auto id : matches) - log(" %s%s\n", log_id(id), design->selected_whole_module(design->module(id)) ? "" : "*"); + log(" %s%s\n", id.unescape(), design->selected_whole_module(design->module(id)) ? "" : "*"); } } else diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 25d8fd34c..9491ef19b 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -246,9 +246,9 @@ struct ChparamPass : public Pass { if (!new_parameters.empty()) log_cmd_error("The options -set and -list cannot be used together.\n"); for (auto module : design->selected_modules()) { - log("%s:\n", log_id(module)); + log("%s:\n", module); for (auto param : module->avail_parameters) - log(" %s\n", log_id(param)); + log(" %s\n", param.unescape()); } return; } diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 14a251c41..f45a2aeee 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -645,16 +645,16 @@ struct ShowWorker module = mod; if (design->selected_whole_module(module->name)) { if (module->get_blackbox_attribute()) { - // log("Skipping blackbox module %s.\n", log_id(module->name)); + //log("Skipping blackbox module %s.\n", module->name.unescape()); continue; } else if (module->cells().size() == 0 && module->connections().empty() && module->processes.empty()) { - log("Skipping empty module %s.\n", log_id(module->name)); + log("Skipping empty module %s.\n", module->name.unescape()); continue; } else - log("Dumping module %s to page %d.\n", log_id(module->name), ++page_counter); + log("Dumping module %s to page %d.\n", module->name.unescape(), ++page_counter); } else - log("Dumping selected parts of module %s to page %d.\n", log_id(module->name), ++page_counter); + log("Dumping selected parts of module %s to page %d.\n", module->name.unescape(), ++page_counter); handle_module(); } } diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc index 2993c3d3a..9439a3a2e 100644 --- a/passes/cmds/splice.cc +++ b/passes/cmds/splice.cc @@ -149,7 +149,7 @@ struct SpliceWorker void run() { - log("Splicing signals in module %s:\n", log_id(module->name)); + log("Splicing signals in module %s:\n", module->name.unescape()); driven_bits.push_back(RTLIL::State::Sm); driven_bits.push_back(RTLIL::State::Sm); diff --git a/passes/cmds/splitcells.cc b/passes/cmds/splitcells.cc index d2063a0c8..a99e4d268 100644 --- a/passes/cmds/splitcells.cc +++ b/passes/cmds/splitcells.cc @@ -89,7 +89,7 @@ struct SplitcellsWorker if (GetSize(slices) <= 1) return 0; slices.push_back(GetSize(outsig)); - log("Splitting %s cell %s/%s into %d slices:\n", log_id(cell->type), log_id(module), log_id(cell), GetSize(slices)-1); + log("Splitting %s cell %s/%s into %d slices:\n", cell->type.unescape(), module, cell, GetSize(slices)-1); for (int i = 1; i < GetSize(slices); i++) { int slice_msb = slices[i]-1; @@ -126,7 +126,7 @@ struct SplitcellsWorker if (slice->hasParam(ID::WIDTH)) slice->setParam(ID::WIDTH, GetSize(slice->getPort(ID::Y))); - log(" slice %d: %s => %s\n", i, log_id(slice_name), log_signal(slice->getPort(ID::Y))); + log(" slice %d: %s => %s\n", i, slice_name, log_signal(slice->getPort(ID::Y))); } module->remove(cell); @@ -155,7 +155,7 @@ struct SplitcellsWorker if (GetSize(slices) <= 1) return 0; slices.push_back(GetSize(outsig)); - log("Splitting %s cell %s/%s into %d slices:\n", log_id(cell->type), log_id(module), log_id(cell), GetSize(slices)-1); + log("Splitting %s cell %s/%s into %d slices:\n", cell->type.unescape(), module, cell, GetSize(slices)-1); for (int i = 1; i < GetSize(slices); i++) { int slice_msb = slices[i]-1; @@ -185,7 +185,7 @@ struct SplitcellsWorker slice->setParam(ID::WIDTH, GetSize(slice->getPort(ID::Q))); - log(" slice %d: %s => %s\n", i, log_id(slice_name), log_signal(slice->getPort(ID::Q))); + log(" slice %d: %s => %s\n", i, slice_name.unescape(), log_signal(slice->getPort(ID::Q))); } module->remove(cell); @@ -258,7 +258,7 @@ struct SplitcellsPass : public Pass { if (count_split_pre) log("Split %d cells in module %s into %d cell slices.\n", - count_split_pre, log_id(module), count_split_post); + count_split_pre, module, count_split_post); } } } SplitnetsPass; diff --git a/passes/cmds/sta.cc b/passes/cmds/sta.cc index 5dfac1575..259794d32 100644 --- a/passes/cmds/sta.cc +++ b/passes/cmds/sta.cc @@ -66,12 +66,12 @@ struct StaWorker Module *inst_module = design->module(cell->type); if (!inst_module) { if (unrecognised_cells.insert(cell->type).second) - log_warning("Cell type '%s' not recognised! Ignoring.\n", log_id(cell->type)); + log_warning("Cell type '%s' not recognised! Ignoring.\n", cell->type.unescape()); continue; } if (!inst_module->get_blackbox_attribute()) { - log_warning("Cell type '%s' is not a black- nor white-box! Ignoring.\n", log_id(cell->type)); + log_warning("Cell type '%s' is not a black- nor white-box! Ignoring.\n", cell->type.unescape()); continue; } @@ -82,7 +82,7 @@ struct StaWorker if (!timing.count(derived_type)) { auto &t = timing.setup_module(inst_module); if (t.has_inputs && t.comb.empty() && t.arrival.empty() && t.required.empty()) - log_warning("Module '%s' has no timing arcs!\n", log_id(cell->type)); + log_warning("Module '%s' has no timing arcs!\n", cell->type.unescape()); } auto &t = timing.at(derived_type); @@ -203,10 +203,10 @@ struct StaWorker return; } - log("Latest arrival time in '%s' is %d:\n", log_id(module), maxarrival); + log("Latest arrival time in '%s' is %d:\n", module, maxarrival); auto it = endpoints.find(maxbit); if (it != endpoints.end() && it->second.sink) - log(" %6d %s (%s.%s)\n", maxarrival, log_id(it->second.sink), log_id(it->second.sink->type), log_id(it->second.port)); + log(" %6d %s (%s.%s)\n", maxarrival, it->second.sink, it->second.sink->type.unescape(), it->second.port.unescape()); else { log(" %6d (%s)\n", maxarrival, b.wire->port_output ? "" : ""); if (!b.wire->port_output) @@ -217,7 +217,7 @@ struct StaWorker int arrival = b.wire->get_intvec_attribute(ID::sta_arrival)[b.offset]; if (jt->second.driver) { log(" %s\n", log_signal(b)); - log(" %6d %s (%s.%s->%s)\n", arrival, log_id(jt->second.driver), log_id(jt->second.driver->type), log_id(jt->second.src_port), log_id(jt->second.dst_port)); + log(" %6d %s (%s.%s->%s)\n", arrival, jt->second.driver, jt->second.driver->type.unescape(), jt->second.src_port.unescape(), jt->second.dst_port.unescape()); } else if (b.wire->port_input) log(" %6d %s (%s)\n", arrival, log_signal(b), ""); @@ -234,13 +234,13 @@ struct StaWorker continue; if (!b.wire->attributes.count(ID::sta_arrival)) { - log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b)); + log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", module, log_signal(b)); continue; } auto arrival = b.wire->get_intvec_attribute(ID::sta_arrival)[b.offset]; if (arrival < 0) { - log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b)); + log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", module, log_signal(b)); continue; } arrival += i.second.required; diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 9494d6032..de767b96a 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -523,7 +523,7 @@ struct statdata_t { print_log_line("cells", local_num_cells, local_area, num_cells, area, 0, print_area, print_hierarchical, print_global_only); for (auto &it : num_cells_by_type) if (it.second) { - auto name = string(log_id(it.first)); + auto name = string(it.first.unescape()); print_log_line(name, local_num_cells_by_type.count(it.first) ? local_num_cells_by_type.at(it.first) : 0, local_area_cells_by_type.count(it.first) ? local_area_cells_by_type.at(it.first) : 0, it.second, area_cells_by_type.at(it.first), 1, print_area, print_hierarchical, print_global_only); @@ -533,7 +533,7 @@ struct statdata_t { print_global_only); for (auto &it : num_submodules_by_type) if (it.second) - print_log_line(string(log_id(it.first)), it.second, 0, it.second, + print_log_line(string(it.first.unescape()), it.second, 0, it.second, submodules_area_by_type.count(it.first) ? submodules_area_by_type.at(it.first) : 0, 1, print_area, print_hierarchical, print_global_only); } @@ -607,7 +607,7 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %s", json11::Json(log_id(it.first)).dump(), + log(" %s: %s", json11::Json(it.first.unescape()).dump(), json_line(local_num_cells_by_type.count(it.first) ? local_num_cells_by_type.at(it.first) : 0, local_area_cells_by_type.count(it.first) ? local_area_cells_by_type.at(it.first) : 0, it.second, area_cells_by_type.at(it.first)) @@ -621,7 +621,7 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %s", json11::Json(log_id(it.first)).dump(), + log(" %s: %s", json11::Json(it.first.unescape()).dump(), json_line(0, 0, it.second, submodules_area_by_type.count(it.first) ? submodules_area_by_type.at(it.first) : 0) .c_str()); @@ -662,14 +662,14 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(log_id(it.first)).dump(), it.second); + log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); first_line = false; } for (auto &it : num_submodules_by_type) if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(log_id(it.first)).dump(), it.second); + log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); first_line = false; } log("\n"); @@ -697,14 +697,14 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(log_id(it.first)).dump(), it.second); + log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); first_line = false; } for (auto &it : num_submodules_by_type) if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(log_id(it.first)).dump(), it.second); + log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); first_line = false; } log("\n"); @@ -734,7 +734,7 @@ statdata_t hierarchy_worker(std::map &mod_stat, RTL for (auto &it : mod_data.num_submodules_by_type) { if (mod_stat.count(it.first) > 0) { if (!quiet) - mod_data.print_log_line(string(log_id(it.first)), mod_stat.at(it.first).local_num_cells, + mod_data.print_log_line(string(it.first.unescape()), mod_stat.at(it.first).local_num_cells, mod_stat.at(it.first).local_area, mod_stat.at(it.first).num_cells, mod_stat.at(it.first).area, level, has_area, hierarchy_mode); hierarchy_worker(mod_stat, it.first, level + 1, quiet, has_area, hierarchy_mode) * it.second; @@ -1009,7 +1009,7 @@ struct StatPass : public Pass { first_module = false; } else { log("\n"); - log("=== %s%s ===\n", log_id(mod->name), mod->is_selected_whole() ? "" : " (partially selected)"); + log("=== %s%s ===\n", mod->name.unescape(), mod->is_selected_whole() ? "" : " (partially selected)"); log("\n"); data.log_data(mod->name, false, has_area, hierarchy_mode); } @@ -1026,7 +1026,7 @@ struct StatPass : public Pass { log("=== design hierarchy ===\n"); log("\n"); mod_stat[top_mod->name].print_log_header(has_area, hierarchy_mode, true); - mod_stat[top_mod->name].print_log_line(log_id(top_mod->name), mod_stat[top_mod->name].local_num_cells, + mod_stat[top_mod->name].print_log_line(top_mod->name.unescape(), mod_stat[top_mod->name].local_num_cells, mod_stat[top_mod->name].local_area, mod_stat[top_mod->name].num_cells, mod_stat[top_mod->name].area, 0, has_area, hierarchy_mode, true); } diff --git a/passes/cmds/timeest.cc b/passes/cmds/timeest.cc index 1caa1ddaf..579a9c48e 100644 --- a/passes/cmds/timeest.cc +++ b/passes/cmds/timeest.cc @@ -83,7 +83,7 @@ struct EstimateSta { void run() { - log("\nModule %s\n", log_id(m)); + log("\nModule %s\n", m); if (clk.has_value()) log("Domain %s\n", log_signal(*clk)); @@ -97,10 +97,10 @@ struct EstimateSta { FfData ff(nullptr, cell); if (!ff.has_clk) { log_warning("Ignoring unsupported storage element '%s' (%s)\n", - log_id(cell), log_id(cell->type)); + cell, cell->type.unescape()); continue; } - if (ff.sig_clk != clk) + if (!clk || ff.sig_clk.as_bit() != *clk) continue; launch.append(ff.sig_q); sample.append(ff.sig_d); @@ -121,7 +121,7 @@ struct EstimateSta { aigs.emplace(fingerprint, Aig(cell)); if (aigs.at(fingerprint).name.empty()) { log_error("Unsupported cell '%s' in module '%s'", - log_id(cell->type), log_id(m)); + cell->type.unescape(), m); } } @@ -141,15 +141,15 @@ struct EstimateSta { for (auto &mem : Mem::get_all_memories(m)) { for (auto &rd : mem.rd_ports) { if (!rd.clk_enable) { - log_error("Unsupported async memory port '%s'\n", log_id(rd.cell)); + log_error("Unsupported async memory port '%s'\n", rd.cell); continue; } - if (sigmap(rd.clk) != clk) + if (!clk || sigmap(rd.clk).as_bit() != *clk) continue; add_seq(rd.cell, rd.data, {rd.addr, rd.srst, rd.en}); } for (auto &wr : mem.wr_ports) { - if (sigmap(wr.clk) != clk) + if (!clk || sigmap(wr.clk).as_bit() != *clk) continue; add_seq(wr.cell, {}, {wr.en, wr.addr, wr.data}); } @@ -165,7 +165,7 @@ struct EstimateSta { } else if (port->port_output && !port->port_input) { all_outputs.append(port); } else if (port->port_output && port->port_input) { - log_warning("Ignoring bi-directional port %s\n", log_id(port)); + log_warning("Ignoring bi-directional port %s\n", port); } } add_seq(nullptr, all_inputs, all_outputs); @@ -216,7 +216,7 @@ struct EstimateSta { } if (!topo.sort()) - log_error("Module '%s' contains combinational loops", log_id(m)); + log_error("Module '%s' contains combinational loops", m); // now we determine how long it takes for signals to stabilize @@ -342,7 +342,7 @@ struct EstimateSta { std::string src_attr = cell->get_src_attribute(); cell_src = stringf(" source: %s", src_attr); } - log(" cell %s (%s)%s\n", log_id(cell), log_id(cell->type), cell_src); + log(" cell %s (%s)%s\n", cell, cell->type.unescape(), cell_src); printed.insert(cell); } } else { @@ -425,7 +425,7 @@ struct TimeestPass : Pass { if (clk_domain_specified) { if (!m->wire(RTLIL::escape_id(clk_name))) { - log_warning("No domain '%s' in module %s\n", clk_name.c_str(), log_id(m)); + log_warning("No domain '%s' in module %s\n", clk_name.c_str(), m); continue; } diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc index 52c00072f..828b65c24 100644 --- a/passes/cmds/torder.cc +++ b/passes/cmds/torder.cc @@ -74,7 +74,7 @@ struct TorderPass : public Pass { for (auto module : design->selected_modules()) { - log("module %s\n", log_id(module)); + log("module %s\n", module); SigMap sigmap(module); dict> bit_drivers, bit_users; @@ -116,12 +116,12 @@ struct TorderPass : public Pass { for (auto &it : toposort.loops) { log(" loop"); for (auto cell : it) - log(" %s", log_id(cell)); + log(" %s", cell); log("\n"); } for (auto cell : toposort.sorted) - log(" cell %s\n", log_id(cell)); + log(" cell %s\n", cell); } } } TorderPass; diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc index 222fecaca..37f7da89b 100644 --- a/passes/cmds/trace.cc +++ b/passes/cmds/trace.cc @@ -28,34 +28,34 @@ struct TraceMonitor : public RTLIL::Monitor { void notify_module_add(RTLIL::Module *module) override { - log("#TRACE# Module add: %s\n", log_id(module)); + log("#TRACE# Module add: %s\n", module); } void notify_module_del(RTLIL::Module *module) override { - log("#TRACE# Module delete: %s\n", log_id(module)); + log("#TRACE# Module delete: %s\n", module); } void notify_connect(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) 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)); + log("#TRACE# Cell connect: %s.%s.%s = %s (was: %s)\n", cell->module, cell, port.unescape(), log_signal(sig), log_signal(old_sig)); } void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) override { - log("#TRACE# Connection in module %s: %s = %s\n", log_id(module), log_signal(sigsig.first), log_signal(sigsig.second)); + log("#TRACE# Connection in module %s: %s = %s\n", module, log_signal(sigsig.first), log_signal(sigsig.second)); } void notify_connect(RTLIL::Module *module, const std::vector &sigsig_vec) override { - log("#TRACE# New connections in module %s:\n", log_id(module)); + log("#TRACE# New connections in module %s:\n", module); for (auto &sigsig : sigsig_vec) log("## %s = %s\n", log_signal(sigsig.first), log_signal(sigsig.second)); } void notify_blackout(RTLIL::Module *module) override { - log("#TRACE# Blackout in module %s:\n", log_id(module)); + log("#TRACE# Blackout in module %s:\n", module); } }; diff --git a/passes/cmds/viz.cc b/passes/cmds/viz.cc index e3b09d029..0d4e3efda 100644 --- a/passes/cmds/viz.cc +++ b/passes/cmds/viz.cc @@ -279,7 +279,7 @@ struct Graph { Graph(Module *module, const VizConfig &config) : module(module), config(config) { - log("Running 'viz -%d' for module %s:\n", config.effort, log_id(module)); + log("Running 'viz -%d' for module %s:\n", config.effort, module); log(" Phase %d: Construct initial graph\n", phase_counter++); SigMap sigmap(module); @@ -718,7 +718,7 @@ struct VizWorker void write_dot(FILE *f) { - fprintf(f, "digraph \"%s\" {\n", log_id(module)); + fprintf(f, "digraph \"%s\" {\n", module->name.unescape().c_str()); fprintf(f, " rankdir = LR;\n"); dict>> extra_lines; @@ -734,7 +734,7 @@ struct VizWorker buffer.emplace_back(); for (auto name : g->names()) - buffer.back().push_back(log_id(name)); + buffer.back().push_back(name.unescape()); std::sort(buffer.back().begin(), buffer.back().end()); std::sort(buffer.begin(), buffer.end()); @@ -782,7 +782,7 @@ struct VizWorker g->names().sort(); std::string label; // = stringf("vg=%d\\n", g->index); for (auto n : g->names()) - label = label + (label.empty() ? "" : "\\n") + log_id(n); + label = label + (label.empty() ? "" : "\\n") + n.unescape(); fprintf(f, "\tn%d [shape=rectangle,label=\"%s\"];\n", g->index, label.c_str()); } else { std::string label = stringf("vg=%d | %d cells", g->index, GetSize(g->names())); diff --git a/passes/cmds/wrapcell.cc b/passes/cmds/wrapcell.cc index 4c6f44ed7..1d73decc5 100644 --- a/passes/cmds/wrapcell.cc +++ b/passes/cmds/wrapcell.cc @@ -70,7 +70,7 @@ std::optional format_with_params(std::string fmt, const dicttype)) log_error("Non-internal cell type '%s' on cell '%s' in module '%s' unsupported\n", - log_id(cell->type), log_id(cell), log_id(module)); + cell->type.unescape(), cell, module); std::vector> unused_outputs, used_outputs; for (auto conn : cell->connections()) { @@ -233,7 +233,7 @@ struct WrapcellPass : Pass { std::optional unescaped_name = format_with_params(name_fmt, cell->parameters, context); if (!unescaped_name) log_error("Formatting error when processing cell '%s' in module '%s'\n", - log_id(cell), log_id(module)); + cell, module); IdString name = RTLIL::escape_id(unescaped_name.value()); if (d->module(name)) @@ -274,7 +274,7 @@ struct WrapcellPass : Pass { if (!value) log_error("Formatting error when processing cell '%s' in module '%s'\n", - log_id(cell), log_id(module)); + cell, module); subm->set_string_attribute(rule.name, value.value()); } diff --git a/passes/cmds/xprop.cc b/passes/cmds/xprop.cc index 7291bb859..25c1a7320 100644 --- a/passes/cmds/xprop.cc +++ b/passes/cmds/xprop.cc @@ -463,7 +463,11 @@ struct XpropWorker return; } - log_warning("Unhandled cell %s (%s) during maybe-x marking\n", log_id(cell), log_id(cell->type)); + if (cell->type.in(ID($scopeinfo))) { + return; + } + + log_warning("Unhandled cell %s (%s) during maybe-x marking\n", cell, cell->type.unescape()); mark_outputs_maybe_x(cell); } @@ -858,7 +862,7 @@ struct XpropWorker if ((ff.has_clk || ff.has_gclk) && !ff.has_ce && !ff.has_aload && !ff.has_srst && !ff.has_arst && !ff.has_sr) { if (ff.has_clk && maybe_x(ff.sig_clk)) { - log_warning("Only non-x CLK inputs are currently supported for %s (%s)\n", log_id(cell), log_id(cell->type)); + log_warning("Only non-x CLK inputs are currently supported for %s (%s)\n", cell, cell->type.unescape()); } else { auto init_q = ff.val_init; auto init_q_is_1 = init_q; @@ -903,7 +907,7 @@ struct XpropWorker return; } } else { - log_warning("Unhandled FF-cell %s (%s), consider running clk2fflogic, async2sync and/or dffunmap\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled FF-cell %s (%s), consider running clk2fflogic, async2sync and/or dffunmap\n", cell, cell->type.unescape()); } } @@ -960,9 +964,9 @@ struct XpropWorker log("Running 'demuxmap' preserves x-propagation and can be run before 'xprop'.\n"); if (options.required) - log_error("Unhandled cell %s (%s)\n", log_id(cell), log_id(cell->type)); + log_error("Unhandled cell %s (%s)\n", cell, cell->type.unescape()); else - log_warning("Unhandled cell %s (%s)\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled cell %s (%s)\n", cell, cell->type.unescape()); } void split_ports() @@ -976,7 +980,7 @@ struct XpropWorker auto wire = module->wire(port); if (module->design->selected(module, wire)) { if (wire->port_input == wire->port_output) { - log_warning("Port %s not an input or an output port which is not supported by xprop\n", log_id(wire)); + log_warning("Port %s not an input or an output port which is not supported by xprop\n", wire); } else if ((options.split_inputs && !options.assume_def_inputs && wire->port_input) || (options.split_outputs && wire->port_output)) { auto port_d = module->uniquify(stringf("%s_d", port)); auto port_x = module->uniquify(stringf("%s_x", port)); diff --git a/passes/equiv/equiv_induct.cc b/passes/equiv/equiv_induct.cc index e4480c893..c2308462e 100644 --- a/passes/equiv/equiv_induct.cc +++ b/passes/equiv/equiv_induct.cc @@ -84,7 +84,7 @@ struct EquivInductWorker : public EquivWorker<> void run() { - log("Found %d unproven $equiv cells in module %s:\n", GetSize(workset), log_id(module)); + log("Found %d unproven $equiv cells in module %s:\n", GetSize(workset), module); if (satgen.model_undef) { for (auto cell : cells) @@ -217,7 +217,7 @@ struct EquivInductPass : public Pass { } if (unproven_equiv_cells.empty()) { - log("No selected unproven $equiv cells found in %s.\n", log_id(module)); + log("No selected unproven $equiv cells found in %s.\n", module); continue; } diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc index bae7452f7..3aa3fac63 100644 --- a/passes/equiv/equiv_make.cc +++ b/passes/equiv/equiv_make.cc @@ -79,6 +79,7 @@ struct EquivMakeWorker if (token == ".fsm") { IdString modname = RTLIL::escape_id(next_token(line)); + (void)modname; IdString signame = RTLIL::escape_id(next_token(line)); if (encdata.count(signame)) log_cmd_error("Re-definition of signal '%s' in encfile '%s'!\n", signame, fn); @@ -159,7 +160,7 @@ struct EquivMakeWorker if (encdata.count(id)) { - log("Creating encoder/decoder for signal %s.\n", log_id(id)); + log("Creating encoder/decoder for signal %s.\n", id.unescape()); Wire *dec_wire = equiv_mod->addWire(id.str() + "_decoded", gold_wire->width); Wire *enc_wire = equiv_mod->addWire(id.str() + "_encoded", gate_wire->width); @@ -226,15 +227,15 @@ struct EquivMakeWorker if (gold_wire == nullptr || gate_wire == nullptr || gold_wire->width != gate_wire->width) { if (gold_wire && gold_wire->port_id) - log_error("Can't match gold port `%s' to a gate port.\n", log_id(gold_wire)); + log_error("Can't match gold port `%s' to a gate port.\n", gold_wire); if (gate_wire && gate_wire->port_id) - log_error("Can't match gate port `%s' to a gold port.\n", log_id(gate_wire)); + log_error("Can't match gate port `%s' to a gold port.\n", gate_wire); continue; } log("Presumably equivalent wires: %s (%s), %s (%s) -> %s\n", - log_id(gold_wire), log_signal(assign_map(gold_wire)), - log_id(gate_wire), log_signal(assign_map(gate_wire)), log_id(id)); + gold_wire, log_signal(assign_map(gold_wire)), + gate_wire, log_signal(assign_map(gate_wire)), id.unescape()); if (gold_wire->port_output || gate_wire->port_output) { @@ -313,7 +314,7 @@ struct EquivMakeWorker new_sig[i] = old_sig[i]; if (old_sig != new_sig) { log("Changing input %s of cell %s (%s): %s -> %s\n", - log_id(conn.first), log_id(c), log_id(c->type), + conn.first.unescape(), c, c->type.unescape(), log_signal(old_sig), log_signal(new_sig)); c->setPort(conn.first, new_sig); } @@ -344,7 +345,7 @@ struct EquivMakeWorker goto try_next_cell_name; log("Presumably equivalent cells: %s %s (%s) -> %s\n", - log_id(gold_cell), log_id(gate_cell), log_id(gold_cell->type), log_id(id)); + gold_cell, gate_cell, gold_cell->type.unescape(), id.unescape()); for (auto gold_conn : gold_cell->connections()) { diff --git a/passes/equiv/equiv_mark.cc b/passes/equiv/equiv_mark.cc index 97a2a38dd..0f355af4e 100644 --- a/passes/equiv/equiv_mark.cc +++ b/passes/equiv/equiv_mark.cc @@ -109,7 +109,7 @@ struct EquivMarkWorker void run() { - log("Running equiv_mark on module %s:\n", log_id(module)); + log("Running equiv_mark on module %s:\n", module); // marking region 0 diff --git a/passes/equiv/equiv_miter.cc b/passes/equiv/equiv_miter.cc index 6acfe85a9..b8372ceb0 100644 --- a/passes/equiv/equiv_miter.cc +++ b/passes/equiv/equiv_miter.cc @@ -82,7 +82,7 @@ struct EquivMiterWorker for (auto c : source_module->selected_cells()) if (c->type == ID($equiv)) { - log("Seed $equiv cell: %s\n", log_id(c)); + log("Seed $equiv cell: %s\n", c); seed_cells.insert(c); } @@ -194,11 +194,11 @@ struct EquivMiterWorker w->port_input = true; } if (w->port_output && w->port_input) - log("Created miter inout port %s.\n", log_id(w)); + log("Created miter inout port %s.\n", w); else if (w->port_output) - log("Created miter output port %s.\n", log_id(w)); + log("Created miter output port %s.\n", w); else if (w->port_input) - log("Created miter input port %s.\n", log_id(w)); + log("Created miter input port %s.\n", w); } miter_module->fixup_ports(); @@ -252,7 +252,7 @@ struct EquivMiterWorker void run() { - log("Creating miter %s from module %s.\n", log_id(miter_module), log_id(source_module)); + log("Creating miter %s from module %s.\n", miter_module, source_module); find_miter_cells_wires(); copy_to_miter(); make_stuff(); @@ -320,7 +320,7 @@ struct EquivMiterPass : public Pass { extra_args(args, argidx, design); if (design->module(worker.miter_name)) - log_cmd_error("Miter module %s already exists.\n", log_id(worker.miter_name)); + log_cmd_error("Miter module %s already exists.\n", worker.miter_name.unescape()); worker.source_module = nullptr; for (auto m : design->selected_modules()) { diff --git a/passes/equiv/equiv_purge.cc b/passes/equiv/equiv_purge.cc index 5b0696d9b..4062161bb 100644 --- a/passes/equiv/equiv_purge.cc +++ b/passes/equiv/equiv_purge.cc @@ -37,7 +37,7 @@ struct EquivPurgeWorker Wire *wire = sig.as_wire(); if (wire->name.isPublic()) { if (!wire->port_output) { - log(" Module output: %s (%s)\n", log_signal(wire), log_id(cellname)); + log(" Module output: %s (%s)\n", log_signal(wire), cellname.unescape()); wire->port_output = true; } return wire; @@ -53,7 +53,7 @@ struct EquivPurgeWorker Wire *wire = module->addWire(name, GetSize(sig)); wire->port_output = true; module->connect(wire, sig); - log(" Module output: %s (%s)\n", log_signal(wire), log_id(cellname)); + log(" Module output: %s (%s)\n", log_signal(wire), cellname.unescape()); return wire; } } @@ -87,7 +87,7 @@ struct EquivPurgeWorker void run() { - log("Running equiv_purge on module %s:\n", log_id(module)); + log("Running equiv_purge on module %s:\n", module); for (auto wire : module->wires()) { wire->port_input = false; diff --git a/passes/equiv/equiv_remove.cc b/passes/equiv/equiv_remove.cc index 5d1823e12..c871cd9ef 100644 --- a/passes/equiv/equiv_remove.cc +++ b/passes/equiv/equiv_remove.cc @@ -69,7 +69,7 @@ struct EquivRemovePass : public Pass { { for (auto cell : module->selected_cells()) if (cell->type == ID($equiv) && (mode_gold || mode_gate || cell->getPort(ID::A) == cell->getPort(ID::B))) { - log("Removing $equiv cell %s.%s (%s).\n", log_id(module), log_id(cell), log_signal(cell->getPort(ID::Y))); + log("Removing $equiv cell %s.%s (%s).\n", module, cell, log_signal(cell->getPort(ID::Y))); module->connect(cell->getPort(ID::Y), mode_gate ? cell->getPort(ID::B) : cell->getPort(ID::A)); module->remove(cell); remove_count++; diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc index e498928c3..6f3c9dc71 100644 --- a/passes/equiv/equiv_simple.cc +++ b/passes/equiv/equiv_simple.cc @@ -205,10 +205,10 @@ struct EquivSimpleWorker : public EquivWorker (GetSize(cone_a.cells) + GetSize(cone_b.cells)) - GetSize(cells)); #if 0 for (auto cell : short_cells_cone_a) - log(" A-side cell: %s\n", log_id(cell)); + log(" A-side cell: %s\n", cell); for (auto cell : short_cells_cone_b) - log(" B-side cell: %s\n", log_id(cell)); + log(" B-side cell: %s\n", cell); #endif } void report_new_assume_cells(const pool& extra_problem_cells, int old_size, const pool& problem_cells) const @@ -219,7 +219,7 @@ struct EquivSimpleWorker : public EquivWorker old_size - (GetSize(problem_cells) - GetSize(extra_problem_cells))); #if 0 for (auto cell : extra_problem_cells) - log(" cell: %s\n", log_id(cell)); + log(" cell: %s\n", cell); #endif } } @@ -305,7 +305,7 @@ struct EquivSimpleWorker : public EquivWorker pool seed_b = { bit_b }; if (cfg.verbose) { - log(" Trying to prove $equiv cell %s:\n", log_id(cell)); + log(" Trying to prove $equiv cell %s:\n", cell); log(" A = %s, B = %s, Y = %s\n", log_signal(bit_a), log_signal(bit_b), log_signal(cell->getPort(ID::Y))); } else { log(" Trying to prove $equiv for %s:", log_signal(cell->getPort(ID::Y))); @@ -477,7 +477,7 @@ struct EquivSimplePass : public Pass { continue; log("Found %d unproven $equiv cells (%d groups) in %s:\n", - unproven_cells_counter, GetSize(unproven_equiv_cells), log_id(module)); + unproven_cells_counter, GetSize(unproven_equiv_cells), module); for (auto cell : module->cells()) { if (!ct.cell_known(cell->type)) diff --git a/passes/equiv/equiv_status.cc b/passes/equiv/equiv_status.cc index b221be27c..da53c60a2 100644 --- a/passes/equiv/equiv_status.cc +++ b/passes/equiv/equiv_status.cc @@ -67,17 +67,17 @@ struct EquivStatusPass : public Pass { } if (unproven_equiv_cells.empty() && !proven_equiv_cells) { - log("No $equiv cells found in %s.\n", log_id(module)); + log("No $equiv cells found in %s.\n", module); continue; } - log("Found %d $equiv cells in %s:\n", GetSize(unproven_equiv_cells) + proven_equiv_cells, log_id(module)); + log("Found %d $equiv cells in %s:\n", GetSize(unproven_equiv_cells) + proven_equiv_cells, module); log(" Of those cells %d are proven and %d are unproven.\n", proven_equiv_cells, GetSize(unproven_equiv_cells)); if (unproven_equiv_cells.empty()) { log(" Equivalence successfully proven!\n"); } else { for (auto cell : unproven_equiv_cells) - log(" Unproven $equiv %s: %s %s\n", log_id(cell), log_signal(cell->getPort(ID::A)), log_signal(cell->getPort(ID::B))); + log(" Unproven $equiv %s: %s %s\n", cell, log_signal(cell->getPort(ID::A)), log_signal(cell->getPort(ID::B))); } unproven_count += GetSize(unproven_equiv_cells); diff --git a/passes/equiv/equiv_struct.cc b/passes/equiv/equiv_struct.cc index 411f0dd5c..7f8d8d282 100644 --- a/passes/equiv/equiv_struct.cc +++ b/passes/equiv/equiv_struct.cc @@ -79,7 +79,7 @@ struct EquivStructWorker inputs_a.append(bits_a[i]); inputs_b.append(bits_b[i]); input_names.push_back(GetSize(bits_a) == 1 ? port_a.first.str() : - stringf("%s[%d]", log_id(port_a.first), i)); + stringf("%s[%d]", port_a.first.unescape(), i)); } } @@ -111,7 +111,7 @@ struct EquivStructWorker } auto merged_attr = cell_b->get_strpool_attribute(ID::equiv_merged); - merged_attr.insert(log_id(cell_b)); + merged_attr.insert(cell_b->name.unescape()); cell_a->add_strpool_attribute(ID::equiv_merged, merged_attr); module->remove(cell_b); } @@ -144,7 +144,7 @@ struct EquivStructWorker SigBit sig_b = sigmap(cell->getPort(ID::B).as_bit()); SigBit sig_y = sigmap(cell->getPort(ID::Y).as_bit()); if (sig_a == sig_b && equiv_inputs.count(sig_y)) { - log(" Purging redundant $equiv cell %s.\n", log_id(cell)); + log(" Purging redundant $equiv cell %s.\n", cell); module->connect(sig_y, sig_a); module->remove(cell); merge_count++; @@ -266,9 +266,9 @@ struct EquivStructWorker run_strategy: int total_group_size = GetSize(gold_cells) + GetSize(gate_cells) + GetSize(other_cells); log(" %s merging %d %s cells (from group of %d) using strategy %s:\n", phase ? "Bwd" : "Fwd", - 2*GetSize(cell_pairs), log_id(cells_type), total_group_size, strategy); + 2*GetSize(cell_pairs), cells_type.unescape(), total_group_size, strategy); for (auto it : cell_pairs) { - log(" Merging cells %s and %s.\n", log_id(it.first), log_id(it.second)); + log(" Merging cells %s and %s.\n", it.first, it.second); merge_cell_pair(it.first, it.second); } } @@ -347,7 +347,7 @@ struct EquivStructPass : public Pass { for (auto module : design->selected_modules()) { int module_merge_count = 0; - log("Running equiv_struct on module %s:\n", log_id(module)); + log("Running equiv_struct on module %s:\n", module); for (int iter = 0;; iter++) { if (iter == max_iter) { log(" Reached iteration limit of %d.\n", iter); @@ -359,7 +359,7 @@ struct EquivStructPass : public Pass { module_merge_count += worker.merge_count; } if (module_merge_count) - log(" Performed a total of %d merges in module %s.\n", module_merge_count, log_id(module)); + log(" Performed a total of %d merges in module %s.\n", module_merge_count, module); } } } EquivStructPass; diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc index 5f491a16c..dfe99f512 100644 --- a/passes/fsm/fsm_detect.cc +++ b/passes/fsm/fsm_detect.cc @@ -132,7 +132,7 @@ static void detect_fsm(RTLIL::Wire *wire, bool ignore_self_reset=false) if (wire->width <= 1) { if (has_fsm_encoding_attr) { - log_warning("Removing fsm_encoding attribute from 1-bit net: %s.%s\n", log_id(wire->module), log_id(wire)); + log_warning("Removing fsm_encoding attribute from 1-bit net: %s.%s\n", wire->module, wire); wire->attributes.erase(ID::fsm_encoding); } return; @@ -230,23 +230,23 @@ static void detect_fsm(RTLIL::Wire *wire, bool ignore_self_reset=false) warnings.push_back("FSM seems to be self-resetting. Possible simulation-synthesis mismatch!\n"); if (!warnings.empty()) { - string warnmsg = stringf("Regarding the user-specified fsm_encoding attribute on %s.%s:\n", log_id(wire->module), log_id(wire)); + string warnmsg = stringf("Regarding the user-specified fsm_encoding attribute on %s.%s:\n", wire->module, wire); for (auto w : warnings) warnmsg += " " + w; log_warning("%s", warnmsg); } else { - log("FSM state register %s.%s already has fsm_encoding attribute.\n", log_id(wire->module), log_id(wire)); + log("FSM state register %s.%s already has fsm_encoding attribute.\n", wire->module, wire); } } else if (looks_like_state_reg && looks_like_good_state_reg && !has_init_attr && !is_module_port && !is_self_resetting) { - log("Found FSM state register %s.%s.\n", log_id(wire->module), log_id(wire)); + log("Found FSM state register %s.%s.\n", wire->module, wire); wire->attributes[ID::fsm_encoding] = RTLIL::Const("auto"); } else if (looks_like_state_reg) { - log("Not marking %s.%s as FSM state register:\n", log_id(wire->module), log_id(wire)); + log("Not marking %s.%s as FSM state register:\n", wire->module, wire); if (is_module_port) log(" Register is connected to module port.\n"); diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc index b11f0d3be..40c1d9904 100644 --- a/passes/fsm/fsm_expand.cc +++ b/passes/fsm/fsm_expand.cc @@ -189,12 +189,12 @@ struct FsmExpand if (GetSize(input_sig) > 10) log_warning("Cell %s.%s (%s) has %d input bits, merging into FSM %s.%s might be problematic.\n", - log_id(cell->module), log_id(cell), log_id(cell->type), - GetSize(input_sig), log_id(fsm_cell->module), log_id(fsm_cell)); + cell->module, cell, cell->type.unescape(), + GetSize(input_sig), fsm_cell->module, fsm_cell); if (GetSize(fsm_data.transition_table) > 10000) log_warning("Transition table for FSM %s.%s already has %d rows, merging more cells " - "into this FSM might be problematic.\n", log_id(fsm_cell->module), log_id(fsm_cell), + "into this FSM might be problematic.\n", fsm_cell->module, fsm_cell, GetSize(fsm_data.transition_table)); std::vector new_transition_table; diff --git a/passes/fsm/fsm_export.cc b/passes/fsm/fsm_export.cc index 7c79a53cc..1b06b18c2 100644 --- a/passes/fsm/fsm_export.cc +++ b/passes/fsm/fsm_export.cc @@ -64,7 +64,7 @@ void write_kiss2(struct RTLIL::Module *module, struct RTLIL::Cell *cell, std::st kiss_name.assign(attr_it->second.decode_string()); } else { - kiss_name.assign(log_id(module) + std::string("-") + log_id(cell) + ".kiss2"); + kiss_name.assign(module->name.unescape() + std::string("-") + cell->name.unescape() + ".kiss2"); } log("\n"); diff --git a/passes/fsm/fsm_info.cc b/passes/fsm/fsm_info.cc index ff3714021..7b3b59ee9 100644 --- a/passes/fsm/fsm_info.cc +++ b/passes/fsm/fsm_info.cc @@ -50,7 +50,7 @@ struct FsmInfoPass : public Pass { for (auto cell : mod->selected_cells()) if (cell->type == ID($fsm)) { log("\n"); - log("FSM `%s' from module `%s':\n", log_id(cell), log_id(mod)); + log("FSM `%s' from module `%s':\n", cell, mod); FsmData fsm_data; fsm_data.copy_from_cell(cell); fsm_data.log_info(cell); diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc index e4cd53a07..b32c01c39 100644 --- a/passes/fsm/fsm_recode.cc +++ b/passes/fsm/fsm_recode.cc @@ -96,7 +96,7 @@ static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fs log_error("FSM encoding `%s' is not supported!\n", encoding); if (encfile) - fprintf(encfile, ".fsm %s %s\n", log_id(module), RTLIL::unescape_id(cell->parameters[ID::NAME].decode_string()).c_str()); + fprintf(encfile, ".fsm %s %s\n", module->name.unescape().c_str(), RTLIL::unescape_id(cell->parameters[ID::NAME].decode_string()).c_str()); int state_idx_counter = fsm_data.reset_state >= 0 ? 1 : 0; for (int i = 0; i < int(fsm_data.state_table.size()); i++) diff --git a/passes/hierarchy/flatten.cc b/passes/hierarchy/flatten.cc index 17bd6e340..2dd20302c 100644 --- a/passes/hierarchy/flatten.cc +++ b/passes/hierarchy/flatten.cc @@ -149,7 +149,7 @@ struct FlattenWorker hier_wire->attributes.erase(ID::hierconn); if (GetSize(hier_wire) < GetSize(tpl_wire)) { log_warning("Widening signal %s.%s to match size of %s.%s (via %s.%s).\n", - log_id(module), log_id(hier_wire), log_id(tpl), log_id(tpl_wire), log_id(module), log_id(cell)); + module, hier_wire, tpl, tpl_wire, module, cell); hier_wire->width = GetSize(tpl_wire); } new_wire = hier_wire; @@ -261,7 +261,7 @@ struct FlattenWorker if (sigmap(new_conn.first).has_const()) log_error("Cell port %s.%s.%s is driving constant bits: %s <= %s\n", - log_id(module), log_id(cell), log_id(port_it.first), log_signal(new_conn.first), log_signal(new_conn.second)); + module, cell, port_it.first.unescape(), log_signal(new_conn.first), log_signal(new_conn.second)); module->connect(new_conn); sigmap.add(new_conn.first, new_conn.second); @@ -316,12 +316,12 @@ struct FlattenWorker continue; if (cell->get_bool_attribute(ID::keep_hierarchy) || tpl->get_bool_attribute(ID::keep_hierarchy)) { - log("Keeping %s.%s (found keep_hierarchy attribute).\n", log_id(module), log_id(cell)); + log("Keeping %s.%s (found keep_hierarchy attribute).\n", module, cell); used_modules.insert(tpl); continue; } - log_debug("Flattening %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log_debug("Flattening %s.%s (%s).\n", module, cell, cell->type.unescape()); // If a design is fully selected and has a top module defined, topological sorting ensures that all cells // added during flattening are black boxes, and flattening is finished in one pass. However, when flattening // individual modules, this isn't the case, and the newly added cells might have to be flattened further. @@ -443,7 +443,7 @@ struct FlattenPass : public Pass { if (cleanup && top != nullptr) for (auto module : design->modules().to_vector()) if (!used_modules[module] && !module->get_blackbox_attribute(worker.ignore_wb)) { - log("Deleting now unused module %s.\n", log_id(module)); + log("Deleting now unused module %s.\n", module); design->remove(module); } diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 416997bee..67475eda0 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -225,7 +225,7 @@ struct IFExpander // about it and don't set has_interfaces_not_found (to avoid a // loop). log_warning("Could not find interface instance for `%s' in `%s'\n", - log_id(interface_name), log_id(&module)); + interface_name.unescape(), &module); } // Handle an interface connection from the module @@ -268,12 +268,12 @@ struct IFExpander // Go over all wires in interface, and add replacements to lists. for (auto mod_wire : mod_replace_ports->wires()) { - std::string signal_name1 = conn_name.str() + "." + log_id(mod_wire->name); - std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire); + std::string signal_name1 = conn_name.str() + "." + mod_wire->name.unescape(); + std::string signal_name2 = interface_name.str() + "." + mod_wire->name.unescape(); connections_to_add_name.push_back(RTLIL::IdString(signal_name1)); if(module.wire(signal_name2) == nullptr) { log_error("Could not find signal '%s' in '%s'\n", - signal_name2.c_str(), log_id(module.name)); + signal_name2.c_str(), module.name.unescape()); } else { RTLIL::Wire *wire_in_parent = module.wire(signal_name2); @@ -432,7 +432,7 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI if (id <= 0 || id > GetSize(mod.ports)) log_error("Module `%s' referenced in module `%s' in cell `%s' " "has only %d ports, requested port %d.\n", - log_id(cell.type), log_id(&module), log_id(&cell), + cell.type.unescape(), &module, &cell, GetSize(mod.ports), id); continue; } @@ -441,8 +441,8 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI if (!wire || wire->port_id == 0) { log_error("Module `%s' referenced in module `%s' in cell `%s' " "does not have a port named '%s'.\n", - log_id(cell.type), log_id(&module), log_id(&cell), - log_id(conn.first)); + cell.type.unescape(), &module, &cell, + conn.first.unescape()); } } for (auto ¶m : cell.parameters) { @@ -450,7 +450,7 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI if (id <= 0 || id > GetSize(mod.avail_parameters)) log_error("Module `%s' referenced in module `%s' in cell `%s' " "has only %d parameters, requested parameter %d.\n", - log_id(cell.type), log_id(&module), log_id(&cell), + cell.type.unescape(), &module, &cell, GetSize(mod.avail_parameters), id); continue; } @@ -460,8 +460,8 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI strchr(param.first.c_str(), '.') == NULL) { log_error("Module `%s' referenced in module `%s' in cell `%s' " "does not have a parameter named '%s'.\n", - log_id(cell.type), log_id(&module), log_id(&cell), - log_id(param.first)); + cell.type.unescape(), &module, &cell, + param.first.unescape()); } } } @@ -1036,7 +1036,7 @@ struct HierarchyPass : public Pass { if (top_mod == nullptr) for (auto mod : design->modules()) if (mod->get_bool_attribute(ID::top)) { - log("Attribute `top' found on module `%s'. Setting top module to %s.\n", log_id(mod), log_id(mod)); + log("Attribute `top' found on module `%s'. Setting top module to %s.\n", mod, mod); top_mod = mod; } @@ -1057,12 +1057,12 @@ struct HierarchyPass : public Pass { dict db; for (Module *mod : design->selected_modules()) { int score = find_top_mod_score(design, mod, db); - log("root of %3d design levels: %-20s\n", score, log_id(mod)); + log("root of %3d design levels: %-20s\n", score, mod); if (!top_mod || score > db[top_mod]) top_mod = mod; } if (top_mod != nullptr) - log("Automatically selected %s as design top module.\n", log_id(top_mod)); + log("Automatically selected %s as design top module.\n", top_mod); } if (top_mod != nullptr && top_mod->name.begins_with("$abstract")) { @@ -1162,7 +1162,7 @@ struct HierarchyPass : public Pass { std::map cache; for (auto mod : design->modules()) if (set_keep_print(cache, mod)) { - log("Module %s directly or indirectly displays text -> setting \"keep\" attribute.\n", log_id(mod)); + log("Module %s directly or indirectly displays text -> setting \"keep\" attribute.\n", mod); mod->set_bool_attribute(ID::keep); } } @@ -1171,7 +1171,7 @@ struct HierarchyPass : public Pass { std::map cache; for (auto mod : design->modules()) if (set_keep_assert(cache, mod)) { - log("Module %s directly or indirectly contains formal properties -> setting \"keep\" attribute.\n", log_id(mod)); + log("Module %s directly or indirectly contains formal properties -> setting \"keep\" attribute.\n", mod); mod->set_bool_attribute(ID::keep); } } @@ -1190,7 +1190,7 @@ struct HierarchyPass : public Pass { src += ": "; log_error("%sProperty `%s' in module `%s' uses unsupported SVA constructs. See frontend warnings for details, run `chformal -remove a:unsupported_sva' to ignore.\n", - src, log_id(cell->name), log_id(mod->name)); + src, cell->name.unescape(), mod->name.unescape()); } } } @@ -1499,7 +1499,7 @@ struct HierarchyPass : public Pass { bool resize_widths = !keep_portwidths && GetSize(w) != GetSize(conn.second); if (resize_widths && verific_mod && boxed_params) log_debug("Ignoring width mismatch on %s.%s.%s from verific, is port width parametrizable?\n", - log_id(module), log_id(cell), log_id(conn.first) + module, cell, conn.first.unescape() ); else if (resize_widths) { if (GetSize(w) < GetSize(conn.second)) @@ -1523,14 +1523,14 @@ struct HierarchyPass : public Pass { } if (!conn.second.is_fully_const() || !w->port_input || w->port_output) - log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", log_id(module), log_id(cell), - log_id(conn.first), GetSize(conn.second), GetSize(sig)); + log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", module, cell, + conn.first.unescape(), GetSize(conn.second), GetSize(sig)); cell->setPort(conn.first, sig); } if (w->port_output && !w->port_input && sig.has_const()) log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n", - log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig)); + module, cell, conn.first.unescape(), cell->type.unescape(), log_signal(sig)); } } } diff --git a/passes/hierarchy/keep_hierarchy.cc b/passes/hierarchy/keep_hierarchy.cc index 9d77b5239..aa3ac72e3 100644 --- a/passes/hierarchy/keep_hierarchy.cc +++ b/passes/hierarchy/keep_hierarchy.cc @@ -42,7 +42,7 @@ struct ThresholdHierarchyKeeping { return 0; if (module->get_blackbox_attribute()) - log_error("Missing cost information on instanced blackbox %s\n", log_id(module)); + log_error("Missing cost information on instanced blackbox %s\n", module); if (done.count(module)) return done.at(module); @@ -61,13 +61,13 @@ struct ThresholdHierarchyKeeping { RTLIL::Module *submodule = design->module(cell->type); if (!submodule) log_error("Hierarchy contains unknown module '%s' (instanced as %s in %s)\n", - log_id(cell->type), log_id(cell), log_id(module)); + cell->type.unescape(), cell, module); size += visit(submodule); } } if (size > threshold) { - log("Keeping %s (estimated size above threshold: %" PRIu64 " > %" PRIu64 ").\n", log_id(module), size, threshold); + log("Keeping %s (estimated size above threshold: %" PRIu64 " > %" PRIu64 ").\n", module, size, threshold); module->set_bool_attribute(ID::keep_hierarchy); size = 0; } @@ -124,7 +124,7 @@ struct KeepHierarchyPass : public Pass { worker.visit(top); } else { for (auto module : design->selected_modules()) { - log("Marking %s.\n", log_id(module)); + log("Marking %s.\n", module); module->set_bool_attribute(ID::keep_hierarchy); } } diff --git a/passes/hierarchy/uniquify.cc b/passes/hierarchy/uniquify.cc index 49b59c8df..941f4dce8 100644 --- a/passes/hierarchy/uniquify.cc +++ b/passes/hierarchy/uniquify.cc @@ -71,7 +71,7 @@ struct UniquifyPass : public Pass { for (auto cell : module->selected_cells()) { Module *tmod = design->module(cell->type); - IdString newname = module->name.str() + "." + log_id(cell->name); + IdString newname = module->name.str() + "." + cell->name.unescape(); if (tmod == nullptr) continue; @@ -82,14 +82,14 @@ struct UniquifyPass : public Pass { if (tmod->get_bool_attribute(ID::unique) && newname == tmod->name) continue; - log("Creating module %s from %s.\n", log_id(newname), log_id(tmod)); + log("Creating module %s from %s.\n", newname.unescape(), tmod); auto smod = tmod->clone(); smod->name = newname; cell->type = newname; smod->set_bool_attribute(ID::unique); if (smod->attributes.count(ID::hdlname) == 0) - smod->attributes[ID::hdlname] = string(log_id(tmod->name)); + smod->attributes[ID::hdlname] = string(tmod->name.unescape()); design->add(smod); did_something = true; diff --git a/passes/memory/memlib.md b/passes/memory/memlib.md index f3c0dd937..5ad3f7777 100644 --- a/passes/memory/memlib.md +++ b/passes/memory/memlib.md @@ -310,7 +310,7 @@ The port clock is always provided on the memory cell as `PORT__CLK` signal (even if it is also shared). Shared clocks are also provided as `CLK_` signals. -For `anyedge` clocks, the cell gets a `PORT__CLKPOL` parameter that is set +For `anyedge` clocks, the cell gets a `PORT__CLK_POL` parameter that is set to 1 for `posedge` clocks and 0 for `negedge` clocks. If the clock is shared, the same information will also be provided as `CLK__POL` parameter. diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 10301b44a..833aa634b 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -44,7 +44,7 @@ struct rules_t void dump_config() const { - log(" bram %s # variant %d\n", log_id(name), variant); + log(" bram %s # variant %d\n", name.unescape(), variant); log(" init %d\n", init); log(" abits %d\n", abits); log(" dbits %d\n", dbits); @@ -61,16 +61,16 @@ struct rules_t void check_vectors() const { - if (groups != GetSize(ports)) log_error("Bram %s variant %d has %d groups but only %d entries in 'ports'.\n", log_id(name), variant, groups, GetSize(ports)); - if (groups != GetSize(wrmode)) log_error("Bram %s variant %d has %d groups but only %d entries in 'wrmode'.\n", log_id(name), variant, groups, GetSize(wrmode)); - if (groups != GetSize(enable)) log_error("Bram %s variant %d has %d groups but only %d entries in 'enable'.\n", log_id(name), variant, groups, GetSize(enable)); - if (groups != GetSize(transp)) log_error("Bram %s variant %d has %d groups but only %d entries in 'transp'.\n", log_id(name), variant, groups, GetSize(transp)); - if (groups != GetSize(clocks)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clocks'.\n", log_id(name), variant, groups, GetSize(clocks)); - if (groups != GetSize(clkpol)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clkpol'.\n", log_id(name), variant, groups, GetSize(clkpol)); + if (groups != GetSize(ports)) log_error("Bram %s variant %d has %d groups but only %d entries in 'ports'.\n", name.unescape(), variant, groups, GetSize(ports)); + if (groups != GetSize(wrmode)) log_error("Bram %s variant %d has %d groups but only %d entries in 'wrmode'.\n", name.unescape(), variant, groups, GetSize(wrmode)); + if (groups != GetSize(enable)) log_error("Bram %s variant %d has %d groups but only %d entries in 'enable'.\n", name.unescape(), variant, groups, GetSize(enable)); + if (groups != GetSize(transp)) log_error("Bram %s variant %d has %d groups but only %d entries in 'transp'.\n", name.unescape(), variant, groups, GetSize(transp)); + if (groups != GetSize(clocks)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clocks'.\n", name.unescape(), variant, groups, GetSize(clocks)); + if (groups != GetSize(clkpol)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clkpol'.\n", name.unescape(), variant, groups, GetSize(clkpol)); int group = 0; for (auto e : enable) - if (e > dbits) log_error("Bram %s variant %d group %d has %d enable bits but only %d dbits.\n", log_id(name), variant, group, e, dbits); + if (e > dbits) log_error("Bram %s variant %d group %d has %d enable bits but only %d dbits.\n", name.unescape(), variant, group, e, dbits); } vector make_portinfos() const @@ -100,7 +100,7 @@ struct rules_t log_assert(name == other.name); if (groups != other.groups) - log_error("Bram %s variants %d and %d have different values for 'groups'.\n", log_id(name), variant, other.variant); + log_error("Bram %s variants %d and %d have different values for 'groups'.\n", name.unescape(), variant, other.variant); if (abits != other.abits) variant_params[ID::CFG_ABITS] = abits; @@ -112,7 +112,7 @@ struct rules_t for (int i = 0; i < groups; i++) { if (ports[i] != other.ports[i]) - log_error("Bram %s variants %d and %d have different number of %c-ports.\n", log_id(name), variant, other.variant, 'A'+i); + log_error("Bram %s variants %d and %d have different number of %c-ports.\n", name.unescape(), variant, other.variant, 'A'+i); if (wrmode[i] != other.wrmode[i]) variant_params[stringf("\\CFG_WRMODE_%c", 'A' + i)] = wrmode[i]; if (enable[i] != other.enable[i]) @@ -428,7 +428,7 @@ bool replace_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals, const transp_max = max(transp_max, pi.transp); } - log(" Mapping to bram type %s (variant %d):\n", log_id(bram.name), bram.variant); + log(" Mapping to bram type %s (variant %d):\n", bram.name.unescape(), bram.variant); // bram.dump_config(); std::vector shuffle_map; @@ -715,21 +715,21 @@ grow_read_ports:; for (auto it : match.min_limits) { if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); + it.first.c_str(), match.name.unescape()); if (match_properties[it.first] >= it.second) continue; log(" Rule for bram type %s rejected: requirement 'min %s %d' not met.\n", - log_id(match.name), it.first.c_str(), it.second); + match.name.unescape(), it.first.c_str(), it.second); return false; } for (auto it : match.max_limits) { if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); + it.first.c_str(), match.name.unescape()); if (match_properties[it.first] <= it.second) continue; log(" Rule for bram type %s rejected: requirement 'max %s %d' not met.\n", - log_id(match.name), it.first.c_str(), it.second); + match.name.unescape(), it.first.c_str(), it.second); return false; } @@ -759,13 +759,13 @@ grow_read_ports:; if (!exists) ss << "!"; IdString key = std::get<1>(sums.front()); - ss << log_id(key); + ss << key.unescape(); const Const &value = rules.map_case(std::get<2>(sums.front())); if (exists && value != Const(1)) ss << "=\"" << value.decode_string() << "\""; log(" Rule for bram type %s rejected: requirement 'attribute %s ...' not met.\n", - log_id(match.name), ss.str().c_str()); + match.name.unescape(), ss.str().c_str()); return false; } } @@ -874,7 +874,7 @@ grow_read_ports:; for (int dupidx = 0; dupidx < dup_count; dupidx++) { Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", mem.memid, grid_d, grid_a, dupidx)), bram.name); - log(" Creating %s cell at grid position <%d %d %d>: %s\n", log_id(bram.name), grid_d, grid_a, dupidx, log_id(c)); + log(" Creating %s cell at grid position <%d %d %d>: %s\n", bram.name.unescape(), grid_d, grid_a, dupidx, c); for (auto &vp : variant_params) c->setParam(vp.first, vp.second); @@ -1004,7 +1004,7 @@ grow_read_ports:; void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) { - log("Processing %s.%s:\n", log_id(mem.module), log_id(mem.memid)); + log("Processing %s.%s:\n", mem.module, mem.memid.unescape()); mem.narrow(); bool cell_init = !mem.inits.empty(); @@ -1031,7 +1031,7 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) auto &match = rules.matches.at(i); if (!rules.brams.count(rules.matches[i].name)) - log_error("No bram description for resource %s found!\n", log_id(rules.matches[i].name)); + log_error("No bram description for resource %s found!\n", rules.matches[i].name.unescape()); for (int vi = 0; vi < GetSize(rules.brams.at(match.name)); vi++) { @@ -1047,7 +1047,7 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) avail_wr_ports += GetSize(bram.ports) < j ? bram.ports.at(j) : 0; } - log(" Checking rule #%d for bram type %s (variant %d):\n", i+1, log_id(bram.name), bram.variant); + log(" Checking rule #%d for bram type %s (variant %d):\n", i+1, bram.name.unescape(), bram.variant); log(" Bram geometry: abits=%d dbits=%d wports=%d rports=%d\n", bram.abits, bram.dbits, avail_wr_ports, avail_rd_ports); int dups = avail_rd_ports ? (match_properties["rports"] + avail_rd_ports - 1) / avail_rd_ports : 1; @@ -1077,11 +1077,11 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) goto next_match_rule; log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n", - log_id(match.name), awaste, dwaste, bwaste, waste, efficiency); + match.name.unescape(), awaste, dwaste, bwaste, waste, efficiency); if (cell_init && bram.init == 0) { log(" Rule #%d for bram type %s (variant %d) rejected: cannot be initialized.\n", - i+1, log_id(bram.name), bram.variant); + i+1, bram.name.unescape(), bram.variant); goto next_match_rule; } @@ -1090,11 +1090,11 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) continue; if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); + it.first.c_str(), match.name.unescape()); if (match_properties[it.first] >= it.second) continue; log(" Rule #%d for bram type %s (variant %d) rejected: requirement 'min %s %d' not met.\n", - i+1, log_id(bram.name), bram.variant, it.first.c_str(), it.second); + i+1, bram.name.unescape(), bram.variant, it.first.c_str(), it.second); goto next_match_rule; } @@ -1103,11 +1103,11 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) continue; if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); + it.first.c_str(), match.name.unescape()); if (match_properties[it.first] <= it.second) continue; log(" Rule #%d for bram type %s (variant %d) rejected: requirement 'max %s %d' not met.\n", - i+1, log_id(bram.name), bram.variant, it.first.c_str(), it.second); + i+1, bram.name.unescape(), bram.variant, it.first.c_str(), it.second); goto next_match_rule; } @@ -1137,18 +1137,18 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) if (!exists) ss << "!"; IdString key = std::get<1>(sums.front()); - ss << log_id(key); + ss << key.unescape(); const Const &value = rules.map_case(std::get<2>(sums.front())); if (exists && value != Const(1)) ss << "=\"" << value.decode_string() << "\""; log(" Rule for bram type %s (variant %d) rejected: requirement 'attribute %s ...' not met.\n", - log_id(bram.name), bram.variant, ss.str().c_str()); + bram.name.unescape(), bram.variant, ss.str().c_str()); goto next_match_rule; } } - log(" Rule #%d for bram type %s (variant %d) accepted.\n", i+1, log_id(bram.name), bram.variant); + log(" Rule #%d for bram type %s (variant %d) accepted.\n", i+1, bram.name.unescape(), bram.variant); if (or_next_if_better || !best_rule_cache.empty()) { @@ -1156,7 +1156,7 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) log_error("Found 'or_next_if_better' in last match rule.\n"); if (!replace_memory(mem, rules, initvals, bram, match, match_properties, 1)) { - log(" Mapping to bram type %s failed.\n", log_id(match.name)); + log(" Mapping to bram type %s failed.\n", match.name.unescape()); failed_brams.insert(pair(bram.name, bram.variant)); goto next_match_rule; } @@ -1183,12 +1183,12 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) auto &best_bram = rules.brams.at(rules.matches.at(best_rule.first).name).at(best_rule.second); if (!replace_memory(mem, rules, initvals, best_bram, rules.matches.at(best_rule.first), match_properties, 2)) - log_error("Mapping to bram type %s (variant %d) after pre-selection failed.\n", log_id(best_bram.name), best_bram.variant); + log_error("Mapping to bram type %s (variant %d) after pre-selection failed.\n", best_bram.name.unescape(), best_bram.variant); return; } if (!replace_memory(mem, rules, initvals, bram, match, match_properties, 0)) { - log(" Mapping to bram type %s failed.\n", log_id(match.name)); + log(" Mapping to bram type %s failed.\n", match.name.unescape()); failed_brams.insert(pair(bram.name, bram.variant)); goto next_match_rule; } diff --git a/passes/memory/memory_libmap.cc b/passes/memory/memory_libmap.cc index 87adaa26d..a7be16577 100644 --- a/passes/memory/memory_libmap.cc +++ b/passes/memory/memory_libmap.cc @@ -204,7 +204,7 @@ struct MemMapping { if (!check_init(rdef)) continue; if (rdef.prune_rom && mem.wr_ports.empty()) { - log_debug("memory %s.%s: rejecting mapping to %s: ROM mapping disabled (prune_rom set)\n", log_id(mem.module->name), log_id(mem.memid), log_id(rdef.id)); + log_debug("memory %s.%s: rejecting mapping to %s: ROM mapping disabled (prune_rom set)\n", mem.module->name.unescape(), mem.memid.unescape(), rdef.id.unescape()); continue; } MemConfig cfg; @@ -323,7 +323,7 @@ struct MemMapping { void log_reject(const Ram &ram, std::string message) { if(ys_debug(1)) { - rejected_cfg_debug_msgs += stringf("can't map to to %s: ", log_id(ram.id)); + rejected_cfg_debug_msgs += stringf("can't map to to %s: ", ram.id.unescape()); rejected_cfg_debug_msgs += message; rejected_cfg_debug_msgs += "\n"; } @@ -338,7 +338,7 @@ struct MemMapping { rejected_cfg_debug_msgs += portname; first = false; } - rejected_cfg_debug_msgs += stringf("] of %s: ", log_id(ram.id)); + rejected_cfg_debug_msgs += stringf("] of %s: ", ram.id.unescape()); rejected_cfg_debug_msgs += message; rejected_cfg_debug_msgs += "\n"; } @@ -361,7 +361,7 @@ struct MemMapping { rejected_cfg_debug_msgs += portname; first = false; } - rejected_cfg_debug_msgs += stringf("] of %s: ", log_id(ram.id)); + rejected_cfg_debug_msgs += stringf("] of %s: ", ram.id.unescape()); rejected_cfg_debug_msgs += message; rejected_cfg_debug_msgs += "\n"; } @@ -380,7 +380,7 @@ void MemMapping::dump_configs(int stage) { default: abort(); } - log_debug("Memory %s.%s mapping candidates (%s):\n", log_id(mem.module->name), log_id(mem.memid), stage_name); + log_debug("Memory %s.%s mapping candidates (%s):\n", mem.module->name.unescape(), mem.memid.unescape(), stage_name); if (logic_ok) { log_debug("- logic fallback\n"); log_debug(" - cost: %f\n", logic_cost); @@ -391,7 +391,7 @@ void MemMapping::dump_configs(int stage) { } void MemMapping::dump_config(MemConfig &cfg) { - log_debug("- %s:\n", log_id(cfg.def->id)); + log_debug("- %s:\n", cfg.def->id.unescape()); for (auto &it: cfg.def->options) log_debug(" - option %s %s\n", it.first, log_const(it.second)); log_debug(" - emulation score: %d\n", cfg.score_emu); @@ -527,7 +527,7 @@ void MemMapping::determine_style() { auto find_attr = search_for_attribute(mem, ID::lram); if (find_attr.first && find_attr.second.as_bool()) { kind = RamKind::Huge; - log("found attribute 'lram' on memory %s.%s, forced mapping to huge RAM\n", log_id(mem.module->name), log_id(mem.memid)); + log("found attribute 'lram' on memory %s.%s, forced mapping to huge RAM\n", mem.module->name.unescape(), mem.memid.unescape()); return; } for (auto attr: {ID::ram_block, ID::rom_block, ID::ram_style, ID::rom_style, ID::ramstyle, ID::romstyle, ID::syn_ramstyle, ID::syn_romstyle}) { @@ -536,7 +536,7 @@ void MemMapping::determine_style() { Const val = find_attr.second; if (val == 1) { kind = RamKind::NotLogic; - log("found attribute '%s = 1' on memory %s.%s, disabled mapping to FF\n", log_id(attr), log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = 1' on memory %s.%s, disabled mapping to FF\n", attr.unescape(), mem.module->name.unescape(), mem.memid.unescape()); return; } std::string val_s = val.decode_string(); @@ -549,20 +549,20 @@ void MemMapping::determine_style() { // Nothing. } else if (val_s == "logic" || val_s == "registers") { kind = RamKind::Logic; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to FF\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to FF\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); } else if (val_s == "distributed") { kind = RamKind::Distributed; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to distributed RAM\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to distributed RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); } else if (val_s == "block" || val_s == "block_ram" || val_s == "ebr") { kind = RamKind::Block; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to block RAM\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to block RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); } else if (val_s == "huge" || val_s == "ultra") { kind = RamKind::Huge; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to huge RAM\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to huge RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); } else { kind = RamKind::NotLogic; style = val_s; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to %s RAM\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid), val_s); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to %s RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape(), val_s); } return; } @@ -1991,7 +1991,7 @@ void MemMapping::emit_port(const MemConfig &cfg, std::vector &cells, cons } void MemMapping::emit(const MemConfig &cfg) { - log("mapping memory %s.%s via %s\n", log_id(mem.module->name), log_id(mem.memid), log_id(cfg.def->id)); + log("mapping memory %s.%s via %s\n", mem.module->name.unescape(), mem.memid.unescape(), cfg.def->id.unescape()); // First, handle emulations. if (cfg.emu_read_first) mem.emulate_read_first(&worker.initvals); @@ -2252,9 +2252,9 @@ struct MemoryLibMapPass : public Pass { int best = map.logic_cost; if (!map.logic_ok) { if (map.cfgs.empty()) { - log_debug("Rejected candidates for mapping memory %s.%s:\n", log_id(module->name), log_id(mem.memid)); + log_debug("Rejected candidates for mapping memory %s.%s:\n", module->name.unescape(), mem.memid.unescape()); log_debug("%s", map.rejected_cfg_debug_msgs); - log_error("no valid mapping found for memory %s.%s\n", log_id(module->name), log_id(mem.memid)); + log_error("no valid mapping found for memory %s.%s\n", module->name.unescape(), mem.memid.unescape()); } idx = 0; best = map.cfgs[0].cost; @@ -2266,7 +2266,7 @@ struct MemoryLibMapPass : public Pass { } } if (idx == -1) { - log("using FF mapping for memory %s.%s\n", log_id(module->name), log_id(mem.memid)); + log("using FF mapping for memory %s.%s\n", module->name.unescape(), mem.memid.unescape()); } else { map.emit(map.cfgs[idx]); // Rebuild indices after modifying module diff --git a/passes/memory/memory_memx.cc b/passes/memory/memory_memx.cc index 22aebb43f..54c71a0e8 100644 --- a/passes/memory/memory_memx.cc +++ b/passes/memory/memory_memx.cc @@ -60,7 +60,7 @@ struct MemoryMemxPass : public Pass { { if (port.clk_enable) log_error("Memory %s.%s has a synchronous read port. Synchronous read ports are not supported by memory_memx!\n", - log_id(module), log_id(mem.memid)); + module, mem.memid.unescape()); SigSpec addr_ok = make_addr_check(mem, port.addr); Wire *raw_rdata = module->addWire(NEW_ID, GetSize(port.data)); diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc index fe884772a..fbe41431a 100644 --- a/passes/memory/memory_share.cc +++ b/passes/memory/memory_share.cc @@ -80,7 +80,7 @@ struct MemoryShareWorker if (GetSize(mem.rd_ports) <= 1) return false; - log("Consolidating read ports of memory %s.%s by address:\n", log_id(module), log_id(mem.memid)); + log("Consolidating read ports of memory %s.%s by address:\n", module, mem.memid.unescape()); bool changed = false; int abits = 0; @@ -197,7 +197,7 @@ struct MemoryShareWorker if (GetSize(mem.wr_ports) <= 1) return false; - log("Consolidating write ports of memory %s.%s by address:\n", log_id(module), log_id(mem.memid)); + log("Consolidating write ports of memory %s.%s by address:\n", module, mem.memid.unescape()); bool changed = false; int abits = 0; @@ -316,7 +316,7 @@ struct MemoryShareWorker if (eligible_ports.size() <= 1) return; - log("Consolidating write ports of memory %s.%s using sat-based resource sharing:\n", log_id(module), log_id(mem.memid)); + log("Consolidating write ports of memory %s.%s using sat-based resource sharing:\n", module, mem.memid.unescape()); // Group eligible ports by clock domain and width. diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index ac47f6bf7..773bbfde9 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -193,7 +193,7 @@ struct MuxpackWorker { for (auto cell : candidate_cells) { - log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); + log_debug("Considering %s (%s)\n", cell, cell->type.unescape()); SigSpec a_sig = sigmap(cell->getPort(ID::A)); if (cell->type == ID($mux)) { @@ -263,7 +263,6 @@ struct MuxpackWorker int cases = GetSize(chain) - cursor; Cell *first_cell = chain[cursor]; - dict taps_dict; if (cases < 2) { cursor++; @@ -273,7 +272,7 @@ struct MuxpackWorker Cell *last_cell = chain[cursor+cases-1]; log("Converting %s.%s ... %s.%s to a pmux with %d cases.\n", - log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), cases); + module, first_cell, module, last_cell, cases); mux_count += cases; pmux_count += 1; diff --git a/passes/opt/opt_balance_tree.cc b/passes/opt/opt_balance_tree.cc index 129a27376..98d5b9928 100644 --- a/passes/opt/opt_balance_tree.cc +++ b/passes/opt/opt_balance_tree.cc @@ -279,7 +279,7 @@ struct OptBalanceTreeWorker { if (inner_cells) { // Create a tree - log_debug(" Creating tree for %s with %d sources and %d inner cells...\n", log_id(head_cell), GetSize(sources), inner_cells); + log_debug(" Creating tree for %s with %d sources and %d inner cells...\n", head_cell, GetSize(sources), inner_cells); // Build a vector of all source signals vector source_signals; @@ -369,7 +369,7 @@ struct OptBalanceTreePass : public Pass { // Log stats for (auto cell_type : cell_types) - log("Converted %d %s cells into trees.\n", cell_count[cell_type], log_id(cell_type)); + log("Converted %d %s cells into trees.\n", cell_count[cell_type], cell_type.unescape()); // Clean up Yosys::run_pass("clean -purge"); diff --git a/passes/opt/opt_clean/inits.cc b/passes/opt/opt_clean/inits.cc index 70c2ef9e2..0618e739a 100644 --- a/passes/opt/opt_clean/inits.cc +++ b/passes/opt/opt_clean/inits.cc @@ -109,7 +109,7 @@ bool remove_redundant_inits(ShardedVector wires, bool verbose) { bool did_something = false; for (RTLIL::Wire *wire : wires) { if (verbose) - log_debug(" removing redundant init attribute on %s.\n", log_id(wire)); + log_debug(" removing redundant init attribute on %s.\n", wire); wire->attributes.erase(ID::init); did_something = true; } diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc index 1a2c1fe82..b9aab1850 100644 --- a/passes/opt/opt_demorgan.cc +++ b/passes/opt/opt_demorgan.cc @@ -43,7 +43,7 @@ void demorgan_worker( if (GetSize(insig) < 1) return; - log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig)); + log("Inspecting %s cell %s (%d inputs)\n", cell->type.unescape(), cell->name.unescape(), GetSize(insig)); int num_inverted = 0; for(int i=0; iconnect(ff.sig_q[i], State::S0); log("Handling always-active CLR at position %d on %s (%s) from module %s (changing to const driver).\n", - i, log_id(cell), log_id(cell->type), log_id(module)); + i, cell, cell->type.unescape(), module); sr_removed = true; } else if (is_always_active(ff.sig_set[i], ff.pol_set)) { initvals.remove_init(ff.sig_q[i]); @@ -312,7 +312,7 @@ struct OptDffWorker else module->addNot(NEW_ID, ff.sig_clr[i], ff.sig_q[i]); log("Handling always-active SET at position %d on %s (%s) from module %s (changing to combinatorial circuit).\n", - i, log_id(cell), log_id(cell->type), log_id(module)); + i, cell, cell->type.unescape(), module); sr_removed = true; } else { keep_bits.push_back(i); @@ -335,7 +335,7 @@ struct OptDffWorker if (clr_inactive && signal_all_same(ff.sig_set)) { log("Removing never-active CLR on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_sr = false; ff.has_arst = true; ff.pol_arst = ff.pol_set; @@ -344,7 +344,7 @@ struct OptDffWorker changed = true; } else if (set_inactive && signal_all_same(ff.sig_clr)) { log("Removing never-active SET on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_sr = false; ff.has_arst = true; ff.pol_arst = ff.pol_clr; @@ -370,7 +370,7 @@ struct OptDffWorker if (!failed) { log("Converting CLR/SET to ARST on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_sr = false; ff.has_arst = true; ff.val_arst = val_arst_builder.build(); @@ -389,7 +389,7 @@ struct OptDffWorker // Converts constant Async Load to ARST if (is_always_inactive(ff.sig_aload, ff.pol_aload)) { log("Removing never-active async load on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_aload = false; changed = true; return false; @@ -398,7 +398,7 @@ struct OptDffWorker if (is_active(ff.sig_aload, ff.pol_aload)) { // ALOAD always active log("Handling always-active async load on %s (%s) from module %s (changing to combinatorial circuit).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.remove(); if (ff.has_sr) { @@ -433,7 +433,7 @@ struct OptDffWorker // AD is constant -> ARST if (ff.sig_ad.is_fully_const() && !ff.has_arst && !ff.has_sr) { log("Changing const-value async load to async reset on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_arst = true; ff.has_aload = false; ff.sig_arst = ff.sig_aload; @@ -450,12 +450,12 @@ struct OptDffWorker // Removes ARST if never active or replaces FF if always active if (is_inactive(ff.sig_arst, ff.pol_arst)) { log("Removing never-active ARST on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_arst = false; changed = true; } else if (is_always_active(ff.sig_arst, ff.pol_arst)) { log("Handling always-active ARST on %s (%s) from module %s (changing to const driver).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.remove(); module->connect(ff.sig_q, ff.val_arst); return true; @@ -469,12 +469,12 @@ struct OptDffWorker // Removes SRST if never active or forces D to reset value if always active if (is_inactive(ff.sig_srst, ff.pol_srst)) { log("Removing never-active SRST on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_srst = false; changed = true; } else if (is_always_active(ff.sig_srst, ff.pol_srst)) { log("Handling always-active SRST on %s (%s) from module %s (changing to const D).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_srst = false; if (!ff.ce_over_srst) ff.has_ce = false; @@ -489,7 +489,7 @@ struct OptDffWorker if (is_always_inactive(ff.sig_ce, ff.pol_ce)) { if (ff.has_srst && !ff.ce_over_srst) { log("Handling never-active EN on %s (%s) from module %s (connecting SRST instead).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.pol_ce = ff.pol_srst; ff.sig_ce = ff.sig_srst; ff.has_srst = false; @@ -497,7 +497,7 @@ struct OptDffWorker changed = true; } else if (!opt.keepdc || ff.val_init.is_fully_def()) { log("Handling never-active EN on %s (%s) from module %s (removing D path).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_ce = ff.has_clk = ff.has_srst = false; changed = true; } else { @@ -507,7 +507,7 @@ struct OptDffWorker } } else if (is_active(ff.sig_ce, ff.pol_ce)) { log("Removing always-active EN on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_ce = false; changed = true; } @@ -517,7 +517,7 @@ struct OptDffWorker { if (!opt.keepdc || ff.val_init.is_fully_def()) { log("Handling const CLK on %s (%s) from module %s (removing D path).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_ce = ff.has_clk = ff.has_srst = false; changed = true; } else if (ff.has_ce || ff.has_srst || ff.sig_d != ff.sig_q) { @@ -532,7 +532,7 @@ struct OptDffWorker // Detect feedback loops where D is hardwired to Q if (ff.has_clk && ff.has_srst) { log("Handling D = Q on %s (%s) from module %s (conecting SRST instead).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); if (ff.has_ce && ff.ce_over_srst) { SigSpec ce = ff.pol_ce ? ff.sig_ce : create_not(ff.sig_ce, ff.is_fine); SigSpec srst = ff.pol_srst ? ff.sig_srst : create_not(ff.sig_srst, ff.is_fine); @@ -549,7 +549,7 @@ struct OptDffWorker changed = true; } else if (!opt.keepdc || ff.val_init.is_fully_def()) { log("Handling D = Q on %s (%s) from module %s (removing D path).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_gclk = ff.has_clk = ff.has_ce = false; changed = true; } @@ -627,7 +627,7 @@ struct OptDffWorker dff_cells.push_back(new_cell); log("Adding SRST signal on %s (%s) from module %s (D = %s, Q = %s, rval = %s).\n", - log_id(cell), log_id(cell->type), log_id(module), + cell, cell->type.unescape(), module, log_signal(new_ff.sig_d), log_signal(new_ff.sig_q), log_signal(new_ff.val_srst)); } @@ -701,7 +701,7 @@ struct OptDffWorker dff_cells.push_back(new_cell); log("Adding EN signal on %s (%s) from module %s (D = %s, Q = %s).\n", - log_id(cell), log_id(cell->type), log_id(module), + cell, cell->type.unescape(), module, log_signal(new_ff.sig_d), log_signal(new_ff.sig_q)); } @@ -768,7 +768,7 @@ struct OptDffWorker if (ff.has_aload && !ff.has_clk && ff.sig_ad == ff.sig_q) { log("Handling AD = Q on %s (%s) from module %s (removing async load path).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_aload = false; changed = true; } @@ -885,7 +885,7 @@ struct OptDffWorker } log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", - val ? 1 : 0, i, log_id(cell), log_id(cell->type), log_id(module)); + val ? 1 : 0, i, cell, cell->type.unescape(), module); // Replace the Q output with the constant value initvals.remove_init(ff.sig_q[i]); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 2c040b09d..48a9aa1da 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -88,7 +88,7 @@ void replace_undriven(RTLIL::Module *module, const NewCellTypes &ct) } } - log_debug("Setting undriven signal in %s to constant: %s = %s\n", log_id(module), log_signal(sig), log_signal(val)); + log_debug("Setting undriven signal in %s to constant: %s = %s\n", module, log_signal(sig), log_signal(val)); module->connect(sig, val); did_something = true; } @@ -105,11 +105,11 @@ void replace_undriven(RTLIL::Module *module, const NewCellTypes &ct) initval.set(i, State::Sx); } if (initval.is_fully_undef()) { - log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire)); + log_debug("Removing init attribute from %s/%s.\n", module, wire); wire->attributes.erase(ID::init); did_something = true; } else if (initval != wire->attributes.at(ID::init)) { - log_debug("Updating init attribute on %s/%s: %s\n", log_id(module), log_id(wire), log_signal(initval)); + log_debug("Updating init attribute on %s/%s: %s\n", module, wire, log_signal(initval)); wire->attributes[ID::init] = initval; did_something = true; } @@ -196,7 +196,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ return false; log_debug("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n", - log_id(cell->type), log_id(cell), log_id(module)); + cell->type.unescape(), cell, module); for (int i = 0; i < GRP_N; i++) { @@ -224,7 +224,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ new_a.replace(dict{{State::Sx, State::S1}, {State::Sz, State::S1}}, &new_b); else log_abort(); } - log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a)); + log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), cell->type.unescape(), log_signal(new_a)); module->connect(new_y, new_b); module->connect(new_conn); continue; @@ -261,7 +261,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ } } if (!undef_y.empty()) { - log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(undef_b), log_id(cell->type), log_signal(undef_a)); + log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(undef_b), cell->type.unescape(), log_signal(undef_a)); module->connect(undef_y, undef_b); if (def_y.empty()) { module->connect(new_conn); @@ -292,7 +292,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ module->connect(new_conn); - log_debug(" New cell `%s': A=%s", log_id(c), log_signal(new_a)); + log_debug(" New cell `%s': A=%s", c, log_signal(new_a)); if (b_name == ID::B) log_debug(", B=%s", log_signal(new_b)); log_debug("\n"); @@ -308,7 +308,7 @@ void handle_polarity_inv(Cell *cell, IdString port, IdString param, const SigMap SigSpec sig = assign_map(cell->getPort(port)); if (invert_map.count(sig)) { log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", - log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module), + port.unescape(), cell->type.unescape(), cell, cell->module, log_signal(sig), log_signal(invert_map.at(sig))); cell->setPort(port, (invert_map.at(sig))); cell->setParam(param, !cell->getParam(param).as_bool()); @@ -337,7 +337,7 @@ void handle_clkpol_celltype_swap(Cell *cell, string type1, string type2, IdStrin SigSpec sig = assign_map(cell->getPort(port)); if (invert_map.count(sig)) { log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", - log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module), + port.unescape(), cell->type.unescape(), cell, cell->module, log_signal(sig), log_signal(invert_map.at(sig))); cell->setPort(port, (invert_map.at(sig))); cell->type = cell->type == type1 ? type2 : type1; @@ -511,7 +511,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (!cells.sort()) { // There might be a combinational loop, or there might be constants on the output of cells. 'check' may find out more. // ...unless this is a coarse-grained cell loop, but not a bit loop, in which case it won't, and all is good. - log("Couldn't topologically sort cells, optimizing module %s may take a longer time.\n", log_id(module)); + log("Couldn't topologically sort cells, optimizing module %s may take a longer time.\n", module); } for (auto cell : cells.sorted) @@ -631,7 +631,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { if (cell->type == ID($reduce_xnor)) { log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n", - log_id(cell->type), log_id(cell->name), log_id(module)); + cell->type.unescape(), cell->name.unescape(), module); cell->type = ID($not); did_something = true; } else { @@ -651,7 +651,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (a_fully_const != b_fully_const) { log_debug("Replacing %s cell `%s' in module `%s' having one fully constant input\n", - log_id(cell->type), log_id(cell->name), log_id(module)); + cell->type.unescape(), cell->name.unescape(), module); RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y)); int width = GetSize(cell->getPort(ID::Y)); @@ -932,7 +932,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons break; } if (i > 0) { - log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, cell->type.unescape(), cell, module); SigSpec new_a = sig_a.extract_end(i); SigSpec new_b = sig_b.extract_end(i); if (new_a.empty() && is_signed) @@ -988,7 +988,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons break; } if (i > 0) { - log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, cell->type.unescape(), cell, module); SigSpec new_a = sig_a.extract_end(i); SigSpec new_b = sig_b.extract_end(i); if (new_a.empty() && is_signed) @@ -1062,7 +1062,7 @@ skip_fine_alu: } if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID::S))) != 0) { - log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", cell->type.unescape(), cell, module); RTLIL::SigSpec tmp = cell->getPort(ID::A); cell->setPort(ID::A, cell->getPort(ID::B)); cell->setPort(ID::B, tmp); @@ -1241,7 +1241,7 @@ skip_fine_alu: RTLIL::SigSpec input = b; ACTION_DO(ID::Y, cell->getPort(ID::A)); } else { - log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", cell->type.unescape(), cell, module); cell->type = ID($not); cell->parameters.erase(ID::B_WIDTH); cell->parameters.erase(ID::B_SIGNED); @@ -1255,8 +1255,8 @@ skip_fine_alu: if (cell->type.in(ID($eq), ID($ne)) && (assign_map(cell->getPort(ID::A)).is_fully_zero() || assign_map(cell->getPort(ID::B)).is_fully_zero())) { - log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell), - log_id(module), cell->type == ID($eq) ? "$logic_not" : "$reduce_bool"); + log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", cell->type.unescape(), cell, + module, cell->type == ID($eq) ? "$logic_not" : "$reduce_bool"); cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool); if (assign_map(cell->getPort(ID::A)).is_fully_zero()) { cell->setPort(ID::A, cell->getPort(ID::B)); @@ -1303,7 +1303,7 @@ skip_fine_alu: } log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n", - log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort(ID::B))), shift_bits, log_id(module), log_signal(sig_y)); + cell->type.unescape(), cell, log_signal(assign_map(cell->getPort(ID::B))), shift_bits, module, log_signal(sig_y)); module->connect(cell->getPort(ID::Y), sig_y); module->remove(cell); @@ -1428,7 +1428,7 @@ skip_identity: if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == State::S1 && cell->getPort(ID::B) == State::S0) { - log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", cell->type.unescape(), cell, module); cell->setPort(ID::A, cell->getPort(ID::S)); cell->unsetPort(ID::B); cell->unsetPort(ID::S); @@ -1446,7 +1446,7 @@ skip_identity: } if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == State::S0) { - log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", cell->type.unescape(), cell, module); cell->setPort(ID::A, cell->getPort(ID::S)); cell->unsetPort(ID::S); if (cell->type == ID($mux)) { @@ -1465,7 +1465,7 @@ skip_identity: } if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::B) == State::S1) { - log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", cell->type.unescape(), cell, module); cell->setPort(ID::B, cell->getPort(ID::S)); cell->unsetPort(ID::S); if (cell->type == ID($mux)) { @@ -1515,7 +1515,7 @@ skip_identity: } if (cell->getPort(ID::S).size() != new_s.size()) { log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n", - GetSize(cell->getPort(ID::S)) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module)); + GetSize(cell->getPort(ID::S)) - GetSize(new_s), cell->type.unescape(), cell, module); cell->setPort(ID::A, new_a); cell->setPort(ID::B, new_b); cell->setPort(ID::S, new_s); @@ -2021,7 +2021,7 @@ skip_alu_split: Const y_value(cell->type.in(ID($eq), ID($eqx)) ? 0 : 1, GetSize(y_sig)); log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n", - log_id(cell), log_id(module), log_signal(y_value)); + cell, module, log_signal(y_value)); module->connect(y_sig, y_value); module->remove(cell); @@ -2033,7 +2033,7 @@ skip_alu_split: if (redundant_bits) { log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n", - redundant_bits, log_id(cell->type), log_id(cell), log_id(module)); + redundant_bits, cell->type.unescape(), cell, module); cell->setPort(ID::A, sig_a); cell->setPort(ID::B, sig_b); @@ -2172,7 +2172,7 @@ skip_alu_split: if (replace || remove) { log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n", - log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str()); + cell->type.unescape(), cell, condition.c_str(), replacement.c_str()); if (replace) module->connect(cell->getPort(ID::Y), replace_sig); module->remove(cell); @@ -2295,7 +2295,7 @@ struct OptExprPass : public Pass { NewCellTypes ct(design); for (auto module : design->selected_modules()) { - log("Optimizing module %s.\n", log_id(module)); + log("Optimizing module %s.\n", module); if (undriven) { did_something = false; diff --git a/passes/opt/opt_hier.cc b/passes/opt/opt_hier.cc index 5c3b09b31..532bcad63 100644 --- a/passes/opt/opt_hier.cc +++ b/passes/opt/opt_hier.cc @@ -101,7 +101,7 @@ struct ModuleIndex { if (!port || (!port->port_input && !port->port_output) || port->width != value.size()) { log_error("Port %s connected on instance %s not found in module %s" " or width is not matching\n", - log_id(port_name), log_id(instantiation), log_id(module)); + port_name.unescape(), instantiation, module); } if (port->port_input && port->port_output) { @@ -145,12 +145,12 @@ struct ModuleIndex { if (nunused > 0) { log("Disconnected %d input bits of instance '%s' (type '%s') in '%s'\n", - nunused, log_id(instantiation), log_id(instantiation->type), log_id(parent.module)); + nunused, instantiation, instantiation->type.unescape(), parent.module); changed = true; } if (nconstants > 0) { log("Substituting constant for %d output bits of instance '%s' (type '%s') in '%s'\n", - nconstants, log_id(instantiation), log_id(instantiation->type), log_id(parent.module)); + nconstants, instantiation, instantiation->type.unescape(), parent.module); changed = true; } } @@ -189,7 +189,7 @@ struct ModuleIndex { if (ntie_togethers > 0) { log("Replacing %d output bits with tie-togethers on instance '%s' of '%s' in '%s'\n", - ntie_togethers, log_id(instantiation), log_id(instantiation->type), log_id(parent.module)); + ntie_togethers, instantiation, instantiation->type.unescape(), parent.module); changed = true; } @@ -290,7 +290,7 @@ struct UsageData { if (!port || (!port->port_input && !port->port_output) || port->width != value.size()) { log_error("Port %s connected on instance %s not found in module %s" " or width is not matching\n", - log_id(port_name), log_id(instance), log_id(module)); + port_name.unescape(), instance, module); } if (port->port_input && port->port_output) { @@ -347,7 +347,7 @@ struct UsageData { }; module->rewrite_sigspecs(disconnect_rewrite); for (auto chunk : disconnect_outputs.chunks()) { - log("Disconnected unused output terminal '%s' in module '%s'\n", log_signal(chunk), log_id(module)); + log("Disconnected unused output terminal '%s' in module '%s'\n", log_signal(chunk), module); did_something = true; module->connect(chunk, SigSpec(RTLIL::Sx, chunk.size())); } @@ -368,7 +368,7 @@ struct UsageData { SigSpec const_ = chunk; const_.replace(constant_inputs); log("Substituting constant %s for input terminal '%s' in module '%s'\n", - log_signal(const_), log_signal(chunk), log_id(module)); + log_signal(const_), log_signal(chunk), module); } // Propagate tied-together inputs @@ -397,7 +397,7 @@ struct UsageData { module->rewrite_sigspecs(ties_rewrite); if (applied_ties.size()) { log("Replacing %zu input terminal bits with tie-togethers in module '%s'\n", - applied_ties.size(), log_id(module)); + applied_ties.size(), module); } return did_something; } @@ -433,7 +433,7 @@ struct OptHierPass : Pass { dict indices; for (auto module : d->modules()) { - log_debug("Building index for %s\n", log_id(module)); + log_debug("Building index for %s\n", module); indices.emplace(module->name, ModuleIndex(module)); } @@ -442,14 +442,14 @@ struct OptHierPass : Pass { if (module->get_bool_attribute(ID::top)) continue; - log_debug("Starting usage data for %s\n", log_id(module)); + log_debug("Starting usage data for %s\n", module); usage_datas.emplace(module->name, UsageData(module)); } for (auto module : d->modules()) { for (auto cell : module->cells()) { if (usage_datas.count(cell->type)) { - log_debug("Account for instance %s of %s in %s\n", log_id(cell), log_id(cell->type), log_id(module)); + log_debug("Account for instance %s of %s in %s\n", cell, cell->type.unescape(), module); usage_datas.at(cell->type).refine(cell, indices.at(module->name)); } } @@ -460,13 +460,13 @@ struct OptHierPass : Pass { ModuleIndex &parent_index = indices.at(module->name); if (usage_datas.count(module->name)) { - log_debug("Applying usage data changes to %s\n", log_id(module)); + log_debug("Applying usage data changes to %s\n", module); did_something |= usage_datas.at(module->name).apply_changes(parent_index); } for (auto cell : module->cells()) { if (indices.count(cell->type)) { - log_debug("Applying changes to instance %s of %s in %s\n", log_id(cell), log_id(cell->type), log_id(module)); + log_debug("Applying changes to instance %s of %s in %s\n", cell, cell->type.unescape(), module); did_something |= indices.at(cell->type).apply_changes(parent_index, cell); } } diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index c0a017748..72c465ead 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -121,7 +121,7 @@ struct OptLutWorker SigSpec lut_input = cell->getPort(ID::A); int lut_arity = 0; - log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); + log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, module, cell); luts.insert(cell); // First, find all dedicated logic we're connected to. This results in an overapproximation @@ -162,7 +162,7 @@ struct OptLutWorker { if (lut_width <= dlogic_conn.first) { - log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, module, lut_dlogic.second); log_debug(" LUT input A[%d] not present.\n", dlogic_conn.first); legal = false; break; @@ -173,7 +173,7 @@ struct OptLutWorker if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic.second->getPort(dlogic_conn.second)[0])) { - log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, module, lut_dlogic.second); log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic.second->type, dlogic_conn.second, log_signal(lut_dlogic.second->getPort(dlogic_conn.second))); legal = false; break; @@ -182,7 +182,7 @@ struct OptLutWorker if (legal) { - log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type, module, lut_dlogic.second); lut_legal_dlogics.insert(lut_dlogic); for (auto &dlogic_conn : dlogic_map) lut_dlogic_inputs.insert(dlogic_conn.first); @@ -258,7 +258,7 @@ struct OptLutWorker if (const0_match || const1_match || input_match != -1) { - log_debug("Found redundant cell %s.%s.\n", log_id(module), log_id(lut)); + log_debug("Found redundant cell %s.%s.\n", module, lut); SigBit value; if (const0_match) @@ -341,7 +341,7 @@ struct OptLutWorker int lutB_arity = luts_arity[lutB]; pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; - log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); + log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", module, lutA, module, lutB); if (index.query_is_output(lutA->getPort(ID::Y))) { @@ -421,13 +421,12 @@ struct OptLutWorker } RTLIL::Cell *lutM, *lutR; - pool lutM_inputs, lutR_inputs; + pool lutR_inputs; pool lutM_dlogic_inputs; if (combine == COMBINE_A) { log_debug(" Combining LUTs into cell A.\n"); lutM = lutA; - lutM_inputs = lutA_inputs; lutM_dlogic_inputs = lutA_dlogic_inputs; lutR = lutB; lutR_inputs = lutB_inputs; @@ -436,7 +435,6 @@ struct OptLutWorker { log_debug(" Combining LUTs into cell B.\n"); lutM = lutB; - lutM_inputs = lutB_inputs; lutM_dlogic_inputs = lutB_dlogic_inputs; lutR = lutA; lutR_inputs = lutA_inputs; diff --git a/passes/opt/opt_lut_ins.cc b/passes/opt/opt_lut_ins.cc index 580853b51..c1355da25 100644 --- a/passes/opt/opt_lut_ins.cc +++ b/passes/opt/opt_lut_ins.cc @@ -64,7 +64,7 @@ struct OptLutInsPass : public Pass { for (auto module : design->selected_modules()) { - log("Optimizing LUTs in %s.\n", log_id(module)); + log("Optimizing LUTs in %s.\n", module); std::vector remove_cells; // Gather LUTs. @@ -181,7 +181,7 @@ struct OptLutInsPass : public Pass { } if (!doit) continue; - log(" Optimizing lut %s (%d -> %d)\n", log_id(cell), GetSize(inputs), GetSize(new_inputs)); + log(" Optimizing lut %s (%d -> %d)\n", cell, GetSize(inputs), GetSize(new_inputs)); if (techname == "lattice" || techname == "ecp5") { // Pad the LUT to 4 inputs, adding consts from the front. int extra = 4 - GetSize(new_inputs); diff --git a/passes/opt/opt_mem.cc b/passes/opt/opt_mem.cc index 9c5a6d83e..0bd97f5f9 100644 --- a/passes/opt/opt_mem.cc +++ b/passes/opt/opt_mem.cc @@ -108,13 +108,13 @@ struct OptMemPass : public Pass { } State bit; if (!always_0[i]) { - log("%s.%s: removing const-1 lane %d\n", log_id(module->name), log_id(mem.memid), i); + log("%s.%s: removing const-1 lane %d\n", module->name.unescape(), mem.memid.unescape(), i); bit = State::S1; } else if (!always_1[i]) { - log("%s.%s: removing const-0 lane %d\n", log_id(module->name), log_id(mem.memid), i); + log("%s.%s: removing const-0 lane %d\n", module->name.unescape(), mem.memid.unescape(), i); bit = State::S0; } else { - log("%s.%s: removing const-x lane %d\n", log_id(module->name), log_id(mem.memid), i); + log("%s.%s: removing const-x lane %d\n", module->name.unescape(), mem.memid.unescape(), i); bit = State::Sx; } // Reconnect read port data. diff --git a/passes/opt/opt_mem_feedback.cc b/passes/opt/opt_mem_feedback.cc index 20a2a79ed..fe5157934 100644 --- a/passes/opt/opt_mem_feedback.cc +++ b/passes/opt/opt_mem_feedback.cc @@ -163,7 +163,7 @@ struct OptMemFeedbackWorker { auto &port = mem.wr_ports[i]; - log(" Analyzing %s.%s write port %d.\n", log_id(module), log_id(mem.memid), i); + log(" Analyzing %s.%s write port %d.\n", module, mem.memid.unescape(), i); for (int sub = 0; sub < (1 << port.wide_log2); sub++) { @@ -232,7 +232,7 @@ struct OptMemFeedbackWorker // Okay, let's do it. - log("Populating enable bits on write ports of memory %s.%s with async read feedback:\n", log_id(module), log_id(mem.memid)); + log("Populating enable bits on write ports of memory %s.%s with async read feedback:\n", module, mem.memid.unescape()); // If a write port has a feedback path that we're about to bypass, // but also has priority over some other write port, the feedback diff --git a/passes/opt/opt_mem_widen.cc b/passes/opt/opt_mem_widen.cc index 95e01088c..f642666db 100644 --- a/passes/opt/opt_mem_widen.cc +++ b/passes/opt/opt_mem_widen.cc @@ -65,7 +65,7 @@ struct OptMemWidenPass : public Pass { factor_log2 = port.wide_log2; if (factor_log2 == 0) continue; - log("Widening base width of memory %s in module %s by factor %d.\n", log_id(mem.memid), log_id(module->name), 1 << factor_log2); + log("Widening base width of memory %s in module %s by factor %d.\n", mem.memid.unescape(), module->name.unescape(), 1 << factor_log2); total_count++; // The inits are too messy to expand one-by-one, for they may // collide with one another after expansion. Just hit it with diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 0020af09f..af77ff46d 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -21,11 +21,9 @@ #include "kernel/sigtools.h" #include "kernel/log.h" #include "kernel/celltypes.h" +#include #include #include -#include -#include -#include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -128,7 +126,7 @@ struct OptMuxtreeWorker // In case of $pmux, port B is multiple slices, concatenated, one per bit of port S for (int i = 0; i < GetSize(sig_s); i++) { RTLIL::SigSpec sig = sig_b.extract(i*GetSize(sig_a), GetSize(sig_a)); - RTLIL::SigSpec ctrl_sig = assign_map(sig_s.extract(i, 1)); + RTLIL::SigSpec ctrl_sig = assign_map(SigSpec{sig_s[i]}); portinfo_t portinfo = used_port_bit(sig, this_mux_idx); portinfo.ctrl_sig = sig2bits(ctrl_sig, false).front(); portinfo.const_activated = ctrl_sig.is_fully_const() && ctrl_sig.as_bool(); @@ -231,7 +229,7 @@ struct OptMuxtreeWorker for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++) if (root_muxes.at(mux_idx)) { - log_debug(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : ""); + log_debug(" Root of a mux tree: %s%s\n", mux2info[mux_idx].cell, root_enable_muxes.at(mux_idx) ? " (pure)" : ""); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); if (glob_evals_left == 0) { @@ -242,7 +240,7 @@ struct OptMuxtreeWorker while (!root_mux_rerun.empty()) { int mux_idx = *root_mux_rerun.begin(); - log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell)); + log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", mux2info[mux_idx].cell); log_assert(root_enable_muxes.at(mux_idx)); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); @@ -342,14 +340,21 @@ struct OptMuxtreeWorker // The payload is a reference counter used to manage the list // When it is non-zero, the signal in known to be inactive // When it reaches zero, the map element is removed - std::unordered_map known_inactive; + std::vector known_inactive; // database of known active signals - std::unordered_map known_active; + std::vector known_active; // this is just used to keep track of visited muxes in order to prohibit // endless recursion in mux loops - std::unordered_set visited_muxes; + std::vector visited_muxes; + + // Initialize with the maximum possible sizes + knowledge_t(int num_bits, int num_muxes) { + known_inactive.assign(num_bits, 0); + known_active.assign(num_bits, 0); + visited_muxes.assign(num_muxes, false); + } }; static void activate_port(knowledge_t &knowledge, int port_idx, const muxinfo_t &muxinfo) { @@ -366,11 +371,10 @@ struct OptMuxtreeWorker } static void deactivate_port(knowledge_t &knowledge, int port_idx, const muxinfo_t &muxinfo) { - auto unlearn = [](std::unordered_map& knowns, int i) { - auto it = knowns.find(i); - if (it != knowns.end()) - if (--it->second == 0) - knowns.erase(it); + auto unlearn = [](std::vector& knowns, int bit_idx) { + if (knowns[bit_idx] > 0) { + --knowns[bit_idx]; + } }; if (port_idx < GetSize(muxinfo.ports)-1 && !muxinfo.ports[port_idx].const_activated) @@ -418,9 +422,9 @@ struct OptMuxtreeWorker vector input_mux_queue; for (int m : muxinfo.ports[port_idx].input_muxes) { - if (knowledge.visited_muxes.count(m)) + if (knowledge.visited_muxes[m]) continue; - knowledge.visited_muxes.insert(m); + knowledge.visited_muxes[m] = true; input_mux_queue.push_back(m); } for (int m : input_mux_queue) { @@ -433,7 +437,7 @@ struct OptMuxtreeWorker // Ran out of subtree depth, re-eval this input tree in the next re-run root_mux_rerun.insert(m); root_enable_muxes.at(m) = true; - log_debug(" Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell)); + log_debug(" Removing pure flag from root mux %s.\n", mux2info[m].cell); } else { auto new_limits = limits.subtree(); // Since our knowledge includes assumption, @@ -453,7 +457,7 @@ struct OptMuxtreeWorker // Allow revisiting input muxes, since evaluating other ports should // revisit these input muxes with different activation assumptions for (int m : input_mux_queue) - knowledge.visited_muxes.erase(m); + knowledge.visited_muxes[m] = false; // Undo our assumptions that the port is active deactivate_port(knowledge, port_idx, muxinfo); @@ -475,11 +479,11 @@ struct OptMuxtreeWorker vector bits = sig2bits(sig, false); for (int i = 0; i < GetSize(bits); i++) { if (bits[i] >= 0) { - if (knowledge.known_inactive.count(bits[i]) > 0) { + if (knowledge.known_inactive[bits[i]] > 0) { sig[i] = State::S0; did_something = true; } else - if (knowledge.known_active.count(bits[i]) > 0) { + if (knowledge.known_active[bits[i]] > 0) { sig[i] = State::S1; did_something = true; } @@ -513,8 +517,8 @@ struct OptMuxtreeWorker } if (did_something) { - log(" Replacing known input bits on port %s of cell %s: %s -> %s\n", log_id(portname), - log_id(muxinfo.cell), log_signal(muxinfo.cell->getPort(portname)), log_signal(sig)); + log(" Replacing known input bits on port %s of cell %s: %s -> %s\n", portname.unescape(), + muxinfo.cell, log_signal(muxinfo.cell->getPort(portname)), log_signal(sig)); muxinfo.cell->setPort(portname, sig); } } @@ -526,7 +530,7 @@ struct OptMuxtreeWorker glob_evals_left--; muxinfo_t &muxinfo = mux2info[mux_idx]; - log_debug("\t\teval %s (replace %d enable %d)\n", log_id(muxinfo.cell), limits.do_replace_known, limits.do_mark_ports_observable); + log_debug("\t\teval %s (replace %d enable %d)\n", muxinfo.cell, limits.do_replace_known, limits.do_mark_ports_observable); // set input ports to constants if we find known active or inactive signals if (limits.do_replace_known) { @@ -552,7 +556,7 @@ struct OptMuxtreeWorker portinfo_t &portinfo = muxinfo.ports[port_idx]; if (portinfo.const_deactivated) continue; - if (knowledge.known_active.count(portinfo.ctrl_sig) > 0) { + if (knowledge.known_active[portinfo.ctrl_sig] > 0) { eval_mux_port(knowledge, mux_idx, port_idx, limits); return; } @@ -566,7 +570,7 @@ struct OptMuxtreeWorker if (portinfo.const_deactivated) continue; if (port_idx < GetSize(muxinfo.ports)-1) - if (knowledge.known_inactive.count(portinfo.ctrl_sig) > 0) + if (knowledge.known_inactive[portinfo.ctrl_sig] > 0) continue; eval_mux_port(knowledge, mux_idx, port_idx, limits); @@ -578,8 +582,8 @@ struct OptMuxtreeWorker void eval_root_mux(int mux_idx) { log_assert(glob_evals_left > 0); - knowledge_t knowledge; - knowledge.visited_muxes.insert(mux_idx); + knowledge_t knowledge(GetSize(bit2info), GetSize(mux2info)); + knowledge.visited_muxes[mux_idx] = true; limits_t limits = {}; limits.do_mark_ports_observable = root_enable_muxes.at(mux_idx); eval_mux(knowledge, mux_idx, limits); diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc index 6d6cadfe7..b4592038b 100644 --- a/passes/opt/opt_reduce.cc +++ b/passes/opt/opt_reduce.cc @@ -110,22 +110,20 @@ struct OptReduceWorker RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S)); RTLIL::SigSpec new_sig_b, new_sig_s; - pool handled_sig; + dict> grouped_b_to_s; - handled_sig.insert(sig_a); - for (int i = 0; i < sig_s.size(); i++) - { - RTLIL::SigSpec this_b = sig_b.extract(i*sig_a.size(), sig_a.size()); - if (handled_sig.count(this_b) > 0) - continue; - - RTLIL::SigSpec this_s = sig_s.extract(i, 1); - for (int j = i+1; j < sig_s.size(); j++) { - RTLIL::SigSpec that_b = sig_b.extract(j*sig_a.size(), sig_a.size()); - if (this_b == that_b) - this_s.append(sig_s.extract(j, 1)); + int port_width = sig_a.size(); + for (int i = 0; i < sig_s.size(); i++) { + RTLIL::SigSpec this_b = sig_b.extract(i*port_width, port_width); + if (grouped_b_to_s.count(this_b)) { + grouped_b_to_s[this_b].push_back(sig_s[i]); + } else { + grouped_b_to_s[this_b] = {sig_s[i]}; } + } + for (auto &[this_b, this_s_bit] : grouped_b_to_s) { + RTLIL::SigSpec this_s{this_s_bit}; if (this_s.size() > 1) { RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or)); @@ -141,7 +139,6 @@ struct OptReduceWorker new_sig_b.append(this_b); new_sig_s.append(this_s); - handled_sig.insert(this_b); } if (new_sig_s.size() == 0) diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index bf9569d99..b213048aa 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -560,9 +560,9 @@ struct OptSharePass : public Pass { log(" Found cells that share an operand and can be merged by moving the %s %s in front " "of " "them:\n", - log_id(shared.mux->type), log_id(shared.mux)); + shared.mux->type.unescape(), shared.mux); for (const auto& op : shared.ports) - log(" %s\n", log_id(op.op)); + log(" %s\n", op.op); log("\n"); merge_operators(module, shared.mux, shared.ports, shared.shared_operand, sigmap); diff --git a/passes/opt/peepopt_formal_clockgateff.pmg b/passes/opt/peepopt_formal_clockgateff.pmg index 835f68bd8..1f44a2cf4 100644 --- a/passes/opt/peepopt_formal_clockgateff.pmg +++ b/passes/opt/peepopt_formal_clockgateff.pmg @@ -44,7 +44,7 @@ endmatch code log("replacing clock gate pattern in %s with ff: latch=%s, and=%s\n", - log_id(module), log_id(latch), log_id(and_gate)); + module, latch, and_gate); // Add a flip-flop and rewire the AND gate to use the output of this flop // instead of the latch. We don't delete the latch in case its output is diff --git a/passes/opt/peepopt_muldiv.pmg b/passes/opt/peepopt_muldiv.pmg index a4e232342..c7eb8ec95 100644 --- a/passes/opt/peepopt_muldiv.pmg +++ b/passes/opt/peepopt_muldiv.pmg @@ -32,7 +32,7 @@ code val_y.extend_u0(GetSize(div_y), param(div, \A_SIGNED).as_bool()); did_something = true; - log("muldiv pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div)); + log("muldiv pattern in %s: mul=%s, div=%s\n", module, mul, div); module->connect(div_y, val_y); autoremove(div); accept; diff --git a/passes/opt/peepopt_muldiv_c.pmg b/passes/opt/peepopt_muldiv_c.pmg index 2cf9b028b..eb8b31e13 100644 --- a/passes/opt/peepopt_muldiv_c.pmg +++ b/passes/opt/peepopt_muldiv_c.pmg @@ -119,7 +119,7 @@ code autoremove(div); // Log, fixup, accept - log("muldiv_const pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div)); + log("muldiv_const pattern in %s: mul=%s, div=%s\n", module, mul, div); mul->fixup_parameters(); accept; endcode diff --git a/passes/opt/peepopt_shiftadd.pmg b/passes/opt/peepopt_shiftadd.pmg index 58dbefc12..6144e44ef 100644 --- a/passes/opt/peepopt_shiftadd.pmg +++ b/passes/opt/peepopt_shiftadd.pmg @@ -112,7 +112,7 @@ code did_something = true; log("shiftadd pattern in %s: shift=%s, add/sub=%s, offset: %d\n", \ - log_id(module), log_id(shift), log_id(add), offset); + module, shift, add, offset); SigSpec new_a; if(offset<0) { diff --git a/passes/opt/peepopt_shiftmul_left.pmg b/passes/opt/peepopt_shiftmul_left.pmg index 607f8368c..383222195 100644 --- a/passes/opt/peepopt_shiftmul_left.pmg +++ b/passes/opt/peepopt_shiftmul_left.pmg @@ -99,7 +99,7 @@ code } did_something = true; - log("left shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul)); + log("left shiftmul pattern in %s: shift=%s, mul=%s\n", module, shift, mul); int const_factor = mul_const.as_int(); int new_const_factor = 1 << factor_bits; diff --git a/passes/opt/peepopt_shiftmul_right.pmg b/passes/opt/peepopt_shiftmul_right.pmg index 108829d4f..ac0958bb8 100644 --- a/passes/opt/peepopt_shiftmul_right.pmg +++ b/passes/opt/peepopt_shiftmul_right.pmg @@ -76,7 +76,7 @@ code reject; did_something = true; - log("right shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul)); + log("right shiftmul pattern in %s: shift=%s, mul=%s\n", module, shift, mul); int const_factor = mul_const.as_int(); int new_const_factor = 1 << factor_bits; diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 4a0864df0..6668ff2de 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -390,7 +390,7 @@ struct Pmux2ShiftxPass : public Pass { if (verbose) { printed_pmux_header = true; - log("Inspecting $pmux cell %s/%s.\n", log_id(module), log_id(cell)); + log("Inspecting $pmux cell %s/%s.\n", module, cell); log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); } @@ -441,7 +441,7 @@ struct Pmux2ShiftxPass : public Pass { if (!printed_pmux_header) { printed_pmux_header = true; - log("Inspecting $pmux cell %s/%s.\n", log_id(module), log_id(cell)); + log("Inspecting $pmux cell %s/%s.\n", module, cell); log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); } @@ -714,7 +714,7 @@ struct Pmux2ShiftxPass : public Pass { Cell *c = module->addShiftx(NEW_ID, data, shifted_cmp, outsig, false, src); updated_S.append(en); updated_B.append(outsig); - log(" created $shiftx cell %s.\n", log_id(c)); + log(" created $shiftx cell %s.\n", c); // remove this sig and continue with the next block seldb.erase(sig); @@ -799,7 +799,7 @@ struct OnehotPass : public Pass { continue; if (verbose) - log("Checking $eq(%s, %s) cell %s/%s.\n", log_signal(A), log_signal(B), log_id(module), log_id(cell)); + log("Checking $eq(%s, %s) cell %s/%s.\n", log_signal(A), log_signal(B), module, cell); if (!onehot_db.query(A)) { if (verbose) @@ -831,7 +831,7 @@ struct OnehotPass : public Pass { if (verbose) log(" replacing with constant 0 driver.\n"); else - log("Replacing one-hot $eq(%s, %s) cell %s/%s with constant 0 driver.\n", log_signal(A), log_signal(B), log_id(module), log_id(cell)); + log("Replacing one-hot $eq(%s, %s) cell %s/%s with constant 0 driver.\n", log_signal(A), log_signal(B), module, cell); module->connect(Y, SigSpec(1, GetSize(Y))); } else @@ -840,7 +840,7 @@ struct OnehotPass : public Pass { if (verbose) log(" replacing with signal %s.\n", log_signal(sig)); else - log("Replacing one-hot $eq(%s, %s) cell %s/%s with signal %s.\n",log_signal(A), log_signal(B), log_id(module), log_id(cell), log_signal(sig)); + log("Replacing one-hot $eq(%s, %s) cell %s/%s with signal %s.\n",log_signal(A), log_signal(B), module, cell, log_signal(sig)); sig.extend_u0(GetSize(Y)); module->connect(Y, sig); } diff --git a/passes/opt/share.cc b/passes/opt/share.cc index f7843cc08..119243d48 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -36,7 +36,6 @@ struct ShareWorkerConfig { int limit; size_t pattern_limit; - bool opt_force; bool opt_aggressive; bool opt_fast; StaticCellTypes::Categories::Category generic_uni_ops, generic_bin_ops, generic_cbin_ops, generic_other_ops; @@ -363,11 +362,6 @@ struct ShareWorker not_a_muxed_cell: continue; - if (config.opt_force) { - shareable_cells.insert(cell); - continue; - } - if (cell->type.in(ID($memrd), ID($memrd_v2))) { if (cell->parameters.at(ID::CLK_ENABLE).as_bool()) continue; @@ -964,7 +958,7 @@ struct ShareWorker optimize_activation_patterns(activation_patterns_cache[cell]); if (activation_patterns_cache[cell].empty()) { - log("%sFound cell that is never activated: %s\n", indent, log_id(cell)); + log("%sFound cell that is never activated: %s\n", indent, cell); RTLIL::SigSpec cell_outputs = modwalker.cell_outputs[cell]; module->connect(RTLIL::SigSig(cell_outputs, RTLIL::SigSpec(RTLIL::State::Sx, cell_outputs.size()))); cells_to_remove.insert(cell); @@ -1129,7 +1123,7 @@ struct ShareWorker for (auto &loop : toposort.loops) { log("### loop ###\n"); for (auto &c : loop) - log("%s (%s)\n", log_id(c), log_id(c->type)); + log("%s (%s)\n", c, c->type.unescape()); } return found_scc; @@ -1246,14 +1240,14 @@ struct ShareWorker return; log("Found %d cells in module %s that may be considered for resource sharing.\n", - GetSize(shareable_cells), log_id(module)); + GetSize(shareable_cells), module); while (!shareable_cells.empty() && config.limit != 0) { RTLIL::Cell *cell = *shareable_cells.begin(); shareable_cells.erase(cell); - log(" Analyzing resource sharing options for %s (%s):\n", log_id(cell), log_id(cell->type)); + log(" Analyzing resource sharing options for %s (%s):\n", cell, cell->type.unescape()); const pool &cell_activation_patterns = find_cell_activation_patterns(cell, " "); RTLIL::SigSpec cell_activation_signals = bits_from_activation_patterns(cell_activation_patterns); @@ -1281,12 +1275,12 @@ struct ShareWorker log(" Found %d candidates:", GetSize(candidates)); for (auto c : candidates) - log(" %s", log_id(c)); + log(" %s", c); log("\n"); for (auto other_cell : candidates) { - log(" Analyzing resource sharing with %s (%s):\n", log_id(other_cell), log_id(other_cell->type)); + log(" Analyzing resource sharing with %s (%s):\n", other_cell, other_cell->type.unescape()); const pool &other_cell_activation_patterns = find_cell_activation_patterns(other_cell, " "); RTLIL::SigSpec other_cell_activation_signals = bits_from_activation_patterns(other_cell_activation_patterns); @@ -1338,13 +1332,13 @@ struct ShareWorker RTLIL::SigSpec all_ctrl_signals; for (auto &p : filtered_cell_activation_patterns) { - log(" Activation pattern for cell %s: %s = %s\n", log_id(cell), log_signal(p.first), log_signal(p.second)); + log(" Activation pattern for cell %s: %s = %s\n", cell, log_signal(p.first), log_signal(p.second)); cell_active.push_back(qcsat.ez->vec_eq(qcsat.importSig(p.first), qcsat.importSig(p.second))); all_ctrl_signals.append(p.first); } for (auto &p : filtered_other_cell_activation_patterns) { - log(" Activation pattern for cell %s: %s = %s\n", log_id(other_cell), log_signal(p.first), log_signal(p.second)); + log(" Activation pattern for cell %s: %s = %s\n", other_cell, log_signal(p.first), log_signal(p.second)); other_cell_active.push_back(qcsat.ez->vec_eq(qcsat.importSig(p.first), qcsat.importSig(p.second))); all_ctrl_signals.append(p.first); } @@ -1355,13 +1349,13 @@ struct ShareWorker qcsat.prepare(); if (!qcsat.ez->solve(sub1)) { - log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", log_id(cell)); + log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", cell); cells_to_remove.insert(cell); break; } if (!qcsat.ez->solve(sub2)) { - log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", log_id(other_cell)); + log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", other_cell); cells_to_remove.insert(other_cell); shareable_cells.erase(other_cell); continue; @@ -1397,20 +1391,20 @@ struct ShareWorker if (restrict_activation_patterns(optimized_cell_activation_patterns, optimized_other_cell_activation_patterns)) { for (auto &p : optimized_cell_activation_patterns) - log(" Simplified activation pattern for cell %s: %s = %s\n", log_id(cell), log_signal(p.first), log_signal(p.second)); + log(" Simplified activation pattern for cell %s: %s = %s\n", cell, log_signal(p.first), log_signal(p.second)); for (auto &p : optimized_other_cell_activation_patterns) - log(" Simplified activation pattern for cell %s: %s = %s\n", log_id(other_cell), log_signal(p.first), log_signal(p.second)); + log(" Simplified activation pattern for cell %s: %s = %s\n", other_cell, log_signal(p.first), log_signal(p.second)); } } if (find_in_input_cone(cell, other_cell)) { - log(" Sharing not possible: %s is in input cone of %s.\n", log_id(other_cell), log_id(cell)); + log(" Sharing not possible: %s is in input cone of %s.\n", other_cell, cell); continue; } if (find_in_input_cone(other_cell, cell)) { - log(" Sharing not possible: %s is in input cone of %s.\n", log_id(cell), log_id(other_cell)); + log(" Sharing not possible: %s is in input cone of %s.\n", cell, other_cell); continue; } @@ -1430,14 +1424,14 @@ struct ShareWorker if (cell_select_score <= other_cell_select_score) { RTLIL::SigSpec act = make_cell_activation_logic(optimized_cell_activation_patterns, supercell_aux); supercell = make_supercell(cell, other_cell, act, supercell_aux); - log(" Activation signal for %s: %s\n", log_id(cell), log_signal(act)); + log(" Activation signal for %s: %s\n", cell, log_signal(act)); } else { RTLIL::SigSpec act = make_cell_activation_logic(optimized_other_cell_activation_patterns, supercell_aux); supercell = make_supercell(other_cell, cell, act, supercell_aux); - log(" Activation signal for %s: %s\n", log_id(other_cell), log_signal(act)); + log(" Activation signal for %s: %s\n", other_cell, log_signal(act)); } - log(" New cell: %s (%s)\n", log_id(supercell), log_id(supercell->type)); + log(" New cell: %s (%s)\n", supercell, supercell->type.unescape()); cells_to_remove.insert(cell); cells_to_remove.insert(other_cell); @@ -1482,9 +1476,9 @@ struct ShareWorker } if (!cells_to_remove.empty()) { - log("Removing %d cells in module %s:\n", GetSize(cells_to_remove), log_id(module)); + log("Removing %d cells in module %s:\n", GetSize(cells_to_remove), module); for (auto c : cells_to_remove) { - log(" Removing cell %s (%s).\n", log_id(c), log_id(c->type)); + log(" Removing cell %s (%s).\n", c, c->type.unescape()); remove_cell(c); } } @@ -1509,14 +1503,6 @@ struct SharePass : public Pass { log("This pass merges shareable resources into a single resource. A SAT solver\n"); log("is used to determine if two resources are share-able.\n"); log("\n"); - log(" -force\n"); - log(" Per default the selection of cells that is considered for sharing is\n"); - log(" narrowed using a list of cell types. With this option all selected\n"); - log(" cells are considered for resource sharing.\n"); - log("\n"); - log(" IMPORTANT NOTE: If the -all option is used then no cells with internal\n"); - log(" state must be selected!\n"); - log("\n"); log(" -aggressive\n"); log(" Per default some heuristics are used to reduce the number of cells\n"); log(" considered for resource sharing to only large resources. This options\n"); @@ -1543,7 +1529,6 @@ struct SharePass : public Pass { config.limit = -1; config.pattern_limit = design->scratchpad_get_int("share.pattern_limit", 1000); - config.opt_force = false; config.opt_aggressive = false; config.opt_fast = false; @@ -1591,10 +1576,6 @@ struct SharePass : public Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-force") { - config.opt_force = true; - continue; - } if (args[argidx] == "-aggressive") { config.opt_aggressive = true; continue; diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 359c76d42..d70299ab8 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -104,14 +104,14 @@ struct WreduceWorker sig_removed.append(bits_removed[i]); if (GetSize(bits_removed) == GetSize(sig_y)) { - log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescape()); module->connect(sig_y, sig_removed); module->remove(cell); return; } log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", - GetSize(sig_removed), GetSize(sig_y), log_id(module), log_id(cell), log_id(cell->type)); + GetSize(sig_removed), GetSize(sig_y), module, cell, cell->type.unescape()); int n_removed = GetSize(sig_removed); int n_kept = GetSize(sig_y) - GetSize(sig_removed); @@ -204,13 +204,13 @@ struct WreduceWorker return; if (GetSize(sig_q) == 0) { - log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescape()); module->remove(cell); return; } log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); for (auto bit : sig_d) work_queue_bits.insert(bit); @@ -258,7 +258,7 @@ struct WreduceWorker if (bits_removed) { log("Removed top %d bits (of %d) from port %c of cell %s.%s (%s).\n", - bits_removed, GetSize(sig) + bits_removed, port, log_id(module), log_id(cell), log_id(cell->type)); + bits_removed, GetSize(sig) + bits_removed, port, module, cell, cell->type.unescape()); cell->setPort(stringf("\\%c", port), sig); did_something = true; } @@ -331,7 +331,7 @@ struct WreduceWorker if (!port_a_signed && !port_b_signed && signed_cost < unsigned_cost) { log("Converting cell %s.%s (%s) from unsigned to signed.\n", - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); cell->setParam(ID::A_SIGNED, 1); cell->setParam(ID::B_SIGNED, 1); port_a_signed = true; @@ -339,7 +339,7 @@ struct WreduceWorker did_something = true; } else if (port_a_signed && port_b_signed && unsigned_cost < signed_cost) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); cell->setParam(ID::A_SIGNED, 0); cell->setParam(ID::B_SIGNED, 0); port_a_signed = false; @@ -359,7 +359,7 @@ struct WreduceWorker if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 && GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); cell->setParam(ID::A_SIGNED, 0); cell->setParam(ID::B_SIGNED, 0); port_a_signed = false; @@ -372,7 +372,7 @@ struct WreduceWorker SigSpec sig_a = mi.sigmap(cell->getPort(ID::A)); if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); cell->setParam(ID::A_SIGNED, 0); port_a_signed = false; did_something = true; @@ -431,14 +431,14 @@ struct WreduceWorker } if (GetSize(sig) == 0) { - log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescape()); module->remove(cell); return; } if (bits_removed) { log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n", - bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); + bits_removed, GetSize(sig) + bits_removed, module, cell, cell->type.unescape()); cell->setPort(ID::Y, sig); did_something = true; } @@ -510,7 +510,7 @@ struct WreduceWorker if (complete_wires[mi.sigmap(w).extract(0, GetSize(w) - unused_top_bits)]) continue; - log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, GetSize(w), log_id(module), log_id(w)); + log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, GetSize(w), module, w); Wire *nw = module->addWire(NEW_ID, GetSize(w) - unused_top_bits); module->connect(nw, SigSpec(w).extract(0, GetSize(nw))); module->swap_names(w, nw); @@ -603,7 +603,7 @@ struct WreducePass : public Pass { } if (original_a_width != GetSize(A)) { log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n", - original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type)); + original_a_width-GetSize(A), original_a_width, module, c, c->type.unescape()); c->setPort(ID::A, A); c->setParam(ID::A_WIDTH, GetSize(A)); } @@ -619,7 +619,7 @@ struct WreducePass : public Pass { } if (original_b_width != GetSize(B)) { log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n", - original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type)); + original_b_width-GetSize(B), original_b_width, module, c, c->type.unescape()); c->setPort(ID::B, B); c->setParam(ID::B_WIDTH, GetSize(B)); } @@ -635,7 +635,7 @@ struct WreducePass : public Pass { log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n", cur_addrbits-max_addrbits, cur_addrbits, c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init", - log_id(module), log_id(c), log_id(memid)); + module, c, memid.unescape()); c->setParam(ID::ABITS, max_addrbits); c->setPort(ID::ADDR, c->getPort(ID::ADDR).extract(0, max_addrbits)); } diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index 15569ebfc..15b4f79a1 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -34,8 +34,8 @@ for the pattern`` and calls the callback function for each found match: pm.run_foobar([&](){ - log("found matching 'foo' cell: %s\n", log_id(pm.st.foo)); - log(" with 'bar' cell: %s\n", log_id(pm.st.bar)); + log("found matching 'foo' cell: %s\n", pm.st.foo); + log(" with 'bar' cell: %s\n", pm.st.bar); }); The `.pmg` file declares matcher state variables that are accessible via the @@ -158,7 +158,7 @@ in `select` lines. Index lines are using the `index expr1 === expr2` syntax. `expr1` is evaluated during matcher initialization and the same restrictions apply as for -`select` expressions. `expr2` is evaluated when the match is calulated. It is a +`select` expressions. `expr2` is evaluated when the match is calculated. It is a function of any state variables assigned to by previous blocks. Both expression are converted to the given type and compared for equality. Only cells for which all `index` statements in the block pass are considered by the match. diff --git a/passes/pmgen/generate.h b/passes/pmgen/generate.h index 85e208774..e44ff58e8 100644 --- a/passes/pmgen/generate.h +++ b/passes/pmgen/generate.h @@ -106,7 +106,7 @@ void generate_pattern(std::function)> run, const if (found_match) { Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d", pmclass, pattern, modcnt++)); - log("Creating module %s with %d cells.\n", log_id(m), cellcnt); + log("Creating module %s with %d cells.\n", m, cellcnt); mod->cloneInto(m); pmtest_addports(m); mods.push_back(m); @@ -126,7 +126,7 @@ void generate_pattern(std::function)> run, const } Module *m = design->addModule(stringf("\\pmtest_%s_%s", pmclass, pattern)); - log("Creating module %s with %d cells.\n", log_id(m), GetSize(mods)); + log("Creating module %s with %d cells.\n", m, GetSize(mods)); for (auto mod : mods) { Cell *c = m->addCell(mod->name, mod->name); for (auto port : mod->ports) { diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc index f6d6a3f93..18bc12346 100644 --- a/passes/pmgen/test_pmgen.cc +++ b/passes/pmgen/test_pmgen.cc @@ -37,7 +37,7 @@ void reduce_chain(test_pmgen_pm &pm) if (ud.longest_chain.empty()) return; - log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); + log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), st.first->type.unescape()); SigSpec A; SigSpec Y = ud.longest_chain.front().first->getPort(ID::Y); @@ -51,7 +51,7 @@ void reduce_chain(test_pmgen_pm &pm) } else { A.append(cell->getPort(it.second == ID::A ? ID::B : ID::A)); } - log(" %s\n", log_id(cell)); + log(" %s\n", cell); pm.autoremove(cell); } @@ -66,7 +66,7 @@ void reduce_chain(test_pmgen_pm &pm) else log_abort(); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } void reduce_tree(test_pmgen_pm &pm) @@ -81,8 +81,8 @@ void reduce_tree(test_pmgen_pm &pm) SigSpec Y = st.first->getPort(ID::Y); pm.autoremove(st.first); - log("Found %s tree with %d leaves for %s (%s).\n", log_id(st.first->type), - GetSize(A), log_signal(Y), log_id(st.first)); + log("Found %s tree with %d leaves for %s (%s).\n", st.first->type.unescape(), + GetSize(A), log_signal(Y), st.first); Cell *c; @@ -95,7 +95,7 @@ void reduce_tree(test_pmgen_pm &pm) else log_abort(); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } void opt_eqpmux(test_pmgen_pm &pm) @@ -109,11 +109,11 @@ void opt_eqpmux(test_pmgen_pm &pm) SigSpec NE = st.pmux->getPort(ID::B).extract(st.pmux_slice_ne*width, width); log("Found eqpmux circuit driving %s (eq=%s, ne=%s, pmux=%s).\n", - log_signal(Y), log_id(st.eq), log_id(st.ne), log_id(st.pmux)); + log_signal(Y), st.eq, st.ne, st.pmux); pm.autoremove(st.pmux); Cell *c = pm.module->addMux(NEW_ID, NE, EQ, st.eq->getPort(ID::Y), Y); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } struct TestPmgenPass : public Pass { diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index 92d8d0569..f754bc948 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -215,7 +215,7 @@ void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map) RTLIL::SigSpec en = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.enable, memwr.enable); if (!en.is_fully_zero()) { log_error("Async reset %s causes memory write to %s.\n", - log_signal(sync->signal), log_id(memwr.memid)); + log_signal(sync->signal), memwr.memid.unescape()); } apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.address, memwr.address); apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.data, memwr.data); diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 8cccb96c4..0df9fc0b2 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -216,7 +216,7 @@ struct ProcCleanPass : public Pass { if (proc->syncs.size() == 0 && proc->root_case.switches.size() == 0 && proc->root_case.actions.size() == 0) { if (!quiet) - log("Removing empty process `%s.%s'.\n", log_id(mod), proc->name); + log("Removing empty process `%s.%s'.\n", mod, proc->name); delme.push_back(proc); } } diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc index bda2d272f..5e07dbcb0 100644 --- a/passes/proc/proc_dlatch.cc +++ b/passes/proc/proc_dlatch.cc @@ -438,7 +438,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str()); else log("Latch inferred for signal `%s.%s' from process `%s.%s': %s\n", - db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), log_id(cell)); + db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), cell); } offset += width; diff --git a/passes/proc/proc_memwr.cc b/passes/proc/proc_memwr.cc index a5ae0d6d5..e79d24e96 100644 --- a/passes/proc/proc_memwr.cc +++ b/passes/proc/proc_memwr.cc @@ -75,7 +75,7 @@ void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict &n cell->setParam(ID::CLK_ENABLE, State::S1); cell->setParam(ID::CLK_POLARITY, State::S0); } else { - log_error("process memory write with unsupported sync type in %s.%s", log_id(mod), log_id(proc)); + log_error("process memory write with unsupported sync type in %s.%s", mod, proc); } } sr->mem_write_actions.clear(); diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc index 8f5eda085..be7961e76 100644 --- a/passes/proc/proc_rmdead.cc +++ b/passes/proc/proc_rmdead.cc @@ -154,10 +154,10 @@ struct ProcRmdeadPass : public Pass { proc_rmdead(switch_it, counter, full_case_counter); if (counter > 0) log("Removed %d dead cases from process %s in module %s.\n", counter, - log_id(proc), log_id(mod)); + proc, mod); if (full_case_counter > 0) log("Marked %d switch rules as full_case in process %s in module %s.\n", - full_case_counter, log_id(proc), log_id(mod)); + full_case_counter, proc, mod); total_counter += counter; } } diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc index 7b3357f82..314535e84 100644 --- a/passes/sat/assertpmux.cc +++ b/passes/sat/assertpmux.cc @@ -148,7 +148,7 @@ struct AssertpmuxWorker void run(Cell *pmux) { - log("Adding assert for $pmux cell %s.%s.\n", log_id(module), log_id(pmux)); + log("Adding assert for $pmux cell %s.%s.\n", module, pmux); int swidth = pmux->getParam(ID::S_WIDTH).as_int(); int cntbits = ceil_log2(swidth+1); diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc index 086dd5278..be2355e00 100644 --- a/passes/sat/async2sync.cc +++ b/passes/sat/async2sync.cc @@ -91,7 +91,7 @@ struct Async2syncPass : public Pass { int trg_width = cell->getParam(ID(TRG_WIDTH)).as_int(); if (trg_width > 1) - log_error("$check cell %s with TRG_WIDTH > 1 is not support by async2sync, use clk2fflogic.\n", log_id(cell)); + log_error("$check cell %s with TRG_WIDTH > 1 is not support by async2sync, use clk2fflogic.\n", cell); if (trg_width == 0) { if (initstate == State::S0) @@ -147,7 +147,7 @@ struct Async2syncPass : public Pass { ff.unmap_ce_srst(); log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_d), log_signal(ff.sig_q)); initvals.remove_init(ff.sig_q); @@ -212,7 +212,7 @@ struct Async2syncPass : public Pass { ff.unmap_ce_srst(); log("Replacing %s.%s (%s): ALOAD=%s, AD=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type, log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_d), log_signal(ff.sig_q)); initvals.remove_init(ff.sig_q); @@ -245,7 +245,7 @@ struct Async2syncPass : public Pass { ff.unmap_srst(); log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_arst), log_signal(ff.sig_d), log_signal(ff.sig_q)); initvals.remove_init(ff.sig_q); @@ -279,7 +279,7 @@ struct Async2syncPass : public Pass { { // Latch. log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q)); initvals.remove_init(ff.sig_q); diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc index b75c8aab1..0b928ddf6 100644 --- a/passes/sat/clk2fflogic.cc +++ b/passes/sat/clk2fflogic.cc @@ -173,7 +173,7 @@ struct Clk2fflogicPass : public Pass { auto &port = mem.rd_ports[i]; if (port.clk_enable) log_error("Read port %d of memory %s.%s is clocked. This is not supported by \"clk2fflogic\"! " - "Call \"memory\" with -nordff to avoid this error.\n", i, log_id(mem.memid), log_id(module)); + "Call \"memory\" with -nordff to avoid this error.\n", i, mem.memid.unescape(), module); } for (int i = 0; i < GetSize(mem.wr_ports); i++) @@ -184,10 +184,10 @@ struct Clk2fflogicPass : public Pass { continue; log("Modifying write port %d on memory %s.%s: CLK=%s, A=%s, D=%s\n", - i, log_id(module), log_id(mem.memid), log_signal(port.clk), + i, module, mem.memid.unescape(), log_signal(port.clk), log_signal(port.addr), log_signal(port.data)); - Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#past_clk#%s", log_id(mem.memid), i, log_signal(port.clk)))); + Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#past_clk#%s", mem.memid.unescape(), i, log_signal(port.clk)))); past_clk->attributes[ID::init] = port.clk_polarity ? State::S1 : State::S0; module->addFf(NEW_ID, port.clk, past_clk); @@ -203,13 +203,13 @@ struct Clk2fflogicPass : public Pass { SigSpec clock_edge = module->Eqx(NEW_ID, {port.clk, SigSpec(past_clk)}, clock_edge_pattern); - SigSpec en_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#en_q", log_id(mem.memid), i)), GetSize(port.en)); + SigSpec en_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#en_q", mem.memid.unescape(), i)), GetSize(port.en)); module->addFf(NEW_ID, port.en, en_q); - SigSpec addr_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#addr_q", log_id(mem.memid), i)), GetSize(port.addr)); + SigSpec addr_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#addr_q", mem.memid.unescape(), i)), GetSize(port.addr)); module->addFf(NEW_ID, port.addr, addr_q); - SigSpec data_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#data_q", log_id(mem.memid), i)), GetSize(port.data)); + SigSpec data_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#data_q", mem.memid.unescape(), i)), GetSize(port.data)); module->addFf(NEW_ID, port.data, data_q); port.clk = State::S0; @@ -291,16 +291,16 @@ struct Clk2fflogicPass : public Pass { if (ff.has_clk) { log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_clk), log_signal(ff.sig_d), log_signal(ff.sig_q)); } else if (ff.has_aload) { log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q)); } else { // $sr. log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q)); } diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index 1a68776ff..ff1ae2628 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -93,7 +93,7 @@ struct CutpointPass : public Pass { for (auto module : design->all_selected_modules()) { if (module->is_selected_whole()) { - log("Making all outputs of module %s cut points, removing module contents.\n", log_id(module)); + log("Making all outputs of module %s cut points, removing module contents.\n", module); module->new_connections(std::vector()); for (auto cell : vector(module->cells())) module->remove(cell); @@ -125,7 +125,7 @@ struct CutpointPass : public Pass { for (auto cell : module->selected_cells()) { if (cell->type == ID($anyseq)) continue; - log("Removing cell %s.%s, making all cell outputs cutpoints.\n", log_id(module), log_id(cell)); + log("Removing cell %s.%s, making all cell outputs cutpoints.\n", module, cell); for (auto &conn : cell->connections()) { if (cell->output(conn.first)) { bool do_cut = true; @@ -171,7 +171,7 @@ struct CutpointPass : public Pass { for (auto wire : module->selected_wires()) { if (wire->port_output) { - log("Making output wire %s.%s a cutpoint.\n", log_id(module), log_id(wire)); + log("Making output wire %s.%s a cutpoint.\n", module, wire); Wire *new_wire = module->addWire(NEW_ID, wire); module->swap_names(wire, new_wire); module->connect(new_wire, flag_undef ? Const(State::Sx, GetSize(new_wire)) : module->Anyseq(NEW_ID, GetSize(new_wire))); @@ -180,7 +180,7 @@ struct CutpointPass : public Pass { wire->port_output = false; continue; } - log("Making wire %s.%s a cutpoint.\n", log_id(module), log_id(wire)); + log("Making wire %s.%s a cutpoint.\n", module, wire); for (auto bit : sigmap(wire)) cutpoint_bits.insert(bit); } diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc index b0eaaca22..a192fba9b 100644 --- a/passes/sat/eval.cc +++ b/passes/sat/eval.cc @@ -149,7 +149,7 @@ struct VlogHammerReporter for (auto c : module->cells()) if (!satgen.importCell(c)) - log_error("Failed to import cell %s (type %s) to SAT database.\n", log_id(c->name), log_id(c->type)); + log_error("Failed to import cell %s (type %s) to SAT database.\n", c->name.unescape(), c->type.unescape()); ez->assume(satgen.signals_eq(recorded_set_vars, recorded_set_vals)); @@ -262,21 +262,21 @@ struct VlogHammerReporter if (module == modules.front()) { RTLIL::SigSpec sig(wire); if (!ce.eval(sig)) - log_error("Can't read back value for port %s!\n", log_id(inputs[i])); + log_error("Can't read back value for port %s!\n", inputs[i].unescape()); input_pattern_list += stringf(" %s", sig.as_const().as_string()); - log("++PAT++ %d %s %s #\n", idx, log_id(inputs[i]), sig.as_const().as_string()); + log("++PAT++ %d %s %s #\n", idx, inputs[i].unescape(), sig.as_const().as_string()); } } if (module->wire(ID(y)) == nullptr) - log_error("No output wire (y) found in module %s!\n", log_id(module->name)); + log_error("No output wire (y) found in module %s!\n", module->name.unescape()); RTLIL::SigSpec sig(module->wire(ID(y))); RTLIL::SigSpec undef; while (!ce.eval(sig, undef)) { - // log_error("Evaluation of y in module %s failed: sig=%s, undef=%s\n", log_id(module->name), log_signal(sig), log_signal(undef)); - log_warning("Setting signal %s in module %s to undef.\n", log_signal(undef), log_id(module->name)); + // log_error("Evaluation of y in module %s failed: sig=%s, undef=%s\n", module, log_signal(sig), log_signal(undef)); + log_warning("Setting signal %s in module %s to undef.\n", log_signal(undef), module->name.unescape()); ce.set(undef, RTLIL::Const(RTLIL::State::Sx, undef.size())); } @@ -288,7 +288,7 @@ struct VlogHammerReporter sat_check(module, recorded_set_vars, recorded_set_vals, sig, true); } else if (rtl_sig.size() > 0) { if (rtl_sig.size() != sig.size()) - log_error("Output (y) has a different width in module %s compared to rtl!\n", log_id(module->name)); + log_error("Output (y) has a different width in module %s compared to rtl!\n", module->name.unescape()); for (int i = 0; i < GetSize(sig); i++) if (rtl_sig[i] == RTLIL::State::Sx) sig[i] = RTLIL::State::Sx; @@ -319,10 +319,10 @@ struct VlogHammerReporter RTLIL::IdString esc_name = RTLIL::escape_id(name); for (auto mod : modules) { if (mod->wire(esc_name) == nullptr) - log_error("Can't find input %s in module %s!\n", name, log_id(mod->name)); + log_error("Can't find input %s in module %s!\n", name, mod->name.unescape()); RTLIL::Wire *port = mod->wire(esc_name); if (!port->port_input || port->port_output) - log_error("Wire %s in module %s is not an input!\n", name, log_id(mod->name)); + log_error("Wire %s in module %s is not an input!\n", name, mod->name.unescape()); if (width >= 0 && width != port->width) log_error("Port %s has different sizes in the different modules!\n", name); width = port->width; @@ -443,7 +443,7 @@ struct EvalPass : public Pass { for (auto mod : design->selected_modules()) { if (module) log_cmd_error("Only one module must be selected for the EVAL pass! (selected: %s and %s)\n", - log_id(module->name), log_id(mod->name)); + module->name.unescape(), mod->name.unescape()); module = mod; } if (module == NULL) diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index 1e975db0f..ef00a6956 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -210,7 +210,7 @@ void create_dff_dq_map(std::map &map, RTLIL::Mo RTLIL::Wire *add_new_wire(RTLIL::Module *module, RTLIL::IdString name, int width = 1) { if (module->count_id(name)) - log_error("Attempting to create wire %s, but a wire of this name exists already! Hint: Try another value for -sep.\n", log_id(name)); + log_error("Attempting to create wire %s, but a wire of this name exists already! Hint: Try another value for -sep.\n", name.unescape()); return module->addWire(name, width); } @@ -673,7 +673,7 @@ struct ExposePass : public Pass { } for (auto cell : delete_cells) { - log("Removing cell: %s/%s (%s)\n", log_id(module), log_id(cell), log_id(cell->type)); + log("Removing cell: %s/%s (%s)\n", module, cell, cell->type.unescape()); module->remove(cell); } } diff --git a/passes/sat/fmcombine.cc b/passes/sat/fmcombine.cc index 505526c14..27a153921 100644 --- a/passes/sat/fmcombine.cc +++ b/passes/sat/fmcombine.cc @@ -77,7 +77,7 @@ struct FmcombineWorker void import_hier_cell(Cell *cell) { if (!cell->parameters.empty()) - log_cmd_error("Cell %s.%s has unresolved instance parameters.\n", log_id(original), log_id(cell)); + log_cmd_error("Cell %s.%s has unresolved instance parameters.\n", original, cell); FmcombineWorker sub_worker(design, cell->type, opts); sub_worker.generate(); @@ -95,11 +95,11 @@ struct FmcombineWorker void generate() { if (design->module(combined_type)) { - // log("Combined module %s already exists.\n", log_id(combined_type)); + // log("Combined module %s already exists.\n", combined_type.unescape()); return; } - log("Generating combined module %s from module %s.\n", log_id(combined_type), log_id(orig_type)); + log("Generating combined module %s from module %s.\n", combined_type.unescape(), orig_type.unescape()); module = design->addModule(combined_type); for (auto wire : original->wires()) { @@ -332,15 +332,15 @@ struct FmcombinePass : public Pass { module = design->module(module_name); if (module == nullptr) - log_cmd_error("Module %s not found.\n", log_id(module_name)); + log_cmd_error("Module %s not found.\n", module_name.unescape()); gold_cell = module->cell(gold_name); if (gold_cell == nullptr) - log_cmd_error("Gold cell %s not found in module %s.\n", log_id(gold_name), log_id(module)); + log_cmd_error("Gold cell %s not found in module %s.\n", gold_name.unescape(), module); gate_cell = module->cell(gate_name); if (gate_cell == nullptr) - log_cmd_error("Gate cell %s not found in module %s.\n", log_id(gate_name), log_id(module)); + log_cmd_error("Gate cell %s not found in module %s.\n", gate_name.unescape(), module); } else { @@ -363,13 +363,13 @@ struct FmcombinePass : public Pass { FmcombineWorker worker(design, gold_cell->type, opts); worker.generate(); - IdString combined_cell_name = module->uniquify(stringf("\\%s_%s", log_id(gold_cell), log_id(gate_cell))); + IdString combined_cell_name = module->uniquify(stringf("\\%s_%s", gold_cell, gate_cell)); Cell *cell = module->addCell(combined_cell_name, worker.combined_type); cell->attributes = gold_cell->attributes; cell->add_strpool_attribute(ID::src, gate_cell->get_strpool_attribute(ID::src)); - log("Combining cells %s and %s in module %s into new cell %s.\n", log_id(gold_cell), log_id(gate_cell), log_id(module), log_id(cell)); + log("Combining cells %s and %s in module %s into new cell %s.\n", gold_cell, gate_cell, module, cell); for (auto &conn : gold_cell->connections()) cell->setPort(conn.first.str() + "_gold", conn.second); diff --git a/passes/sat/formalff.cc b/passes/sat/formalff.cc index 452e0e59b..a2500bde4 100644 --- a/passes/sat/formalff.cc +++ b/passes/sat/formalff.cc @@ -402,7 +402,7 @@ struct PropagateWorker sigmap.apply(bit); if (replaced_clk_bits.count(bit)) log_error("derived signal %s driven by %s (%s) from module %s is used as clock, derived clocks are only supported with clk2fflogic.\n", - log_signal(bit), log_id(cell->name), log_id(cell->type), log_id(module)); + log_signal(bit), cell->name.unescape(), cell->type.unescape(), module); } } } @@ -436,7 +436,7 @@ struct PropagateWorker if (it != replaced_clk_bits.end()) { if (it->second != polarity) log_error("signal %s from module %s is used as clock with different polarities, run clk2fflogic instead.\n", - log_signal(bit), log_id(module)); + log_signal(bit), module); return; } @@ -659,7 +659,7 @@ struct FormalFfPass : public Pass { // XXX $check $print } - log_debug("%s has %d clk bits\n", log_id(module), GetSize(clk_bits)); + log_debug("%s has %d clk bits\n", module, GetSize(clk_bits)); for (auto port : module->ports) { Wire *wire = module->wire(port); @@ -675,7 +675,7 @@ struct FormalFfPass : public Pass { } } } - log_debug("%s has %d non-input clk bits\n", log_id(module), GetSize(clk_bits)); + log_debug("%s has %d non-input clk bits\n", module, GetSize(clk_bits)); if (clk_bits.empty()) continue; @@ -687,21 +687,21 @@ struct FormalFfPass : public Pass { vector &clocked_cells = clk_bit.second; if (!clk.is_wire()) { - log_debug("constant clk bit %s.%s\n", log_id(module), log_signal(SigSpec(clk))); + log_debug("constant clk bit %s.%s\n", module, log_signal(SigSpec(clk))); continue; } if (input_bits.count(clk)) { - log_debug("input clk bit %s.%s\n", log_id(module), log_signal(SigSpec(clk))); + log_debug("input clk bit %s.%s\n", module, log_signal(SigSpec(clk))); continue; } auto found = modwalker.signal_drivers.find(clk); if (found == modwalker.signal_drivers.end() || found->second.empty()) { - log_debug("undriven clk bit %s.%s\n", log_id(module), log_signal(SigSpec(clk))); + log_debug("undriven clk bit %s.%s\n", module, log_signal(SigSpec(clk))); continue; } if (found->second.size() > 1) { - log_debug("multiple drivers for clk bit %s.%s\n", log_id(module), log_signal(SigSpec(clk))); + log_debug("multiple drivers for clk bit %s.%s\n", module, log_signal(SigSpec(clk))); continue; } @@ -711,9 +711,9 @@ struct FormalFfPass : public Pass { pol_clk ? driver.cell->type.in(ID($and), ID($_AND_)) : driver.cell->type.in(ID($or), ID($_OR_)); if (!is_gate) { - log_debug("unsupported gating logic %s.%s (%s) for clock %s %s.%s\n", log_id(module), - log_id(driver.cell), log_id(driver.cell->type), pol_clk ? "posedge" : "negedge", - log_id(module), log_signal(SigSpec(clk))); + log_debug("unsupported gating logic %s.%s (%s) for clock %s %s.%s\n", module, + driver.cell, driver.cell->type.unescape(), pol_clk ? "posedge" : "negedge", + module, log_signal(SigSpec(clk))); continue; } @@ -724,28 +724,28 @@ struct FormalFfPass : public Pass { for (int i = 0; i < 2; i++) { std::swap(gate_clock, gate_enable); - log_debug("clock %s.%s for gated clk bit %s.%s\n", log_id(module), log_signal(SigSpec(gate_clock)), - log_id(module), log_signal(SigSpec(clk))); - log_debug("enable %s.%s for gated clk bit %s.%s\n", log_id(module), log_signal(SigSpec(gate_enable)), - log_id(module), log_signal(SigSpec(clk))); + log_debug("clock %s.%s for gated clk bit %s.%s\n", module, log_signal(SigSpec(gate_clock)), + module, log_signal(SigSpec(clk))); + log_debug("enable %s.%s for gated clk bit %s.%s\n", module, log_signal(SigSpec(gate_enable)), + module, log_signal(SigSpec(clk))); found = modwalker.signal_drivers.find(gate_enable); if (found == modwalker.signal_drivers.end() || found->second.empty()) { - log_debug("undriven gate enable %s.%s of gated clk bit %s.%s\n", log_id(module), - log_signal(SigSpec(gate_enable)), log_id(module), log_signal(SigSpec(clk))); + log_debug("undriven gate enable %s.%s of gated clk bit %s.%s\n", module, + log_signal(SigSpec(gate_enable)), module, log_signal(SigSpec(clk))); continue; } if (found->second.size() > 1) { - log_debug("multiple drivers for gate enable %s.%s of gated clk bit %s.%s\n", log_id(module), - log_signal(SigSpec(gate_enable)), log_id(module), log_signal(SigSpec(clk))); + log_debug("multiple drivers for gate enable %s.%s of gated clk bit %s.%s\n", module, + log_signal(SigSpec(gate_enable)), module, log_signal(SigSpec(clk))); continue; } auto gate_driver = *found->second.begin(); if (!gate_driver.cell->is_builtin_ff()) { - log_debug("non FF driver for gate enable %s.%s of gated clk bit %s.%s\n", log_id(module), - log_signal(SigSpec(gate_enable)), log_id(module), log_signal(SigSpec(clk))); + log_debug("non FF driver for gate enable %s.%s of gated clk bit %s.%s\n", module, + log_signal(SigSpec(gate_enable)), module, log_signal(SigSpec(clk))); continue; } @@ -753,8 +753,8 @@ struct FormalFfPass : public Pass { if (ff.has_gclk || ff.has_ce || ff.has_sr || ff.has_srst || ff.has_arst || (ff.has_aload && ff.has_clk)) { log_debug( "FF driver for gate enable %s.%s of gated clk bit %s.%s has incompatible type: %s\n", - log_id(module), log_signal(SigSpec(gate_enable)), log_id(module), log_signal(SigSpec(clk)), - log_id(gate_driver.cell->type)); + module, log_signal(SigSpec(gate_enable)), module, log_signal(SigSpec(clk)), + gate_driver.cell->type.unescape()); continue; } @@ -767,11 +767,11 @@ struct FormalFfPass : public Pass { ff.sig_d = ff.sig_ad; } - if (!ff.has_clk || sigmap(ff.sig_clk) != gate_clock || ff.pol_clk != pol_clk) { + if (!ff.has_clk || sigmap(ff.sig_clk).as_bit() != gate_clock || ff.pol_clk != pol_clk) { log_debug("FF driver for gate enable %s.%s of gated clk bit %s.%s has incompatible clocking: " "%s %s.%s\n", - log_id(module), log_signal(SigSpec(gate_enable)), log_id(module), - log_signal(SigSpec(clk)), ff.pol_clk ? "posedge" : "negedge", log_id(module), + module, log_signal(SigSpec(gate_enable)), module, + log_signal(SigSpec(clk)), ff.pol_clk ? "posedge" : "negedge", module, log_signal(SigSpec(ff.sig_clk))); continue; } @@ -781,8 +781,8 @@ struct FormalFfPass : public Pass { log_debug("found clock gate, rewriting %d cells\n", GetSize(clocked_cells)); for (auto clocked_cell : clocked_cells) { - log_debug("rewriting cell %s.%s (%s)\n", log_id(module), log_id(clocked_cell), - log_id(clocked_cell->type)); + log_debug("rewriting cell %s.%s (%s)\n", module, clocked_cell, + clocked_cell->type.unescape()); if (clocked_cell->is_builtin_ff()) { @@ -798,7 +798,7 @@ struct FormalFfPass : public Pass { auto &mem = memories.at(clocked_cell->name); bool changed = false; for (auto &rd_port : mem.rd_ports) { - if (rd_port.clk_enable && rd_port.clk == clk && rd_port.clk_polarity == pol_clk) { + if (rd_port.clk_enable && rd_port.clk.as_bit() == clk && rd_port.clk_polarity == pol_clk) { log_debug("patching rd port\n"); changed = true; rd_port.clk = gate_clock; @@ -808,7 +808,7 @@ struct FormalFfPass : public Pass { } } for (auto &wr_port : mem.wr_ports) { - if (wr_port.clk_enable && wr_port.clk == clk && wr_port.clk_polarity == pol_clk) { + if (wr_port.clk_enable && wr_port.clk.as_bit() == clk && wr_port.clk_polarity == pol_clk) { log_debug("patching wr port\n"); changed = true; wr_port.clk = gate_clock; @@ -855,7 +855,7 @@ struct FormalFfPass : public Pass { if (ff.val_init != before) { log("Setting unused undefined initial value of %s.%s (%s) from %s to %s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_const(before), log_const(ff.val_init)); worker.initvals.set_init(ff.sig_q, ff.val_init); } @@ -892,10 +892,10 @@ struct FormalFfPass : public Pass { if (flag_clk2ff && ff.has_clk) { if (ff.sig_clk.is_fully_const()) log_error("Const CLK on %s (%s) from module %s, run async2sync first.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type, module); if (ff.has_aload || ff.has_arst || ff.has_sr) log_error("Async inputs on %s (%s) from module %s, run async2sync first.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); auto clk_wire = ff.sig_clk.is_wire() ? ff.sig_clk.as_wire() : nullptr; @@ -912,7 +912,7 @@ struct FormalFfPass : public Pass { if (!attr.empty() && attr != clk_polarity) log_error("CLK %s on %s (%s) from module %s also used with opposite polarity, run clk2fflogic instead.\n", - log_id(clk_wire), log_id(cell), log_id(cell->type), log_id(module)); + clk_wire, cell, cell->type.unescape(), module); attr = clk_polarity; clk_wire->set_bool_attribute(ID::keep); diff --git a/passes/sat/mutate.cc b/passes/sat/mutate.cc index 79ffcd88d..63a8de277 100644 --- a/passes/sat/mutate.cc +++ b/passes/sat/mutate.cc @@ -558,7 +558,7 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena if (opts.none) { string str = "mutate"; if (!opts.ctrl_name.empty()) - str += stringf(" -ctrl %s %d %d", log_id(opts.ctrl_name), opts.ctrl_width, ctrl_value++); + str += stringf(" -ctrl %s %d %d", opts.ctrl_name.unescape(), opts.ctrl_width, ctrl_value++); str += " -mode none"; if (filename.empty()) log("%s\n", str); @@ -569,20 +569,20 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena for (auto &entry : database) { string str = "mutate"; if (!opts.ctrl_name.empty()) - str += stringf(" -ctrl %s %d %d", log_id(opts.ctrl_name), opts.ctrl_width, ctrl_value++); + str += stringf(" -ctrl %s %d %d", opts.ctrl_name.unescape(), opts.ctrl_width, ctrl_value++); str += stringf(" -mode %s", entry.mode); if (!entry.module.empty()) - str += stringf(" -module %s", log_id(entry.module)); + str += stringf(" -module %s", entry.module.unescape()); if (!entry.cell.empty()) - str += stringf(" -cell %s", log_id(entry.cell)); + str += stringf(" -cell %s", entry.cell.unescape()); if (!entry.port.empty()) - str += stringf(" -port %s", log_id(entry.port)); + str += stringf(" -port %s", entry.port.unescape()); if (entry.portbit >= 0) str += stringf(" -portbit %d", entry.portbit); if (entry.ctrlbit >= 0) str += stringf(" -ctrlbit %d", entry.ctrlbit); if (!entry.wire.empty()) - str += stringf(" -wire %s", log_id(entry.wire)); + str += stringf(" -wire %s", entry.wire.unescape()); if (entry.wirebit >= 0) str += stringf(" -wirebit %d", entry.wirebit); for (auto &s : entry.src) @@ -600,7 +600,7 @@ SigSpec mutate_ctrl_sig(Module *module, IdString name, int width) if (ctrl_wire == nullptr) { - log("Adding ctrl port %s to module %s.\n", log_id(name), log_id(module)); + log("Adding ctrl port %s to module %s.\n", name.unescape(), module); ctrl_wire = module->addWire(name, width); ctrl_wire->port_input = true; @@ -614,7 +614,7 @@ SigSpec mutate_ctrl_sig(Module *module, IdString name, int width) SigSpec ctrl = mutate_ctrl_sig(mod, name, width); - log("Connecting ctrl port to cell %s in module %s.\n", log_id(cell), log_id(mod)); + log("Connecting ctrl port to cell %s in module %s.\n", cell, mod); cell->setPort(name, ctrl); } } @@ -652,13 +652,13 @@ void mutate_inv(Design *design, const mutate_opts_t &opts) if (cell->input(opts.port)) { - log("Add input inverter at %s.%s.%s[%d].\n", log_id(module), log_id(cell), log_id(opts.port), opts.portbit); + log("Add input inverter at %s.%s.%s[%d].\n", module, cell, opts.port.unescape(), opts.portbit); SigBit outbit = module->Not(NEW_ID, bit); bit = mutate_ctrl_mux(module, opts, bit, outbit); } else { - log("Add output inverter at %s.%s.%s[%d].\n", log_id(module), log_id(cell), log_id(opts.port), opts.portbit); + log("Add output inverter at %s.%s.%s[%d].\n", module, cell, opts.port.unescape(), opts.portbit); SigBit inbit = module->addWire(NEW_ID); SigBit outbit = module->Not(NEW_ID, inbit); module->connect(bit, mutate_ctrl_mux(module, opts, inbit, outbit)); @@ -680,13 +680,13 @@ void mutate_const(Design *design, const mutate_opts_t &opts, bool one) if (cell->input(opts.port)) { - log("Add input constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit); + log("Add input constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, module, cell, opts.port.unescape(), opts.portbit); SigBit outbit = one ? State::S1 : State::S0; bit = mutate_ctrl_mux(module, opts, bit, outbit); } else { - log("Add output constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit); + log("Add output constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, module, cell, opts.port.unescape(), opts.portbit); SigBit inbit = module->addWire(NEW_ID); SigBit outbit = one ? State::S1 : State::S0; module->connect(bit, mutate_ctrl_mux(module, opts, inbit, outbit)); @@ -709,13 +709,13 @@ void mutate_cnot(Design *design, const mutate_opts_t &opts, bool one) if (cell->input(opts.port)) { - log("Add input cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit, opts.ctrlbit); + log("Add input cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, module, cell, opts.port.unescape(), opts.portbit, opts.ctrlbit); SigBit outbit = one ? module->Xor(NEW_ID, bit, ctrl) : module->Xnor(NEW_ID, bit, ctrl); bit = mutate_ctrl_mux(module, opts, bit, outbit); } else { - log("Add output cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit, opts.ctrlbit); + log("Add output cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, module, cell, opts.port.unescape(), opts.portbit, opts.ctrlbit); SigBit inbit = module->addWire(NEW_ID); SigBit outbit = one ? module->Xor(NEW_ID, inbit, ctrl) : module->Xnor(NEW_ID, inbit, ctrl); module->connect(bit, mutate_ctrl_mux(module, opts, inbit, outbit)); @@ -947,26 +947,26 @@ struct MutatePass : public Pass { Module *module = design->module(opts.module); if (module == nullptr) - log_cmd_error("Module %s not found.\n", log_id(opts.module)); + log_cmd_error("Module %s not found.\n", opts.module.unescape()); if (opts.cell.empty()) log_cmd_error("Missing -cell argument.\n"); Cell *cell = module->cell(opts.cell); if (cell == nullptr) - log_cmd_error("Cell %s not found in module %s.\n", log_id(opts.cell), log_id(opts.module)); + log_cmd_error("Cell %s not found in module %s.\n", opts.cell.unescape(), opts.module.unescape()); if (opts.port.empty()) log_cmd_error("Missing -port argument.\n"); if (!cell->hasPort(opts.port)) - log_cmd_error("Port %s not found on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell)); + log_cmd_error("Port %s not found on cell %s.%s.\n", opts.port.unescape(), opts.module.unescape(), opts.cell.unescape()); if (opts.portbit < 0) log_cmd_error("Missing -portbit argument.\n"); if (GetSize(cell->getPort(opts.port)) <= opts.portbit) - log_cmd_error("Out-of-range -portbit argument for port %s on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell)); + log_cmd_error("Out-of-range -portbit argument for port %s on cell %s.%s.\n", opts.port.unescape(), opts.module.unescape(), opts.cell.unescape()); if (opts.mode == "inv") { mutate_inv(design, opts); @@ -982,7 +982,7 @@ struct MutatePass : public Pass { log_cmd_error("Missing -ctrlbit argument.\n"); if (GetSize(cell->getPort(opts.port)) <= opts.ctrlbit) - log_cmd_error("Out-of-range -ctrlbit argument for port %s on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell)); + log_cmd_error("Out-of-range -ctrlbit argument for port %s on cell %s.%s.\n", opts.port.unescape(), opts.module.unescape(), opts.cell.unescape()); if (opts.mode == "cnot0" || opts.mode == "cnot1") { mutate_cnot(design, opts, opts.mode == "cnot1"); diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc index b011227e2..b892683a8 100644 --- a/passes/sat/qbfsat.cc +++ b/passes/sat/qbfsat.cc @@ -597,7 +597,7 @@ struct QbfSatPass : public Pass { RTLIL::Module *module = nullptr; for (auto mod : design->selected_modules()) { if (module) - log_cmd_error("Only one module must be selected for the QBF-SAT pass! (selected: %s and %s)\n", log_id(module), log_id(mod)); + log_cmd_error("Only one module must be selected for the QBF-SAT pass! (selected: %s and %s)\n", module, mod); module = mod; } if (module == nullptr) diff --git a/passes/sat/qbfsat.h b/passes/sat/qbfsat.h index 253cecce4..3441b7819 100644 --- a/passes/sat/qbfsat.h +++ b/passes/sat/qbfsat.h @@ -170,7 +170,6 @@ struct QbfSolutionType { std::smatch m; bool sat_regex_found = false; bool unsat_regex_found = false; - dict hole_value_recovered; for (const std::string &x : stdout_lines) { if(std::regex_search(x, m, hole_value_regex)) { std::string loc = m[1].str(); diff --git a/passes/sat/recover_names.cc b/passes/sat/recover_names.cc index 7939a64e0..e2c93df65 100644 --- a/passes/sat/recover_names.cc +++ b/passes/sat/recover_names.cc @@ -641,8 +641,8 @@ struct RecoverNamesWorker { for (auto gate_bit : gate_bits) { if (solved_gate.count(gate_bit.bit)) continue; - log_debug(" attempting to prove %s[%d] == %s%s[%d]\n", log_id(gold_bit.name), gold_bit.bit, - gate_bit.inverted ? "" : "!", log_id(gate_bit.bit.name), gate_bit.bit.bit); + log_debug(" attempting to prove %s[%d] == %s%s[%d]\n", gold_bit.name.unescape(), gold_bit.bit, + gate_bit.inverted ? "" : "!", gate_bit.bit.name.unescape(), gate_bit.bit.bit); if (!prove_equiv(gold_worker, gate_worker, gold_anchors, gate_anchors, gold_bit, gate_bit.bit, gate_bit.inverted)) continue; log_debug(" success!\n"); @@ -660,7 +660,7 @@ struct RecoverNamesWorker { break; } } - log("Recovered %d net name pairs in module `%s' out.\n", GetSize(gate2gold), log_id(gate_mod)); + log("Recovered %d net name pairs in module `%s' out.\n", GetSize(gate2gold), gate_mod); gate_worker.do_rename(gold_mod, gate2gold, buffer_types); } diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index 9988eef62..accfe0399 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -1369,7 +1369,7 @@ struct SatPass : public Pass { RTLIL::Module *module = NULL; for (auto mod : design->selected_modules()) { if (module) - log_cmd_error("Only one module must be selected for the SAT pass! (selected: %s and %s)\n", log_id(module), log_id(mod)); + log_cmd_error("Only one module must be selected for the SAT pass! (selected: %s and %s)\n", module, mod); module = mod; } if (module == NULL) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index f237daeff..23af70fa5 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -53,9 +53,23 @@ static const std::map g_units = { "zs", -21 }, }; -static double stringToTime(std::string str) +struct scaled_time { + uint64_t time; + int scale; // exponent of 10, e.g. -6 = us, -9 = ns + bool end; +}; + +static uint64_t pow10(int n) { - if (str=="END") return -1; + int r = 1; + while (n--) + r *= 10; + return r; +} + +static scaled_time stringToTime(std::string str) +{ + if (str=="END") return {1, 0, true}; char *endptr; long value = strtol(str.c_str(), &endptr, 10); @@ -66,7 +80,7 @@ static double stringToTime(std::string str) if (value < 0) log_error("Time value '%s' must be positive\n", str); - return value * pow(10.0, g_units.at(endptr)); + return {(unsigned long)value, g_units.at(endptr), false}; } struct SimWorker; @@ -110,8 +124,8 @@ struct SimShared bool hdlname = false; int rstlen = 1; FstData *fst = nullptr; - double start_time = 0; - double stop_time = -1; + scaled_time start_time = {0, 0, false}; + scaled_time stop_time = {1, 0, true}; SimulationMode sim_mode = SimulationMode::sim; bool cycles_set = false; std::vector> outputfiles; @@ -236,11 +250,11 @@ struct SimInstance if (module->get_blackbox_attribute(true)) log_error("Cannot simulate blackbox module %s (instantiated at %s).\n", - log_id(module->name), hiername().c_str()); + module->name.unescape(), hiername().c_str()); if (module->has_processes()) log_error("Found processes in simulation hierarchy (in module %s at %s). Run 'proc' first.\n", - log_id(module), hiername().c_str()); + module, hiername().c_str()); if (parent) { log_assert(parent->children.count(instance) == 0); @@ -399,9 +413,9 @@ struct SimInstance std::string hiername() const { if (instance != nullptr) - return parent->hiername() + "." + log_id(instance->name); + return parent->hiername() + "." + instance->name.unescape(); - return log_id(module->name); + return module->name.unescape(); } vector witness_full_path() const @@ -506,7 +520,7 @@ struct SimInstance { auto &state = mem_database[memid]; if (offset >= state.mem->size * state.mem->width) - log_error("Addressing out of bounds bit %d/%d of memory %s\n", offset, state.mem->size * state.mem->width, log_id(memid)); + log_error("Addressing out of bounds bit %d/%d of memory %s\n", offset, state.mem->size * state.mem->width, memid.unescape()); if (state.data[offset] != data) { state.data.set(offset, data); dirty_memories.insert(memid); @@ -559,7 +573,7 @@ struct SimInstance if (has_y) sig_y = cell->getPort(ID::Y); if (shared->debug) - log("[%s] eval %s (%s)\n", hiername(), log_id(cell), log_id(cell->type)); + log("[%s] eval %s (%s)\n", hiername(), cell, cell->type.unescape()); bool err = false; RTLIL::Const eval_state; @@ -579,7 +593,7 @@ struct SimInstance err = true; if (err) - log_warning("Unsupported evaluable cell type: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); + log_warning("Unsupported evaluable cell type: %s (%s.%s)\n", cell->type.unescape(), module, cell); else set_state(sig_y, eval_state); return; @@ -588,7 +602,7 @@ struct SimInstance if (cell->type == ID($print)) return; - log_error("Unsupported cell type: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); + log_error("Unsupported cell type: %s (%s.%s)\n", cell->type.unescape(), module, cell); } void update_memory(IdString id) { @@ -602,7 +616,7 @@ struct SimInstance Const data = Const(State::Sx, mem.width << port.wide_log2); if (port.clk_enable) - log_error("Memory %s.%s has clocked read ports. Run 'memory_nordff' to transform the circuit to remove those.\n", log_id(module), log_id(mem.memid)); + log_error("Memory %s.%s has clocked read ports. Run 'memory_nordff' to transform the circuit to remove those.\n", module, mem.memid.unescape()); if (addr.is_fully_def()) { int addr_int = addr.as_int(); @@ -805,14 +819,14 @@ struct SimInstance log_assert(cell->module == module); bool has_src = cell->has_attribute(ID::src); log("%s %s%s\n", opening_verbiage, - log_id(cell), has_src ? " at" : ""); + cell, has_src ? " at" : ""); log_source(cell); struct SimInstance *sim = this; while (sim->instance) { has_src = sim->instance->has_attribute(ID::src); - log(" in instance %s of module %s%s\n", log_id(sim->instance), - log_id(sim->instance->type), has_src ? " at" : ""); + log(" in instance %s of module %s%s\n", sim->instance, + sim->instance->type.unescape(), has_src ? " at" : ""); log_source(sim->instance); sim = sim->parent; } @@ -913,7 +927,7 @@ struct SimInstance { for (auto cell : formal_database) { - string label = log_id(cell); + string label = cell->name.unescape(); if (cell->attributes.count(ID::src)) label = cell->attributes.at(ID::src).decode_string(); @@ -925,17 +939,17 @@ struct SimInstance } if (cell->type == ID($cover) && en == State::S1 && a == State::S1) - log("Cover %s.%s (%s) reached.\n", hiername(), log_id(cell), label); + log("Cover %s.%s (%s) reached.\n", hiername(), cell, label); if (cell->type == ID($assume) && en == State::S1 && a != State::S1) - log("Assumption %s.%s (%s) failed.\n", hiername(), log_id(cell), label); + log("Assumption %s.%s (%s) failed.\n", hiername(), cell, label); if (cell->type == ID($assert) && en == State::S1 && a != State::S1) { log_cell_w_hierarchy("Failed assertion", cell); if (shared->serious_asserts) - log_error("Assertion %s.%s (%s) failed.\n", hiername(), log_id(cell), label); + log_error("Assertion %s.%s (%s) failed.\n", hiername(), cell, label); else - log_warning("Assertion %s.%s (%s) failed.\n", hiername(), log_id(cell), label); + log_warning("Assertion %s.%s (%s) failed.\n", hiername(), cell, label); } } } @@ -956,7 +970,7 @@ struct SimInstance { if (!ff_database.empty() || !mem_database.empty()) { if (wbmods.count(module)) - log_error("Instance %s of module %s is not unique: Writeback not possible. (Fix by running 'uniquify'.)\n", hiername(), log_id(module)); + log_error("Instance %s of module %s is not unique: Writeback not possible. (Fix by running 'uniquify'.)\n", hiername(), module); wbmods.insert(module); } @@ -1047,7 +1061,7 @@ struct SimInstance for (auto name : hdlname) exit_scope(); } else - register_signal(log_id(signal.first->name), GetSize(signal.first), signal.first, signal.second.id, registers.count(signal.first)!=0); + register_signal(signal.first->name.unescape().c_str(), GetSize(signal.first), signal.first, signal.second.id, registers.count(signal.first)!=0); } for (auto &trace_mem : trace_mem_database) @@ -1068,7 +1082,7 @@ struct SimInstance for (auto name : hdlname) enter_scope("\\" + name); } else { - signal_name = log_id(memid); + signal_name = memid.unescape(); } for (auto &trace_index : trace_mem.second) { @@ -1255,13 +1269,13 @@ struct SimInstance Const fst_val = Const::from_string(shared->fst->valueOf(item.second)); Const sim_val = get_state(item.first); if (sim_val.size()!=fst_val.size()) { - log_warning("Signal '%s.%s' size is different in gold and gate.\n", scope, log_id(item.first)); + log_warning("Signal '%s.%s' size is different in gold and gate.\n", scope, item.first); continue; } if (shared->sim_mode == SimulationMode::gate && !fst_val.is_fully_def()) { // FST data contains X for(int i=0;isim_mode == SimulationMode::gold && !sim_val.is_fully_def()) { // sim data contains X for(int i=0;imodule->wire(portname); if (w == nullptr) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); top->set_state(w, value); } @@ -1478,24 +1492,24 @@ struct SimWorker : SimShared { Wire *w = topmod->wire(portname); if (!w) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, log_id(portname)); + log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); fst_clock.push_back(id); } for (auto portname : clockn) { Wire *w = topmod->wire(portname); if (!w) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, log_id(portname)); + log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); fst_clock.push_back(id); } @@ -1514,27 +1528,27 @@ struct SimWorker : SimShared uint64_t startCount = 0; uint64_t stopCount = 0; - if (start_time==0) { - if (start_time < fst->getStartTime()) + if (start_time.time == 0) { + if (start_time.time < fst->getStartTime()) log_warning("Start time is before simulation file start time\n"); startCount = fst->getStartTime(); - } else if (start_time==-1) + } else if (start_time.end) startCount = fst->getEndTime(); else { - startCount = start_time / fst->getTimescale(); + startCount = start_time.time * pow10(start_time.scale - fst->getScale()); if (startCount > fst->getEndTime()) { startCount = fst->getEndTime(); log_warning("Start time is after simulation file end time\n"); } } - if (stop_time==0) { - if (stop_time < fst->getStartTime()) + if (stop_time.time == 0) { + if (stop_time.time < fst->getStartTime()) log_warning("Stop time is before simulation file start time\n"); stopCount = fst->getStartTime(); - } else if (stop_time==-1) + } else if (stop_time.end) stopCount = fst->getEndTime(); else { - stopCount = stop_time / fst->getTimescale(); + stopCount = stop_time.time * pow10(stop_time.scale - fst->getScale()); if (stopCount > fst->getEndTime()) { stopCount = fst->getEndTime(); log_warning("Stop time is after simulation file end time\n"); @@ -1616,7 +1630,7 @@ struct SimWorker : SimShared escaped_s = RTLIL::escape_id(cell_name(symbol)); Cell *c = topmod->cell(escaped_s); if (!c) - log_warning("Wire/cell %s not present in module %s\n",symbol,log_id(topmod)); + log_warning("Wire/cell %s not present in module %s\n",symbol,topmod); if (c->is_mem_cell()) { std::string memid = c->parameters.at(ID::MEMID).decode_string(); @@ -1815,7 +1829,7 @@ struct SimWorker : SimShared if (!w) { Cell *c = topmod->cell(escaped_s); if (!c) - log_warning("Wire/cell %s not present in module %s\n",log_id(escaped_s),log_id(topmod)); + log_warning("Wire/cell %s not present in module %s\n",escaped_s.unescape(),topmod); else if (c->type.in(ID($anyconst), ID($anyseq))) { SigSpec sig_y= c->getPort(ID::Y); if ((int)parts[1].size() != GetSize(sig_y)) @@ -1830,9 +1844,9 @@ struct SimWorker : SimShared } else { Cell *c = topmod->cell(escaped_s); if (!c) - log_error("Cell %s not present in module %s\n",log_id(escaped_s),log_id(topmod)); + log_error("Cell %s not present in module %s\n",escaped_s.unescape(),topmod); if (!c->is_mem_cell()) - log_error("Cell %s is not memory cell in module %s\n",log_id(escaped_s),log_id(topmod)); + log_error("Cell %s is not memory cell in module %s\n",escaped_s.unescape(),topmod); Const addr = Const::from_string(parts[1].substr(1,parts[1].size()-2)); Const data = Const::from_string(parts[2]); @@ -2063,13 +2077,13 @@ struct SimWorker : SimShared json.entry("version", "Yosys sim summary"); json.entry("generator", yosys_maybe_version()); json.entry("steps", step); - json.entry("top", log_id(top->module->name)); + json.entry("top", top->module->name.unescape()); json.name("assertions"); json.begin_array(); for (auto &assertion : triggered_assertions) { json.begin_object(); json.entry("step", assertion.step); - json.entry("type", log_id(assertion.cell->type)); + json.entry("type", assertion.cell->type.unescape()); json.entry("path", assertion.instance->witness_full_path(assertion.cell)); auto src = assertion.cell->get_string_attribute(ID::src); if (!src.empty()) { @@ -2134,12 +2148,12 @@ struct SimWorker : SimShared { Wire *w = topmod->wire(portname); if (!w) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, log_id(portname)); + log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); fst_clock.push_back(id); clocks[w] = id; } @@ -2147,12 +2161,12 @@ struct SimWorker : SimShared { Wire *w = topmod->wire(portname); if (!w) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, log_id(portname)); + log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); fst_clock.push_back(id); clocks[w] = id; } @@ -2174,27 +2188,27 @@ struct SimWorker : SimShared uint64_t startCount = 0; uint64_t stopCount = 0; - if (start_time==0) { - if (start_time < fst->getStartTime()) + if (start_time.time == 0) { + if (start_time.time < fst->getStartTime()) log_warning("Start time is before simulation file start time\n"); startCount = fst->getStartTime(); - } else if (start_time==-1) + } else if (start_time.end) startCount = fst->getEndTime(); else { - startCount = start_time / fst->getTimescale(); + startCount = start_time.time * pow10(start_time.scale - fst->getScale()); if (startCount > fst->getEndTime()) { startCount = fst->getEndTime(); log_warning("Start time is after simulation file end time\n"); } } - if (stop_time==0) { - if (stop_time < fst->getStartTime()) + if (stop_time.time == 0) { + if (stop_time.time < fst->getStartTime()) log_warning("Stop time is before simulation file start time\n"); stopCount = fst->getStartTime(); - } else if (stop_time==-1) + } else if (stop_time.end) stopCount = fst->getEndTime(); else { - stopCount = stop_time / fst->getTimescale(); + stopCount = stop_time.time * pow10(stop_time.scale - fst->getScale()); if (stopCount > fst->getEndTime()) { stopCount = fst->getEndTime(); log_warning("Stop time is after simulation file end time\n"); @@ -2345,7 +2359,7 @@ struct VCDWriter : public OutputWriter vcdfile << stringf("$timescale %s $end\n", worker->timescale); worker->top->write_output_header( - [this](IdString name) { vcdfile << stringf("$scope module %s $end\n", log_id(name)); }, + [this](IdString name) { vcdfile << stringf("$scope module %s $end\n", name.unescape()); }, [this]() { vcdfile << stringf("$upscope $end\n");}, [this,use_signal](const char *name, int size, Wire *w, int id, bool is_reg) { if (!use_signal.at(id)) return; @@ -2411,7 +2425,7 @@ struct FSTWriter : public OutputWriter fstWriterSetRepackOnClose(fstfile, 1); worker->top->write_output_header( - [this](IdString name) { fstWriterSetScope(fstfile, FST_ST_VCD_MODULE, stringf("%s",log_id(name)).c_str(), nullptr); }, + [this](IdString name) { fstWriterSetScope(fstfile, FST_ST_VCD_MODULE, stringf("%s",name.unescape()).c_str(), nullptr); }, [this]() { fstWriterSetUpscope(fstfile); }, [this,use_signal](const char *name, int size, Wire *w, int id, bool is_reg) { if (!use_signal.at(id)) return; @@ -2474,7 +2488,7 @@ struct AIWWriter : public OutputWriter RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); Wire *w = worker->top->module->wire(escaped_s); if (!w) - log_error("Wire %s not present in module %s\n",log_id(escaped_s),log_id(worker->top->module)); + log_error("Wire %s not present in module %s\n",escaped_s.unescape(),worker->top->module); if (index < w->start_offset || index > w->start_offset + w->width) log_error("Index %d for wire %s is out of range\n", index, log_signal(w)); if (type == "input") { diff --git a/passes/sat/supercover.cc b/passes/sat/supercover.cc index f1b3ad09c..a2192dc8a 100644 --- a/passes/sat/supercover.cc +++ b/passes/sat/supercover.cc @@ -64,7 +64,7 @@ struct SupercoverPass : public Pass { pool handled_bits; int cnt_wire = 0, cnt_bits = 0; - log("Adding cover cells to module %s.\n", log_id(module)); + log("Adding cover cells to module %s.\n", module); for (auto wire : module->selected_wires()) { bool counted_wire = false; diff --git a/passes/sat/synthprop.cc b/passes/sat/synthprop.cc index d94b4a7f7..a54eef199 100644 --- a/passes/sat/synthprop.cc +++ b/passes/sat/synthprop.cc @@ -60,20 +60,20 @@ struct SynthPropWorker void SynthPropWorker::tracing(RTLIL::Module *mod, int depth, TrackingData &tracing_data, std::string hier_path) { - log("%*sTracing in module %s..\n", 2*depth, "", log_id(mod)); + log("%*sTracing in module %s..\n", 2*depth, "", mod); tracing_data[mod] = TrackingItem(); int cnt = 0; for (auto cell : mod->cells()) { if (cell->type == ID($assert)) { - log("%*sFound assert %s..\n", 2*(depth+1), "", log_id(cell)); + log("%*sFound assert %s..\n", 2*(depth+1), "", cell); tracing_data[mod].assertion_cells.emplace(cell); if (!or_outputs) { - tracing_data[mod].names.push_back(hier_path + "." + log_id(cell)); + tracing_data[mod].names.push_back(hier_path + "." + cell->name.unescape()); } cnt++; } else if (RTLIL::Module *submod = design->module(cell->type)) { - tracing(submod, depth+1, tracing_data, hier_path + "." + log_id(cell)); + tracing(submod, depth+1, tracing_data, hier_path + "." + cell->name.unescape()); if (!or_outputs) { for (size_t i = 0; i < tracing_data[submod].names.size(); i++) tracing_data[mod].names.push_back(tracing_data[submod].names[i]); @@ -93,7 +93,7 @@ void SynthPropWorker::run() log_error("Module is not TOP module\n"); TrackingData tracing_data; - tracing(module, 0, tracing_data, log_id(module->name)); + tracing(module, 0, tracing_data, module->name.unescape()); for (auto &data : tracing_data) { if (data.second.names.size() == 0) continue; diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 083778d3c..eccad8998 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -55,6 +55,7 @@ OBJS += passes/techmap/extractinv.o OBJS += passes/techmap/cellmatch.o OBJS += passes/techmap/clockgate.o OBJS += passes/techmap/constmap.o +OBJS += passes/techmap/arith_tree.o endif ifeq ($(DISABLE_SPAWN),0) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index d58f6b355..7742fa989 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -63,13 +63,19 @@ # include # include # include +# include #endif #ifndef _WIN32 # include # include +# include +#endif +#if defined(__wasm) +#include #endif #include "frontends/blif/blifparse.h" +#include "liberty_cache.h" #ifdef YOSYS_LINK_ABC namespace abc { @@ -125,6 +131,7 @@ struct AbcConfig std::vector liberty_files; std::vector genlib_files; std::string constr_file; + std::string abc_liberty_args; vector lut_costs; std::string delay_target; std::string sop_inputs; @@ -290,6 +297,8 @@ struct RunAbcState { bool err = false; DeferredLogs logs; dict pi_map, po_map; + std::string abc_script; + std::string dont_use_args; RunAbcState(const AbcConfig &config) : config(config) {} void run(ConcurrentStack &process_pool); @@ -1014,87 +1023,102 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module log_header(design, "Extracting gate netlist of module `%s' to `%s/input.blif'..\n", module->name.c_str(), replace_tempdir(run_abc.per_run_tempdir_name, config.global_tempdir_name, run_abc.per_run_tempdir_name, config.show_tempdir).c_str()); - std::string abc_script = stringf("read_blif \"%s/input.blif\"; ", run_abc.per_run_tempdir_name); + run_abc.abc_script = stringf("read_blif \"%s/input.blif\"; ", run_abc.per_run_tempdir_name); if (!config.liberty_files.empty() || !config.genlib_files.empty()) { - std::string dont_use_args; + run_abc.dont_use_args = ""; for (std::string dont_use_cell : config.dont_use_cells) { - dont_use_args += stringf("-X \"%s\" ", dont_use_cell); + run_abc.dont_use_args += stringf("-X \"%s\" ", dont_use_cell); } - bool first_lib = true; - for (std::string liberty_file : config.liberty_files) { - abc_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file); - first_lib = false; + + std::string merged_scl; + if (config.abc_liberty_args.empty()) { + merged_scl = convert_liberty_files_to_merged_scl(config.liberty_files, run_abc.dont_use_args, config.exe_file); } + if (!merged_scl.empty()) { + run_abc.abc_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); + } else if(!config.liberty_files.empty()) { + if (!config.abc_liberty_args.empty()) { + log("ABC: abc_liberty_args provided, using liberty format\n"); + } else { + log_warning("ABC: Merged scl conversion failed, using liberty format\n"); + } + bool first_lib = true; + for (std::string liberty_file : config.liberty_files) { + run_abc.abc_script += stringf("read_lib %s %s %s -w \"%s\" ; ", run_abc.dont_use_args, first_lib ? "" : "-m", config.abc_liberty_args, liberty_file); + first_lib = false; + } + } + for (std::string liberty_file : config.genlib_files) - abc_script += stringf("read_library \"%s\"; ", liberty_file); + run_abc.abc_script += stringf("read_library \"%s\"; ", liberty_file); if (!config.constr_file.empty()) - abc_script += stringf("read_constr -v \"%s\"; ", config.constr_file); + run_abc.abc_script += stringf("read_constr -v \"%s\"; ", config.constr_file); } else if (!config.lut_costs.empty()) - abc_script += stringf("read_lut %s/lutdefs.txt; ", config.global_tempdir_name); + run_abc.abc_script += stringf("read_lut %s/lutdefs.txt; ", config.global_tempdir_name); else - abc_script += stringf("read_library %s/stdcells.genlib; ", config.global_tempdir_name); + run_abc.abc_script += stringf("read_library %s/stdcells.genlib; ", config.global_tempdir_name); if (!config.script_file.empty()) { const std::string &script_file = config.script_file; if (script_file[0] == '+') { for (size_t i = 1; i < script_file.size(); i++) if (script_file[i] == '\'') - abc_script += "'\\''"; + run_abc.abc_script += "'\\''"; else if (script_file[i] == ',') - abc_script += " "; + run_abc.abc_script += " "; else - abc_script += script_file[i]; + run_abc.abc_script += script_file[i]; } else - abc_script += stringf("source %s", script_file); + run_abc.abc_script += stringf("source %s", script_file); } else if (!config.lut_costs.empty()) { bool all_luts_cost_same = true; for (int this_cost : config.lut_costs) if (this_cost != config.lut_costs.front()) all_luts_cost_same = false; - abc_script += config.fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; + run_abc.abc_script += config.fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; if (all_luts_cost_same && !config.fast_mode) - abc_script += "; lutpack -S 1"; + run_abc.abc_script += "; lutpack -S 1"; } else if (!config.liberty_files.empty() || !config.genlib_files.empty()) - abc_script += config.constr_file.empty() ? + run_abc.abc_script += config.constr_file.empty() ? (config.fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (config.fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); else if (config.sop_mode) - abc_script += config.fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP; + run_abc.abc_script += config.fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP; else - abc_script += config.fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; + run_abc.abc_script += config.fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; if (config.script_file.empty() && !config.delay_target.empty()) - for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) - abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8); + for (size_t pos = run_abc.abc_script.find("dretime;"); pos != std::string::npos; pos = run_abc.abc_script.find("dretime;", pos+1)) + run_abc.abc_script = run_abc.abc_script.substr(0, pos) + "dretime; retime -o {D};" + run_abc.abc_script.substr(pos+8); - for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) - abc_script = abc_script.substr(0, pos) + config.delay_target + abc_script.substr(pos+3); + for (size_t pos = run_abc.abc_script.find("{D}"); pos != std::string::npos; pos = run_abc.abc_script.find("{D}", pos)) + run_abc.abc_script = run_abc.abc_script.substr(0, pos) + config.delay_target + run_abc.abc_script.substr(pos+3); - for (size_t pos = abc_script.find("{I}"); pos != std::string::npos; pos = abc_script.find("{I}", pos)) - abc_script = abc_script.substr(0, pos) + config.sop_inputs + abc_script.substr(pos+3); + for (size_t pos = run_abc.abc_script.find("{I}"); pos != std::string::npos; pos = run_abc.abc_script.find("{I}", pos)) + run_abc.abc_script = run_abc.abc_script.substr(0, pos) + config.sop_inputs + run_abc.abc_script.substr(pos+3); - for (size_t pos = abc_script.find("{P}"); pos != std::string::npos; pos = abc_script.find("{P}", pos)) - abc_script = abc_script.substr(0, pos) + config.sop_products + abc_script.substr(pos+3); + for (size_t pos = run_abc.abc_script.find("{P}"); pos != std::string::npos; pos = run_abc.abc_script.find("{P}", pos)) + run_abc.abc_script = run_abc.abc_script.substr(0, pos) + config.sop_products + run_abc.abc_script.substr(pos+3); if (config.abc_dress) - abc_script += stringf("; dress \"%s/input.blif\"", run_abc.per_run_tempdir_name); - abc_script += stringf("; write_blif %s/output.blif", run_abc.per_run_tempdir_name); - abc_script = add_echos_to_abc_cmd(abc_script); + run_abc.abc_script += stringf("; dress \"%s/input.blif\"", run_abc.per_run_tempdir_name); + run_abc.abc_script += stringf("; write_blif %s/output.blif", run_abc.per_run_tempdir_name); + run_abc.abc_script = add_echos_to_abc_cmd(run_abc.abc_script); #if defined(REUSE_YOSYS_ABC_PROCESSES) if (config.is_yosys_abc()) - abc_script += "; echo; echo \"YOSYS_ABC_DONE\"\n"; + run_abc.abc_script += "; echo; echo \"YOSYS_ABC_DONE\"\n"; #endif - for (size_t i = 0; i+1 < abc_script.size(); i++) - if (abc_script[i] == ';' && abc_script[i+1] == ' ') - abc_script[i+1] = '\n'; + for (size_t i = 0; i+1 < run_abc.abc_script.size(); i++) + if (run_abc.abc_script[i] == ';' && run_abc.abc_script[i+1] == ' ') + run_abc.abc_script[i+1] = '\n'; std::string buffer = stringf("%s/abc.script", run_abc.per_run_tempdir_name); FILE *f = fopen(buffer.c_str(), "wt"); if (f == nullptr) log_error("Opening %s for writing failed: %s\n", buffer, strerror(errno)); - fprintf(f, "%s\n", abc_script.c_str()); + fprintf(f, "%s\n", run_abc.abc_script.c_str()); fclose(f); if (dff_mode || !clk_str.empty()) @@ -1349,7 +1373,7 @@ void RunAbcState::run(ConcurrentStack &) logs.log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", count_gates, GetSize(signal_list), count_input, count_output); if (count_output == 0) { - log("Don't call ABC as there is nothing to map.\n"); + logs.log("Don't call ABC as there is nothing to map.\n"); return; } int ret; @@ -1363,13 +1387,13 @@ void RunAbcState::run(ConcurrentStack &) string temp_stdouterr_name = stringf("%s/stdouterr.txt", per_run_tempdir_name); FILE *temp_stdouterr_w = fopen(temp_stdouterr_name.c_str(), "w"); if (temp_stdouterr_w == NULL) - log_error("ABC: cannot open a temporary file for output redirection"); + logs.log_error("ABC: cannot open a temporary file for output redirection"); fflush(stdout); fflush(stderr); FILE *old_stdout = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering FILE *old_stderr = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering #if defined(__wasm) -#define fd_renumber(from, to) (void)__wasi_fd_renumber(from, to) +#define fd_renumber(from, to) (void)__wasilibc_fd_renumber(from, to) #else #define fd_renumber(from, to) dup2(from, to) #endif @@ -1408,10 +1432,10 @@ void RunAbcState::run(ConcurrentStack &) if (std::optional process_opt = process_pool.try_pop_back()) { process = std::move(process_opt.value()); } else if (std::optional process_opt = spawn_abc(config.exe_file.c_str(), logs)) { - process = std::move(process_opt.value()); - } else { - return; - } + process = std::move(process_opt.value()); + } else { + return; + } std::string cmd = stringf( "empty\n" "source %s\n", tmp_script_name); @@ -1911,8 +1935,10 @@ struct AbcPass : public Pass { log(" file format).\n"); log("\n"); log(" -dont_use \n"); - log(" generate netlists for the specified cell library (using the liberty\n"); - log(" file format).\n"); + log(" avoid usage of the technology cell when mapping the design.\n"); + log(" this option can be used multiple times with different cell names and\n"); + log(" supports simple glob patterns in the cell name.\n"); + log(" only supported with Liberty cell libraries.\n"); log("\n"); log(" -genlib \n"); log(" generate netlists for the specified cell library (using the SIS Genlib\n"); @@ -2019,6 +2045,10 @@ struct AbcPass : public Pass { log(" preserve naming by an equivalence check between the original and\n"); log(" post-ABC netlists (experimental).\n"); log("\n"); + log(" -liberty_args \n"); + log(" when -liberty is used, also pass the specified arguments to ABC\n"); + log(" command \"read_lib\". Example: -liberty_args \"-G 250\"\n"); + log("\n"); log("When no target cell library is specified the Yosys standard cell library is\n"); log("loaded into ABC before the ABC script is executed.\n"); log("\n"); @@ -2201,6 +2231,14 @@ struct AbcPass : public Pass { config.markgroups = true; continue; } + if (arg == "-liberty_args" && argidx+1 < args.size()) { + config.abc_liberty_args = args[++argidx]; + if (!config.abc_liberty_args.empty()) { + if (config.abc_liberty_args[0] == '\"' && config.abc_liberty_args.back() == '\"') + config.abc_liberty_args = config.abc_liberty_args.substr(1, config.abc_liberty_args.size() - 2); + } + continue; + } break; } extra_args(args, argidx, design); @@ -2411,7 +2449,7 @@ struct AbcPass : public Pass { for (auto mod : design->selected_modules()) { if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); + log("Skipping module %s as it contains processes.\n", mod); continue; } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 90c48ae34..309365a11 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -386,7 +386,7 @@ struct Abc9Pass : public ScriptPass for (auto mod : selected_modules) { if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); + log("Skipping module %s as it contains processes.\n", mod); continue; } @@ -395,7 +395,7 @@ struct Abc9Pass : public ScriptPass // this check does nothing because the above line adds the whole module to the selection if (!active_design->selected_whole_module(mod)) - log_error("Can't handle partially selected module %s!\n", log_id(mod)); + log_error("Can't handle partially selected module %s!\n", mod); std::string tempdir_name; if (cleanup) @@ -416,7 +416,7 @@ struct Abc9Pass : public ScriptPass log("Extracted %d AND gates and %d wires from module `%s' to a netlist network with %d inputs and %d outputs.\n", active_design->scratchpad_get_int("write_xaiger.num_ands"), active_design->scratchpad_get_int("write_xaiger.num_wires"), - log_id(mod), + mod, active_design->scratchpad_get_int("write_xaiger.num_inputs"), num_outputs); if (num_outputs) { @@ -429,7 +429,7 @@ struct Abc9Pass : public ScriptPass else abc9_exe_cmd += stringf(" -box %s", box_file); run_nocheck(abc9_exe_cmd); - run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name, tempdir_name)); + run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", mod, tempdir_name, tempdir_name)); run_nocheck(stringf("abc9_ops -reintegrate %s", dff_mode ? "-dff" : "")); } else diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index 592f717c1..a32816612 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -24,11 +24,15 @@ #include "kernel/register.h" #include "kernel/log.h" +#include "liberty_cache.h" #ifndef _WIN32 # include # include #endif +#if defined(__wasm) +#include +#endif #ifdef YOSYS_LINK_ABC namespace abc { @@ -181,11 +185,19 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe for (std::string dont_use_cell : dont_use_cells) { dont_use_args += stringf("-X \"%s\" ", dont_use_cell); } - bool first_lib = true; - for (std::string liberty_file : liberty_files) { - abc9_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file); - first_lib = false; + + std::string merged_scl = convert_liberty_files_to_merged_scl(liberty_files, dont_use_args, exe_file); + if (!merged_scl.empty()) { + abc9_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); + } else if(!liberty_files.empty()) { + log_warning("ABC: Merged scl conversion failed, using liberty format\n"); + bool first_lib = true; + for (std::string liberty_file : liberty_files) { + abc9_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file); + first_lib = false; + } } + if (!constr_file.empty()) abc9_script += stringf("read_constr -v \"%s\"; ", constr_file); } else if (!genlib_files.empty()) { @@ -211,6 +223,8 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe abc9_script += stringf("source %s", script_file); } else if (!lut_costs.empty() || !lut_file.empty()) { abc9_script += RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos); + } else if (!liberty_files.empty() || !genlib_files.empty()) { + abc9_script += RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos); } else log_abort(); @@ -285,7 +299,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe FILE *old_stdout = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering FILE *old_stderr = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering #if defined(__wasm) -#define fd_renumber(from, to) (void)__wasi_fd_renumber(from, to) +#define fd_renumber(from, to) (void)__wasilibc_fd_renumber(from, to) #else #define fd_renumber(from, to) dup2(from, to) #endif diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index dda3858da..55c4c7380 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -48,7 +48,7 @@ void check(RTLIL::Design *design, bool dff_mode) auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); if (!r.second) log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - log_id(m), id, log_id(r.first->second)); + m, id, r.first->second.unescape()); } // Make carry in the last PI, and carry out the last PO @@ -60,21 +60,21 @@ void check(RTLIL::Design *design, bool dff_mode) if (w->get_bool_attribute(ID::abc9_carry)) { if (w->port_input) { if (carry_in != IdString()) - log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", log_id(m)); + log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", m); carry_in = port_name; } if (w->port_output) { if (carry_out != IdString()) - log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", log_id(m)); + log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", m); carry_out = port_name; } } } if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", log_id(m)); + log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", m); if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", log_id(m)); + log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", m); if (flop) { int num_outputs = 0; @@ -83,7 +83,7 @@ void check(RTLIL::Design *design, bool dff_mode) if (wire->port_output) num_outputs++; } if (num_outputs != 1) - log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs); + log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", m, num_outputs); } } @@ -97,7 +97,6 @@ void check(RTLIL::Design *design, bool dff_mode) ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_) }; - pool processed; for (auto module : design->selected_modules()) for (auto cell : module->cells()) { auto inst_module = design->module(cell->type); @@ -121,7 +120,7 @@ void check(RTLIL::Design *design, bool dff_mode) if (!derived_module->get_bool_attribute(ID::abc9_flop)) continue; if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) - log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type)); + log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", derived_type.unescape()); if (derived_module->has_processes()) Pass::call_on_module(design, derived_module, "proc -noopt"); @@ -130,20 +129,20 @@ void check(RTLIL::Design *design, bool dff_mode) for (auto derived_cell : derived_module->cells()) { if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) { if (found) - log_error("Whitebox '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module)); + log_error("Whitebox '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", derived_module); found = true; SigBit Q = derived_cell->getPort(ID::Q); log_assert(GetSize(Q.wire) == 1); if (!Q.wire->port_output) - log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell where its 'Q' port does not drive a module output.\n", log_id(derived_module), log_id(derived_cell->type)); + log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell where its 'Q' port does not drive a module output.\n", derived_module, derived_cell->type.unescape()); Const init = Q.wire->attributes.at(ID::init, State::Sx); log_assert(GetSize(init) == 1); } else if (unsupported.count(derived_cell->type)) - log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type)); + log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", derived_module, derived_cell->type.unescape()); } } } @@ -217,7 +216,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) // Block sequential synthesis on cells with (* init *) != 1'b0 // because ABC9 doesn't support them if (init != State::S0) { - log_warning("Whitebox '%s' with (* abc9_flop *) contains a %s cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type)); + log_warning("Whitebox '%s' with (* abc9_flop *) contains a %s cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox.\n", derived_module, derived_cell->type.unescape()); derived_module->set_bool_attribute(ID::abc9_flop, false); } break; @@ -474,7 +473,7 @@ void prep_dff(RTLIL::Design *design) // be instantiating the derived module which will have had any parameters constant-propagated. // This task is expected to be performed by `abc9_ops -prep_hier`, but it looks like it failed to do so for this design. // Please file a bug report! - log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_flop *)\n", log_id(cell->name), log_id(cell->type)); + log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_flop *)\n", cell->name.unescape(), cell->type.unescape()); } modules_sel.select(inst_module); } @@ -621,7 +620,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) std::vector cells; for (auto module : design->selected_modules()) { if (module->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(module)); + log("Skipping module %s as it contains processes.\n", module); continue; } @@ -669,7 +668,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) auto port_wire = inst_module->wire(i.first.name); if (!port_wire) log_error("Port %s in cell %s (type %s) from module %s does not actually exist", - log_id(i.first.name), log_id(cell), log_id(cell->type), log_id(module)); + i.first.name.unescape(), cell, cell->type.unescape(), module); log_assert(port_wire->port_input); auto d = i.second.first; @@ -688,7 +687,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) if (ys_debug(1)) { static pool> seen; if (seen.emplace(cell->type, i.first).second) log("%s.%s[%d] abc9_required = %d\n", - log_id(cell->type), log_id(i.first.name), offset, d); + cell->type.unescape(), i.first.name.unescape(), offset, d); } #endif auto r = box_cache.insert(d); @@ -848,7 +847,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) for (auto cell_name : it) { auto cell = module->cell(cell_name); log_assert(cell); - log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute()); + log("\t%s (%s @ %s)\n", cell, cell->type.unescape(), cell->get_src_attribute()); } } } @@ -882,7 +881,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) // be instantiating the derived module which will have had any parameters constant-propagated. // This task is expected to be performed by `abc9_ops -prep_hier`, but it looks like it failed to do so for this design. // Please file a bug report! - log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_box *)\n", log_id(cell_name), log_id(cell->type)); + log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_box *)\n", cell_name.unescape(), cell->type.unescape()); } log_assert(box_module->get_blackbox_attribute()); @@ -917,7 +916,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) } } else if (w->port_output) - conn = holes_module->addWire(stringf("%s.%s", cell->type, log_id(port_name)), GetSize(w)); + conn = holes_module->addWire(stringf("%s.%s", cell->type, port_name.unescape()), GetSize(w)); } } else // box_module is a blackbox @@ -929,7 +928,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) log_assert(w); if (!w->port_output) continue; - Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name, log_id(port_name)), GetSize(w)); + Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name, port_name.unescape()), GetSize(w)); holes_wire->port_output = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); @@ -965,12 +964,12 @@ void prep_lut(RTLIL::Design *design, int maxlut) if (o == TimingInfo::NameBit()) o = d; else if (o != d) - log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", log_id(module)); + log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", module); delays.push_back(i.second); } if (GetSize(delays) == 0) - log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", log_id(module)); + log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", module); if (maxlut && GetSize(delays) > maxlut) continue; // ABC requires non-decreasing LUT input delays @@ -981,9 +980,9 @@ void prep_lut(RTLIL::Design *design, int maxlut) auto r = table.emplace(K, entry); if (!r.second) { if (r.first->second.area != entry.area) - log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", log_id(module), log_id(r.first->second.name)); + log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", module, r.first->second.name.unescape()); if (r.first->second.delays != entry.delays) - log_error("Modules '%s' and '%s' have conflicting specify entries.\n", log_id(module), log_id(r.first->second.name)); + log_error("Modules '%s' and '%s' have conflicting specify entries.\n", module, r.first->second.name.unescape()); } } @@ -1002,7 +1001,7 @@ void prep_lut(RTLIL::Design *design, int maxlut) ss << std::endl; } for (const auto &i : table) { - ss << "# " << log_id(i.second.name) << std::endl; + ss << "# " << i.second.name.unescape() << std::endl; ss << i.first << " " << i.second.area; for (const auto &j : i.second.delays) ss << " " << j; @@ -1046,7 +1045,7 @@ void prep_box(RTLIL::Design *design) } log_assert(num_outputs == 1); - ss << log_id(module) << " " << r.first->second.as_int(); + ss << module->name.unescape() << " " << r.first->second.as_int(); log_assert(module->get_bool_attribute(ID::whitebox)); ss << " " << "1"; ss << " " << num_inputs << " " << num_outputs << std::endl; @@ -1061,13 +1060,13 @@ void prep_box(RTLIL::Design *design) first = false; else ss << " "; - ss << log_id(wire); + ss << wire->name.unescape(); } ss << std::endl; auto &t = timing.setup_module(module).required; if (t.empty()) - log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", log_id(module)); + log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", module); first = true; for (auto port_name : module->ports) { @@ -1089,8 +1088,8 @@ void prep_box(RTLIL::Design *design) #ifndef NDEBUG if (ys_debug(1)) { static std::set> seen; - if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), - log_id(port_name), it->second.first); + if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", module, + port_name.unescape(), it->second.first); } #endif } @@ -1135,7 +1134,7 @@ void prep_box(RTLIL::Design *design) outputs.emplace_back(wire, i); } - ss << log_id(module) << " " << module->attributes.at(ID::abc9_box_id).as_int(); + ss << module->name.unescape() << " " << module->attributes.at(ID::abc9_box_id).as_int(); bool has_model = module->get_bool_attribute(ID::whitebox) || !module->get_bool_attribute(ID::blackbox); ss << " " << (has_model ? "1" : "0"); ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl; @@ -1148,15 +1147,15 @@ void prep_box(RTLIL::Design *design) else ss << " "; if (GetSize(i.wire) == 1) - ss << log_id(i.wire); + ss << i.wire->name.unescape(); else - ss << log_id(i.wire) << "[" << i.offset << "]"; + ss << i.wire->name.unescape() << "[" << i.offset << "]"; } ss << std::endl; auto &t = timing.setup_module(module); if (t.comb.empty() && !outputs.empty() && !inputs.empty()) { - log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", log_id(module)); + log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", module); } for (const auto &o : outputs) { @@ -1174,9 +1173,9 @@ void prep_box(RTLIL::Design *design) } ss << " # "; if (GetSize(o.wire) == 1) - ss << log_id(o.wire); + ss << o.wire->name.unescape(); else - ss << log_id(o.wire) << "[" << o.offset << "]"; + ss << o.wire->name.unescape() << "[" << o.offset << "]"; ss << std::endl; } ss << std::endl; @@ -1206,7 +1205,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) RTLIL::Module *mapped_mod = design->module(stringf("%s$abc9", module->name)); if (mapped_mod == NULL) - log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module)); + log_error("ABC output file does not contain a module `%s$abc'.\n", module); for (auto w : mapped_mod->wires()) { auto nw = module->addWire(remap_name(w->name), GetSize(w)); @@ -1387,7 +1386,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) else { RTLIL::Cell *existing_cell = module->cell(mapped_cell->name); if (!existing_cell) - log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell)); + log_error("Cannot find existing box cell with name '%s' in original design.\n", mapped_cell); if (existing_cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) { SigBit I = mapped_cell->getPort(ID(i)); @@ -1652,7 +1651,7 @@ static void replace_zbufs(Design *design) if (sig[i] == State::Sz) { Wire *w = mod->addWire(NEW_ID); Cell *ud = mod->addCell(NEW_ID, ID($tribuf)); - ud->set_bool_attribute(ID(aiger2_zbuf)); + ud->set_bool_attribute(ID::aiger2_zbuf); ud->setParam(ID::WIDTH, 1); ud->setPort(ID::Y, w); ud->setPort(ID::EN, State::S0); @@ -1924,12 +1923,12 @@ struct Abc9OpsPass : public Pass { for (auto mod : design->selected_modules()) { if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); + log("Skipping module %s as it contains processes.\n", mod); continue; } if (!design->selected_whole_module(mod)) - log_error("Can't handle partially selected module %s!\n", log_id(mod)); + log_error("Can't handle partially selected module %s!\n", mod); if (!write_lut_dst.empty()) write_lut(mod, write_lut_dst); diff --git a/passes/techmap/abc_new.cc b/passes/techmap/abc_new.cc index 0afabce11..0a312fb77 100644 --- a/passes/techmap/abc_new.cc +++ b/passes/techmap/abc_new.cc @@ -50,6 +50,17 @@ struct AbcNewPass : public ScriptPass { experimental(); } + void on_register() override + { + RTLIL::constpad["abc_new.script.speed"] = "+&st; &dch -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf"; + } + void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -110,6 +121,11 @@ struct AbcNewPass : public ScriptPass { } extra_args(args, argidx, d); + // If no script provided, use a default. + if (abc_exe_options.find("-script") == std::string::npos) { + d->scratchpad_set_string("abc9.script", RTLIL::constpad["abc_new.script.speed"]); + } + log_header(d, "Executing ABC_NEW pass.\n"); log_push(); run_script(d, run_from, run_to); @@ -162,7 +178,7 @@ struct AbcNewPass : public ScriptPass { tmpdir = make_temp_dir(tmpdir); modname = mod->name.str(); exe_options = abc_exe_options; - log_header(active_design, "Mapping module '%s'.\n", log_id(mod)); + log_header(active_design, "Mapping module '%s'.\n", mod); log_push(); active_design->select(mod); } diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc index 19e568a61..6b7e0c377 100644 --- a/passes/techmap/aigmap.cc +++ b/passes/techmap/aigmap.cc @@ -150,21 +150,21 @@ struct AigmapPass : public Pass { if (not_replaced_count == 0 && replaced_cells.empty()) continue; - log("Module %s: replaced %d cells with %d new cells, skipped %d cells.\n", log_id(module), + log("Module %s: replaced %d cells with %d new cells, skipped %d cells.\n", module, GetSize(replaced_cells), GetSize(module->cells()) - orig_num_cells, not_replaced_count); if (!stat_replaced.empty()) { stat_replaced.sort(); log(" replaced %d cell types:\n", GetSize(stat_replaced)); for (auto &it : stat_replaced) - log("%8d %s\n", it.second, log_id(it.first)); + log("%8d %s\n", it.second, it.first.unescape()); } if (!stat_not_replaced.empty()) { stat_not_replaced.sort(); log(" not replaced %d cell types:\n", GetSize(stat_not_replaced)); for (auto &it : stat_not_replaced) - log("%8d %s\n", it.second, log_id(it.first)); + log("%8d %s\n", it.second, it.first.unescape()); } for (auto cell : replaced_cells) diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index 10f93d925..5cce8c0ee 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -156,7 +156,7 @@ struct AlumaccWorker if (!cell->type.in(ID($pos), ID($neg), ID($add), ID($sub), ID($mul))) continue; - log(" creating $macc model for %s (%s).\n", log_id(cell), log_id(cell->type)); + log(" creating $macc model for %s (%s).\n", cell, cell->type.unescape()); maccnode_t *n = new maccnode_t; Macc::term_t new_term; @@ -267,7 +267,7 @@ struct AlumaccWorker if (GetSize(other_n->y) != GetSize(n->y) && macc_may_overflow(other_n->macc, GetSize(other_n->y), port.is_signed)) continue; - log(" merging $macc model for %s into %s.\n", log_id(other_n->cell), log_id(n->cell)); + log(" merging $macc model for %s into %s.\n", other_n->cell, n->cell); bool do_subtract = port.do_subtract; for (int j = 0; j < GetSize(other_n->macc.terms); j++) { @@ -351,7 +351,7 @@ struct AlumaccWorker if (!subtract_b && B < A && GetSize(B)) std::swap(A, B); - log(" creating $alu model for $macc %s.\n", log_id(n->cell)); + log(" creating $alu model for $macc %s.\n", n->cell); alunode = new alunode_t; alunode->cells.push_back(n->cell); @@ -383,7 +383,7 @@ struct AlumaccWorker macc_counter++; - log(" creating $macc cell for %s: %s\n", log_id(n->cell), log_id(cell)); + log(" creating $macc cell for %s: %s\n", n->cell, cell); cell->set_src_attribute(n->cell->get_src_attribute()); @@ -412,7 +412,7 @@ struct AlumaccWorker for (auto cell : lge_cells) { - log(" creating $alu model for %s (%s):", log_id(cell), log_id(cell->type)); + log(" creating $alu model for %s (%s):", cell, cell->type.unescape()); bool cmp_less = cell->type.in(ID($lt), ID($le)); bool cmp_equal = cell->type.in(ID($le), ID($ge)); @@ -451,7 +451,7 @@ struct AlumaccWorker sig_alu[RTLIL::SigSig(A, B)].insert(n); log(" new $alu\n"); } else { - log(" merged with %s.\n", log_id(n->cells.front())); + log(" merged with %s.\n", n->cells.front()); } n->cells.push_back(cell); @@ -484,7 +484,7 @@ struct AlumaccWorker } if (n != nullptr) { - log(" creating $alu model for %s (%s): merged with %s.\n", log_id(cell), log_id(cell->type), log_id(n->cells.front())); + log(" creating $alu model for %s (%s): merged with %s.\n", cell, cell->type.unescape(), n->cells.front()); n->cells.push_back(cell); n->cmp.push_back(std::make_tuple(false, false, cmp_equal, !cmp_equal, false, Y)); } @@ -503,8 +503,8 @@ struct AlumaccWorker log(" creating $pos cell for "); for (int i = 0; i < GetSize(n->cells); i++) - log("%s%s", i ? ", ": "", log_id(n->cells[i])); - log(": %s\n", log_id(n->alu_cell)); + log("%s%s", i ? ", ": "", n->cells[i]); + log(": %s\n", n->alu_cell); goto delete_node; } @@ -514,8 +514,8 @@ struct AlumaccWorker log(" creating $alu cell for "); for (int i = 0; i < GetSize(n->cells); i++) - log("%s%s", i ? ", ": "", log_id(n->cells[i])); - log(": %s\n", log_id(n->alu_cell)); + log("%s%s", i ? ", ": "", n->cells[i]); + log(": %s\n", n->alu_cell); if (n->cells.size() > 0) n->alu_cell->set_src_attribute(n->cells[0]->get_src_attribute()); @@ -562,7 +562,7 @@ struct AlumaccWorker void run() { - log("Extracting $alu and $macc cells in module %s:\n", log_id(module)); + log("Extracting $alu and $macc cells in module %s:\n", module); count_bit_users(); extract_macc(); diff --git a/passes/techmap/arith_tree.cc b/passes/techmap/arith_tree.cc new file mode 100644 index 000000000..259e0c5bb --- /dev/null +++ b/passes/techmap/arith_tree.cc @@ -0,0 +1,426 @@ +/** + * Replaces chains of $add/$sub and $macc cells with carry-save adder trees + * + * Terminology: + * - parent: Cells that consume another cell's output + * - chainable: Adds/subs with no carry-out usage + * - chain: Connected path of chainable cells + */ + +#include "kernel/macc.h" +#include "kernel/sigtools.h" +#include "kernel/wallace_tree.h" +#include "kernel/yosys.h" + +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct Operand { + SigSpec sig; + bool is_signed; + bool negate; +}; + +struct Traversal { + SigMap sigmap; + dict> bit_consumers; + dict fanout; + Traversal(Module *module) : sigmap(module) + { + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_consumers[bit].insert(cell); + + for (auto &pair : bit_consumers) + fanout[pair.first] = pair.second.size(); + + for (auto wire : module->wires()) + if (wire->port_output) + for (auto bit : sigmap(SigSpec(wire))) + fanout[bit]++; + } +}; + +struct Cells { + pool addsub; + pool alu; + pool macc; + + static bool is_addsub(Cell *cell) { return cell->type == ID($add) || cell->type == ID($sub); } + + static bool is_alu(Cell *cell) { return cell->type == ID($alu); } + + static bool is_macc(Cell *cell) { return cell->type == ID($macc) || cell->type == ID($macc_v2); } + + bool empty() { return addsub.empty() && alu.empty() && macc.empty(); } + + Cells(Module *module) + { + for (auto cell : module->cells()) { + if (is_addsub(cell)) + addsub.insert(cell); + else if (is_alu(cell)) + alu.insert(cell); + else if (is_macc(cell)) + macc.insert(cell); + } + } +}; + +struct AluInfo { + Cells &cells; + Traversal &traversal; + bool is_subtract(Cell *cell) + { + SigSpec bi = traversal.sigmap(cell->getPort(ID::BI)); + SigSpec ci = traversal.sigmap(cell->getPort(ID::CI)); + return GetSize(bi) == 1 && bi[0] == State::S1 && GetSize(ci) == 1 && ci[0] == State::S1; + } + + bool is_add(Cell *cell) + { + SigSpec bi = traversal.sigmap(cell->getPort(ID::BI)); + SigSpec ci = traversal.sigmap(cell->getPort(ID::CI)); + return GetSize(bi) == 1 && bi[0] == State::S0 && GetSize(ci) == 1 && ci[0] == State::S0; + } + + bool is_chainable(Cell *cell) + { + if (!(is_add(cell) || is_subtract(cell))) + return false; + + for (auto bit : traversal.sigmap(cell->getPort(ID::X))) + if (traversal.fanout.count(bit) && traversal.fanout[bit] > 0) + return false; + for (auto bit : traversal.sigmap(cell->getPort(ID::CO))) + if (traversal.fanout.count(bit) && traversal.fanout[bit] > 0) + return false; + + return true; + } +}; + +struct Rewriter { + Module *module; + Cells &cells; + Traversal traversal; + AluInfo alu_info; + + Rewriter(Module *module, Cells &cells) : module(module), cells(cells), traversal(module), alu_info{cells, traversal} {} + + Cell *sole_chainable_consumer(SigSpec sig, const pool &candidates) + { + Cell *consumer = nullptr; + for (auto bit : sig) { + if (!traversal.fanout.count(bit) || traversal.fanout[bit] != 1) + return nullptr; + if (!traversal.bit_consumers.count(bit) || traversal.bit_consumers[bit].size() != 1) + return nullptr; + + Cell *c = *traversal.bit_consumers[bit].begin(); + if (!candidates.count(c)) + return nullptr; + + if (consumer == nullptr) + consumer = c; + else if (consumer != c) + return nullptr; + } + return consumer; + } + + dict find_parents(const pool &candidates) + { + dict parent_of; + for (auto cell : candidates) { + Cell *consumer = sole_chainable_consumer(traversal.sigmap(cell->getPort(ID::Y)), candidates); + if (consumer && consumer != cell) + parent_of[cell] = consumer; + } + return parent_of; + } + + std::pair>, pool> invert_parent_map(const dict &parent_of) + { + dict> children_of; + pool has_parent; + for (auto &[child, parent] : parent_of) { + children_of[parent].insert(child); + has_parent.insert(child); + } + return {children_of, has_parent}; + } + + pool collect_chain(Cell *root, const dict> &children_of) + { + pool chain; + std::queue q; + q.push(root); + while (!q.empty()) { + Cell *cur = q.front(); + q.pop(); + if (!chain.insert(cur).second) + continue; + auto it = children_of.find(cur); + if (it != children_of.end()) + for (auto child : it->second) + q.push(child); + } + return chain; + } + + pool internal_bits(const pool &chain) + { + pool bits; + for (auto cell : chain) + for (auto bit : traversal.sigmap(cell->getPort(ID::Y))) + bits.insert(bit); + return bits; + } + + static bool overlaps(SigSpec sig, const pool &bits) + { + for (auto bit : sig) + if (bits.count(bit)) + return true; + return false; + } + + bool feeds_subtracted_port(Cell *child, Cell *parent) + { + bool parent_subtracts; + if (parent->type == ID($sub)) + parent_subtracts = true; + else if (cells.is_alu(parent)) + parent_subtracts = alu_info.is_subtract(parent); + else + return false; + + if (!parent_subtracts) + return false; + + // Check if any bit of child's Y connects to parent's B + SigSpec child_y = traversal.sigmap(child->getPort(ID::Y)); + SigSpec parent_b = traversal.sigmap(parent->getPort(ID::B)); + for (auto bit : child_y) + for (auto pbit : parent_b) + if (bit == pbit) + return true; + return false; + } + + std::vector extract_chain_operands(const pool &chain, Cell *root, const dict &parent_of, int &neg_compensation) + { + pool chain_bits = internal_bits(chain); + + // Propagate negation flags through chain + dict negated; + negated[root] = false; + { + std::queue q; + q.push(root); + while (!q.empty()) { + Cell *cur = q.front(); + q.pop(); + for (auto cell : chain) { + if (!parent_of.count(cell) || parent_of.at(cell) != cur) + continue; + if (negated.count(cell)) + continue; + negated[cell] = negated[cur] ^ feeds_subtracted_port(cell, cur); + q.push(cell); + } + } + } + + // Extract leaf operands + std::vector operands; + neg_compensation = 0; + + for (auto cell : chain) { + bool cell_neg = negated.count(cell) ? negated[cell] : false; + + SigSpec a = traversal.sigmap(cell->getPort(ID::A)); + SigSpec b = traversal.sigmap(cell->getPort(ID::B)); + bool a_signed = cell->getParam(ID::A_SIGNED).as_bool(); + bool b_signed = cell->getParam(ID::B_SIGNED).as_bool(); + bool b_sub = (cell->type == ID($sub)) || (cells.is_alu(cell) && alu_info.is_subtract(cell)); + + // Only add operands not produced by other chain cells + if (!overlaps(a, chain_bits)) { + operands.push_back({a, a_signed, cell_neg}); + if (cell_neg) + neg_compensation++; + } + if (!overlaps(b, chain_bits)) { + bool neg = cell_neg ^ b_sub; + operands.push_back({b, b_signed, neg}); + if (neg) + neg_compensation++; + } + } + return operands; + } + + bool extract_macc_operands(Cell *cell, std::vector &operands, int &neg_compensation) + { + Macc macc(cell); + neg_compensation = 0; + + for (auto &term : macc.terms) { + // Bail on multiplication + if (GetSize(term.in_b) != 0) + return false; + operands.push_back({term.in_a, term.is_signed, term.do_subtract}); + if (term.do_subtract) + neg_compensation++; + } + return true; + } + + SigSpec extend_operand(SigSpec sig, bool is_signed, int width) + { + if (GetSize(sig) < width) { + SigBit pad; + if (is_signed && GetSize(sig) > 0) + pad = sig[GetSize(sig) - 1]; + else + pad = State::S0; + sig.append(SigSpec(pad, width - GetSize(sig))); + } + if (GetSize(sig) > width) + sig = sig.extract(0, width); + return sig; + } + + void replace_with_carry_save_tree(std::vector &operands, SigSpec result_y, int neg_compensation, const char *desc) + { + int width = GetSize(result_y); + std::vector extended; + extended.reserve(operands.size() + 1); + + for (auto &op : operands) { + SigSpec s = extend_operand(op.sig, op.is_signed, width); + if (op.negate) + s = module->Not(NEW_ID, s); + extended.push_back(s); + } + + // Add correction for negated operands (-x = ~x + 1 so 1 per negation) + if (neg_compensation > 0) + extended.push_back(SigSpec(neg_compensation, width)); + + int compressor_count; + auto [a, b] = wallace_reduce_scheduled(module, extended, width, &compressor_count); + log(" %s -> %d $fa + 1 $add (%d operands, module %s)\n", desc, compressor_count, (int)operands.size(), module); + + // Emit final add + module->addAdd(NEW_ID, a, b, result_y, false); + } + + void process_chains() + { + pool candidates; + for (auto cell : cells.addsub) + candidates.insert(cell); + for (auto cell : cells.alu) + if (alu_info.is_chainable(cell)) + candidates.insert(cell); + + if (candidates.empty()) + return; + + auto parent_of = find_parents(candidates); + auto [children_of, has_parent] = invert_parent_map(parent_of); + + pool to_remove; + for (auto root : candidates) { + if (has_parent.count(root) || to_remove.count(root)) + continue; // Not a tree root + + pool chain = collect_chain(root, children_of); + if (chain.size() < 2) + continue; + + int neg_compensation; + auto operands = extract_chain_operands(chain, root, parent_of, neg_compensation); + if (operands.size() < 3) + continue; + + for (auto c : chain) + to_remove.insert(c); + + replace_with_carry_save_tree(operands, root->getPort(ID::Y), neg_compensation, "Replaced add/sub chain"); + } + + for (auto cell : to_remove) + module->remove(cell); + } + + void process_maccs() + { + for (auto cell : cells.macc) { + std::vector operands; + int neg_compensation; + if (!extract_macc_operands(cell, operands, neg_compensation)) + continue; + if (operands.size() < 3) + continue; + + replace_with_carry_save_tree(operands, cell->getPort(ID::Y), neg_compensation, "Replaced $macc"); + module->remove(cell); + } + } +}; + +void run(Module *module) +{ + Cells cells(module); + + if (cells.empty()) + return; + + Rewriter rewriter{module, cells}; + rewriter.process_chains(); + rewriter.process_maccs(); +} + +struct ArithTreePass : public Pass { + ArithTreePass() : Pass("arith_tree", "convert add/sub/macc chains to carry-save adder trees") {} + + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" arith_tree [selection]\n"); + log("\n"); + log("This pass replaces chains of $add/$sub cells, $alu cells (with constant\n"); + log("BI/CI), and $macc/$macc_v2 cells (without multiplications) with carry-save\n"); + log("adder trees using $fa cells and a single final $add.\n"); + log("\n"); + log("The tree uses Wallace-tree scheduling: at each level, ready operands are\n"); + log("grouped into triplets and compressed via full adders, giving\n"); + log("O(log_{1.5} N) depth for N input operands.\n"); + log("\n"); + } + + void execute(std::vector args, RTLIL::Design *design) override + { + log_header(design, "Executing ARITH_TREE pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + break; + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) { + run(module); + } + } +} ArithTreePass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc index 58ac25f51..4c97f6ab1 100644 --- a/passes/techmap/attrmap.cc +++ b/passes/techmap/attrmap.cc @@ -131,13 +131,13 @@ void attrmap_apply(string objname, vector> &actio if (new_attr != attr) log("Changed attribute on %s: %s=%s -> %s=%s\n", objname, - log_id(attr.first), log_const(attr.second), log_id(new_attr.first), log_const(new_attr.second)); + attr.first.unescape(), log_const(attr.second), new_attr.first.unescape(), log_const(new_attr.second)); new_attributes[new_attr.first] = new_attr.second; if (0) delete_this_attr: - log("Removed attribute on %s: %s=%s\n", objname, log_id(attr.first), log_const(attr.second)); + log("Removed attribute on %s: %s=%s\n", objname, attr.first.unescape(), log_const(attr.second)); } attributes.swap(new_attributes); @@ -264,14 +264,14 @@ struct AttrmapPass : public Pass { if (modattr_mode) { for (auto module : design->all_selected_whole_modules()) - attrmap_apply(stringf("%s", log_id(module)), actions, module->attributes); + attrmap_apply(stringf("%s", module), actions, module->attributes); } else { for (auto module : design->all_selected_modules()) { for (auto memb : module->selected_members()) - attrmap_apply(stringf("%s.%s", log_id(module), log_id(memb)), actions, memb->attributes); + attrmap_apply(stringf("%s.%s", module, memb), actions, memb->attributes); // attrmap already applied to process itself during above loop, but not its children for (auto proc : module->selected_processes()) @@ -280,10 +280,10 @@ struct AttrmapPass : public Pass { while (!all_cases.empty()) { RTLIL::CaseRule *cs = all_cases.back(); all_cases.pop_back(); - attrmap_apply(stringf("%s.%s (case)", log_id(module), log_id(proc)), actions, cs->attributes); + attrmap_apply(stringf("%s.%s (case)", module, proc), actions, cs->attributes); for (auto &sw : cs->switches) { - attrmap_apply(stringf("%s.%s (switch)", log_id(module), log_id(proc)), actions, sw->attributes); + attrmap_apply(stringf("%s.%s (switch)", module, proc), actions, sw->attributes); all_cases.insert(all_cases.end(), sw->cases.begin(), sw->cases.end()); } } @@ -328,7 +328,7 @@ struct ParamapPass : public Pass { for (auto module : design->selected_modules()) for (auto cell : module->selected_cells()) - attrmap_apply(stringf("%s.%s", log_id(module), log_id(cell)), actions, cell->parameters); + attrmap_apply(stringf("%s.%s", module, cell), actions, cell->parameters); } } ParamapPass; diff --git a/passes/techmap/attrmvcp.cc b/passes/techmap/attrmvcp.cc index 65b63daf1..cff7d8697 100644 --- a/passes/techmap/attrmvcp.cc +++ b/passes/techmap/attrmvcp.cc @@ -121,8 +121,8 @@ struct AttrmvcpPass : public Pass { for (auto bit : sigmap(wire)) if (net2cells.count(bit)) for (auto cell : net2cells.at(bit)) { - log("Moving attribute %s=%s from %s.%s to %s.%s.\n", log_id(attr.first), log_const(attr.second), - log_id(module), log_id(wire), log_id(module), log_id(cell)); + log("Moving attribute %s=%s from %s.%s to %s.%s.\n", attr.first.unescape(), log_const(attr.second), + module, wire, module, cell); cell->attributes[attr.first] = attr.second; did_something = true; } diff --git a/passes/techmap/booth.cc b/passes/techmap/booth.cc index 11ff71b29..630c83f8c 100644 --- a/passes/techmap/booth.cc +++ b/passes/techmap/booth.cc @@ -58,6 +58,7 @@ synth -top my_design -booth #include "kernel/sigtools.h" #include "kernel/yosys.h" #include "kernel/macc.h" +#include "kernel/wallace_tree.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -223,7 +224,7 @@ struct BoothPassWorker { macc.from_cell(cell); if (!macc.is_simple_product()) { - log_debug("Not mapping cell %s: not a simple macc cell\n", log_id(cell)); + log_debug("Not mapping cell %s: not a simple macc cell\n", cell); continue; } @@ -239,11 +240,11 @@ struct BoothPassWorker { if (x_sz < 4 || y_sz < 4 || z_sz < 8) { log_debug("Not mapping cell %s sized at %dx%x, %x: size below threshold\n", - log_id(cell), x_sz, y_sz, z_sz); + cell, x_sz, y_sz, z_sz); continue; } - log("Mapping cell %s to %s Booth multiplier\n", log_id(cell), is_signed ? "signed" : "unsigned"); + log("Mapping cell %s to %s Booth multiplier\n", cell, is_signed ? "signed" : "unsigned"); // To simplify the generator size the arguments // to be the same. Then allow logic synthesis to @@ -317,36 +318,6 @@ struct BoothPassWorker { } } - SigSig WallaceSum(int width, std::vector summands) - { - for (auto &s : summands) - s.extend_u0(width); - - while (summands.size() > 2) { - std::vector new_summands; - int i; - for (i = 0; i < (int) summands.size() - 2; i += 3) { - SigSpec x = module->addWire(NEW_ID, width); - SigSpec y = module->addWire(NEW_ID, width); - BuildBitwiseFa(module, NEW_ID.str(), summands[i], summands[i + 1], - summands[i + 2], x, y); - new_summands.push_back(y); - new_summands.push_back({x.extract(0, width - 1), State::S0}); - } - - new_summands.insert(new_summands.begin(), summands.begin() + i, summands.end()); - - std::swap(summands, new_summands); - } - - if (!summands.size()) - return SigSig(SigSpec(width, State::S0), SigSpec(width, State::S0)); - else if (summands.size() == 1) - return SigSig(summands[0], SigSpec(width, State::S0)); - else - return SigSig(summands[0], summands[1]); - } - /* Build Multiplier. ------------------------- @@ -415,16 +386,16 @@ struct BoothPassWorker { // Later on yosys will clean up unused constants // DebugDumpAlignPP(aligned_pp); - SigSig wtree_sum = WallaceSum(z_sz, aligned_pp); + auto [wtree_a, wtree_b] = wallace_reduce_scheduled(module, aligned_pp, z_sz); // Debug code: Dump out the csa trees // DumpCSATrees(debug_csa_trees); // Build the CPA to do the final accumulation. - log_assert(wtree_sum.second[0] == State::S0); + log_assert(wtree_b[0] == State::S0); if (mapped_cpa) - BuildCPA(module, wtree_sum.first, {State::S0, wtree_sum.second.extract_end(1)}, Z); + BuildCPA(module, wtree_a, wtree_b, Z); else - module->addAdd(NEW_ID, wtree_sum.first, {wtree_sum.second.extract_end(1), State::S0}, Z); + module->addAdd(NEW_ID, wtree_a, wtree_b, Z); } /* diff --git a/passes/techmap/bufnorm.cc b/passes/techmap/bufnorm.cc index 123687255..c27f2740d 100644 --- a/passes/techmap/bufnorm.cc +++ b/passes/techmap/bufnorm.cc @@ -249,7 +249,7 @@ struct BufnormPass : public Pass { for (auto module : design->selected_modules()) { - log("Buffer-normalizing module %s.\n", log_id(module)); + log("Buffer-normalizing module %s.\n", module); SigMap sigmap(module); module->new_connections({}); @@ -293,7 +293,7 @@ struct BufnormPass : public Pass { bit2wires[keybit].insert(wire); if (wire->port_input) { - log(" primary input: %s\n", log_id(wire)); + log(" primary input: %s\n", wire); for (auto bit : SigSpec(wire)) mapped_bits[sigmap(bit)] = bit; } else { @@ -392,7 +392,7 @@ struct BufnormPass : public Pass { if (w->name.isPublic()) log(" directly driven by cell %s port %s: %s\n", - log_id(cell), log_id(conn.first), log_id(w)); + cell, conn.first.unescape(), w); for (auto bit : SigSpec(w)) mapped_bits[sigmap(bit)] = bit; @@ -502,7 +502,7 @@ struct BufnormPass : public Pass { if (conn.second != newsig) { log(" fixing input signal on cell %s port %s: %s\n", - log_id(cell), log_id(conn.first), log_signal(newsig)); + cell, conn.first.unescape(), log_signal(newsig)); cell->setPort(conn.first, newsig); count_updated_cellports++; } diff --git a/passes/techmap/cellmatch.cc b/passes/techmap/cellmatch.cc index ce1a75193..a2e2393d0 100644 --- a/passes/techmap/cellmatch.cc +++ b/passes/techmap/cellmatch.cc @@ -20,7 +20,7 @@ SigSpec module_inputs(Module *m) continue; if (w->width != 1) log_error("Unsupported wide port (%s) of non-unit width found in module %s.\n", - log_id(w), log_id(m)); + w, m); ret.append(w); } return ret; @@ -36,7 +36,7 @@ SigSpec module_outputs(Module *m) continue; if (w->width != 1) log_error("Unsupported wide port (%s) of non-unit width found in module %s.\n", - log_id(w), log_id(m)); + w, m); ret.append(w); } return ret; @@ -96,7 +96,7 @@ bool derive_module_luts(Module *m, std::vector &luts) ff_types.setup_stdcells_mem(); for (auto cell : m->cells()) { if (ff_types.cell_known(cell->type)) { - log("Ignoring module '%s' which isn't purely combinational.\n", log_id(m)); + log("Ignoring module '%s' which isn't purely combinational.\n", m); return false; } } @@ -106,7 +106,7 @@ bool derive_module_luts(Module *m, std::vector &luts) int ninputs = inputs.size(), noutputs = outputs.size(); if (ninputs > 6) { - log_warning("Skipping module %s with more than 6 inputs bits.\n", log_id(m)); + log_warning("Skipping module %s with more than 6 inputs bits.\n", m); return false; } @@ -123,7 +123,7 @@ bool derive_module_luts(Module *m, std::vector &luts) if (!ceval.eval(bit)) { log("Failed to evaluate output '%s' in module '%s'.\n", - log_signal(outputs[j]), log_id(m)); + log_signal(outputs[j]), m); return false; } @@ -203,7 +203,7 @@ struct CellmatchPass : Pass { for (auto lut : luts) p_classes.insert(p_class(ninputs, lut)); - log_debug("Registered %s\n", log_id(m)); + log_debug("Registered %s\n", m); // save as a viable target targets[p_classes].push_back(Target{m, luts}); @@ -237,7 +237,7 @@ struct CellmatchPass : Pass { p_classes.insert(p_class(inputs.size(), lut)); for (auto target : targets[p_classes]) { - log_debug("Candidate %s for matching to %s\n", log_id(target.module), log_id(m)); + log_debug("Candidate %s for matching to %s\n", target.module, m); SigSpec target_inputs = module_inputs(target.module); SigSpec target_outputs = module_outputs(target.module); @@ -271,10 +271,10 @@ struct CellmatchPass : Pass { } if (match) { - log("Module %s matches %s\n", log_id(m), log_id(target.module)); + log("Module %s matches %s\n", m, target.module); // Add target.module to map_design ("$cellmatch") // as a techmap rule to match m and replace it with target.module - Module *map = map_design->addModule(stringf("\\_60_%s_%s", log_id(m), log_id(target.module))); + Module *map = map_design->addModule(stringf("\\_60_%s_%s", m, target.module)); Cell *cell = map->addCell(ID::_TECHMAP_REPLACE_, target.module->name); map->attributes[ID(techmap_celltype)] = m->name.str(); diff --git a/passes/techmap/clkbufmap.cc b/passes/techmap/clkbufmap.cc index 7003c6656..7954b7891 100644 --- a/passes/techmap/clkbufmap.cc +++ b/passes/techmap/clkbufmap.cc @@ -257,14 +257,14 @@ struct ClkbufmapPass : public Pass { RTLIL::Cell *cell = nullptr; bool is_input = wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute(ID::top); if (!buf_celltype.empty() && (!is_input || buffer_inputs)) { - log("Inserting %s on %s.%s[%d].\n", buf_celltype, log_id(module), log_id(wire), i); + log("Inserting %s on %s.%s[%d].\n", buf_celltype, module, wire, i); cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype)); iwire = module->addWire(NEW_ID); cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit); cell->setPort(RTLIL::escape_id(buf_portname2), iwire); } if (is_input) { - log("Inserting %s on %s.%s[%d].\n", inpad_celltype, log_id(module), log_id(wire), i); + log("Inserting %s on %s.%s[%d].\n", inpad_celltype, module, wire, i); RTLIL::Cell *cell2 = module->addCell(NEW_ID, RTLIL::escape_id(inpad_celltype)); if (iwire) { cell2->setPort(RTLIL::escape_id(inpad_portname), iwire); diff --git a/passes/techmap/clockgate.cc b/passes/techmap/clockgate.cc index b68e5d93d..650719cd5 100644 --- a/passes/techmap/clockgate.cc +++ b/passes/techmap/clockgate.cc @@ -337,6 +337,8 @@ struct ClockgatePass : public Pass { FfData ff(nullptr, cell); // It would be odd to get constants, but we better handle it if (ff.has_ce) { + if (ff.has_srst && !ff.ce_over_srst) + continue; if (!ff.sig_clk.is_bit() || !ff.sig_ce.is_bit()) continue; if (!ff.sig_clk[0].is_wire() || !ff.sig_ce[0].is_wire()) diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc index 5245331f8..103fba103 100644 --- a/passes/techmap/deminout.cc +++ b/passes/techmap/deminout.cc @@ -126,7 +126,7 @@ struct DeminoutPass : public Pass { } if (new_input != new_output) { - log("Demoting inout port %s.%s to %s.\n", log_id(module), log_id(wire), new_input ? "input" : "output"); + log("Demoting inout port %s.%s to %s.\n", module, wire, new_input ? "input" : "output"); wire->port_input = new_input; wire->port_output = new_output; keep_running = true; diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc index 013675c8a..912f7fb81 100644 --- a/passes/techmap/dffinit.cc +++ b/passes/techmap/dffinit.cc @@ -123,14 +123,14 @@ struct DffinitPass : public Pass { if (noreinit && value[i] != State::Sx && value[i] != initval[i]) log_error("Trying to assign a different init value for %s.%s.%s which technically " "have a conflicted init value.\n", - log_id(module), log_id(cell), log_id(it.second)); + module, cell, it.second.unescape()); value.set(i, initval[i]); } if (highlow_mode && GetSize(value) != 0) { if (GetSize(value) != 1) log_error("Multi-bit init value for %s.%s.%s is incompatible with -highlow mode.\n", - log_id(module), log_id(cell), log_id(it.second)); + module, cell, it.second.unescape()); if (value[0] == State::S1) value = Const(high_string); else @@ -138,8 +138,8 @@ struct DffinitPass : public Pass { } if (value.size() != 0) { - log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second), - log_id(it.first), log_signal(sig), log_signal(value)); + log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", module, cell, it.second.unescape(), + it.first.unescape(), log_signal(sig), log_signal(value)); cell->setParam(it.second, value); } } diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc index dc29750c8..3cba527b2 100644 --- a/passes/techmap/dfflegalize.cc +++ b/passes/techmap/dfflegalize.cc @@ -263,7 +263,7 @@ struct DffLegalizePass : public Pass { } void fail_ff(const FfData &ff, const char *reason) { - log_error("FF %s.%s (type %s) cannot be legalized: %s\n", log_id(ff.module->name), log_id(ff.cell->name), log_id(ff.cell->type), reason); + log_error("FF %s.%s (type %s) cannot be legalized: %s\n", ff.module->name.unescape(), ff.cell->name.unescape(), ff.cell->type.unescape(), reason); } bool try_flip(FfData &ff, int supported_mask) { @@ -381,7 +381,7 @@ struct DffLegalizePass : public Pass { if (ff.has_ce && !supported_cells[FF_ADFFE]) ff.unmap_ce(); - log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name)); + log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", ff.module->name.unescape(), ff.cell->name.unescape()); log_assert(ff.width == 1); ff.remove(); @@ -600,7 +600,7 @@ struct DffLegalizePass : public Pass { ff.unmap_ce(); if (ff.cell) - log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name)); + log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", ff.module->name.unescape(), ff.cell->name.unescape()); emulate_split_init_arst(ff); return; } @@ -752,7 +752,7 @@ struct DffLegalizePass : public Pass { // The only hope left is breaking down to adlatch + dlatch + dlatch + mux. if (ff.cell) - log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name)); + log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", ff.module->name.unescape(), ff.cell->name.unescape()); ff.remove(); emulate_split_init_arst(ff); diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index 7461e21d8..d4d13d673 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -155,12 +155,12 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, std::map sig_bit_ref; if (sel && !sel->selected(mod)) { - log(" Skipping module %s as it is not selected.\n", log_id(mod->name)); + log(" Skipping module %s as it is not selected.\n", mod->name.unescape()); return false; } if (mod->processes.size() > 0) { - log(" Skipping module %s as it contains unprocessed processes.\n", log_id(mod->name)); + log(" Skipping module %s as it contains unprocessed processes.\n", mod->name.unescape()); return false; } @@ -674,7 +674,7 @@ struct ExtractPass : public Pass { } RTLIL::Cell *new_cell = replace(needle_map.at(result.needleGraphId), haystack_map.at(result.haystackGraphId), result); design->select(haystack_map.at(result.haystackGraphId), new_cell); - log(" new cell: %s\n", log_id(new_cell->name)); + log(" new cell: %s\n", new_cell->name.unescape()); } } } @@ -691,12 +691,12 @@ struct ExtractPass : public Pass { for (auto &result: results) { log("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits); - log(" primary match in %s:", log_id(haystack_map.at(result.graphId)->name)); + log(" primary match in %s:", haystack_map.at(result.graphId)->name.unescape()); for (auto &node : result.nodes) log(" %s", RTLIL::unescape_id(node.nodeId)); log("\n"); for (auto &it : result.matchesPerGraph) - log(" matches in %s: %d\n", log_id(haystack_map.at(it.first)->name), it.second); + log(" matches in %s: %d\n", haystack_map.at(it.first)->name.unescape(), it.second); RTLIL::Module *mod = haystack_map.at(result.graphId); std::set cells; @@ -716,7 +716,7 @@ struct ExtractPass : public Pass { } RTLIL::Module *newMod = new RTLIL::Module; - newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, log_id(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits); + newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, haystack_map.at(result.graphId)->name.unescape(), result.totalMatchesAfterLimits); map->add(newMod); for (auto wire : wires) { diff --git a/passes/techmap/extract_counter.cc b/passes/techmap/extract_counter.cc index c45792f66..c0e45a70e 100644 --- a/passes/techmap/extract_counter.cc +++ b/passes/techmap/extract_counter.cc @@ -541,7 +541,7 @@ void counter_worker( { extract_value = *sa.begin(); log(" Signal %s declared at %s has COUNT_EXTRACT = %s\n", - log_id(port_wire), + port_wire, count_reg_src.c_str(), extract_value.c_str()); @@ -604,14 +604,14 @@ void counter_worker( { log_error( "Counter extraction is set to FORCE on register %s, but a counter could not be inferred (%s)\n", - log_id(port_wire), + port_wire, reasons[reason]); } return; } //Get new cell name - string countname = string("$COUNTx$") + log_id(extract.rwire->name.str()); + string countname = string("$COUNTx$") + extract.rwire->name.unescape(); //Wipe all of the old connections to the ALU cell->unsetPort(ID::A); @@ -697,7 +697,7 @@ void counter_worker( //Hook up any parallel outputs for(auto load : extract.pouts) { - log(" Counter has parallel output to cell %s port %s\n", log_id(load.cell->name), log_id(load.port)); + log(" Counter has parallel output to cell %s port %s\n", load.cell->name.unescape(), load.port.unescape()); } if(extract.has_pout) { @@ -731,7 +731,7 @@ void counter_worker( countname.c_str(), extract.count_is_up ? "to" : "from", extract.count_value, - log_id(extract.rwire->name), + extract.rwire->name.unescape(), count_reg_src.c_str()); //Optimize the counter @@ -887,13 +887,13 @@ struct ExtractCounterPass : public Pass { for(auto cell : cells_to_remove) { - //log("Removing cell %s\n", log_id(cell->name)); + //log("Removing cell %s\n", cell); module->remove(cell); } for(auto cpair : cells_to_rename) { - //log("Renaming cell %s to %s\n", log_id(cpair.first->name), cpair.second); + //log("Renaming cell %s to %s\n", cpair.first, cpair.second); module->rename(cpair.first, cpair.second); } } diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc index 46ab7e520..15cdc54c9 100644 --- a/passes/techmap/extract_fa.cc +++ b/passes/techmap/extract_fa.cc @@ -289,7 +289,7 @@ struct ExtractFaWorker void run() { - log("Extracting full/half adders from %s:\n", log_id(module)); + log("Extracting full/half adders from %s:\n", module); for (auto it : driver) { @@ -381,7 +381,7 @@ struct ExtractFaWorker auto &fa = facache.at(fakey); X = get<0>(fa); Y = get<1>(fa); - log(" Reusing $fa cell %s.\n", log_id(get<2>(fa))); + log(" Reusing $fa cell %s.\n", get<2>(fa)); } else if (facache.count(fakey_inv)) @@ -390,14 +390,14 @@ struct ExtractFaWorker invert_xy = true; X = get<0>(fa); Y = get<1>(fa); - log(" Reusing $fa cell %s.\n", log_id(get<2>(fa))); + log(" Reusing $fa cell %s.\n", get<2>(fa)); } else { Cell *cell = module->addCell(NEW_ID, ID($fa)); cell->setParam(ID::WIDTH, 1); - log(" Created $fa cell %s.\n", log_id(cell)); + log(" Created $fa cell %s.\n", cell); cell->setPort(ID::A, f3i.inv_a ? module->NotGate(NEW_ID, A) : A); cell->setPort(ID::B, f3i.inv_b ? module->NotGate(NEW_ID, B) : B); @@ -488,7 +488,7 @@ struct ExtractFaWorker auto &fa = facache.at(fakey); X = get<0>(fa); Y = get<1>(fa); - log(" Reusing $fa cell %s.\n", log_id(get<2>(fa))); + log(" Reusing $fa cell %s.\n", get<2>(fa)); } else if (facache.count(fakey_inv)) @@ -497,14 +497,14 @@ struct ExtractFaWorker invert_xy = true; X = get<0>(fa); Y = get<1>(fa); - log(" Reusing $fa cell %s.\n", log_id(get<2>(fa))); + log(" Reusing $fa cell %s.\n", get<2>(fa)); } else { Cell *cell = module->addCell(NEW_ID, ID($fa)); cell->setParam(ID::WIDTH, 1); - log(" Created $fa cell %s.\n", log_id(cell)); + log(" Created $fa cell %s.\n", cell); cell->setPort(ID::A, f2i.inv_a ? module->NotGate(NEW_ID, A) : A); cell->setPort(ID::B, f2i.inv_b ? module->NotGate(NEW_ID, B) : B); diff --git a/passes/techmap/extractinv.cc b/passes/techmap/extractinv.cc index 5050e1464..7444369cc 100644 --- a/passes/techmap/extractinv.cc +++ b/passes/techmap/extractinv.cc @@ -100,7 +100,7 @@ struct ExtractinvPass : public Pass { continue; SigSpec sig = port.second; if (it2->second.size() != sig.size()) - log_error("The inversion parameter needs to be the same width as the port (%s.%s port %s parameter %s)", log_id(module->name), log_id(cell->type), log_id(port.first), log_id(param_name)); + log_error("The inversion parameter needs to be the same width as the port (%s.%s port %s parameter %s)", module->name.unescape(), cell->type.unescape(), port.first.unescape(), param_name.unescape()); RTLIL::Const invmask = it2->second; cell->parameters.erase(param_name); if (invmask.is_fully_zero()) @@ -111,7 +111,7 @@ struct ExtractinvPass : public Pass { RTLIL::Cell *icell = module->addCell(NEW_ID, RTLIL::escape_id(inv_celltype)); icell->setPort(RTLIL::escape_id(inv_portname), SigSpec(iwire, i)); icell->setPort(RTLIL::escape_id(inv_portname2), sig[i]); - log("Inserting %s on %s.%s.%s[%d].\n", inv_celltype, log_id(module), log_id(cell->type), log_id(port.first), i); + log("Inserting %s on %s.%s.%s[%d].\n", inv_celltype, module, cell->type.unescape(), port.first.unescape(), i); sig[i] = SigBit(iwire, i); } cell->setPort(port.first, sig); diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc index f5f225a9b..a6d461209 100644 --- a/passes/techmap/flowmap.cc +++ b/passes/techmap/flowmap.cc @@ -598,7 +598,7 @@ struct FlowmapWorker continue; if (!cell->known()) - log_error("Cell %s (%s.%s) is unknown.\n", cell->type, log_id(module), log_id(cell)); + log_error("Cell %s (%s.%s) is unknown.\n", cell->type, module, cell); pool fanout; for (auto conn : cell->connections()) @@ -636,7 +636,7 @@ struct FlowmapWorker if (fanin > order) log_error("Cell %s (%s.%s) with fan-in %d cannot be mapped to a %d-LUT.\n", - cell->type.c_str(), log_id(module), log_id(cell), fanin, order); + cell->type.c_str(), module, cell, fanin, order); gate_count++; gate_area += 1 << fanin; @@ -1246,14 +1246,14 @@ struct FlowmapWorker } } log(" Breaking LUT %s to %s LUT %s (potential %d).\n", - log_signal(breaking_lut), lut_nodes[breaking_gate] ? "reuse" : "extract", log_signal(breaking_gate), best_potential); + log_signal(breaking_lut), lut_nodes[breaking_gate] ? "reuse" : "extract", log_signal(breaking_gate), best_potential); if (debug_relax) log(" Removing breaking gate %s from LUT.\n", log_signal(breaking_gate)); lut_gates[breaking_lut].erase(breaking_gate); auto cut_inputs = cut_lut_at_gate(breaking_lut, breaking_gate); - pool gate_inputs = cut_inputs.first, other_inputs = cut_inputs.second; + pool gate_inputs = cut_inputs.first; pool worklist = lut_gates[breaking_lut]; pool elim_gates = gate_inputs; @@ -1356,14 +1356,14 @@ struct FlowmapWorker auto origin = node_origins[node]; if (origin.cell->getPort(origin.port).size() == 1) log("Packing %s.%s.%s (%s).\n", - log_id(module), log_id(origin.cell), origin.port.c_str(), log_signal(node)); + module, origin.cell, origin.port.c_str(), log_signal(node)); else log("Packing %s.%s.%s [%d] (%s).\n", - log_id(module), log_id(origin.cell), origin.port.c_str(), origin.offset, log_signal(node)); + module, origin.cell, origin.port.c_str(), origin.offset, log_signal(node)); } else { - log("Packing %s.%s.\n", log_id(module), log_signal(node)); + log("Packing %s.%s.\n", module, log_signal(node)); } for (auto gate_node : lut_gates[node]) @@ -1376,10 +1376,10 @@ struct FlowmapWorker auto gate_origin = node_origins[gate_node]; if (gate_origin.cell->getPort(gate_origin.port).size() == 1) log(" Packing %s.%s.%s (%s).\n", - log_id(module), log_id(gate_origin.cell), gate_origin.port.c_str(), log_signal(gate_node)); + module, gate_origin.cell, gate_origin.port.c_str(), log_signal(gate_node)); else log(" Packing %s.%s.%s [%d] (%s).\n", - log_id(module), log_id(gate_origin.cell), gate_origin.port.c_str(), gate_origin.offset, log_signal(gate_node)); + module, gate_origin.cell, gate_origin.port.c_str(), gate_origin.offset, log_signal(gate_node)); } vector input_nodes(lut_edges_bw[node].begin(), lut_edges_bw[node].end()); @@ -1423,9 +1423,9 @@ struct FlowmapWorker lut_area += lut_table.size(); if ((int)input_nodes.size() >= minlut) - log(" Packed into a %d-LUT %s.%s.\n", GetSize(input_nodes), log_id(module), log_id(lut)); + log(" Packed into a %d-LUT %s.%s.\n", GetSize(input_nodes), module, lut); else - log(" Packed into a %d-LUT %s.%s (implemented as %d-LUT).\n", GetSize(input_nodes), log_id(module), log_id(lut), minlut); + log(" Packed into a %d-LUT %s.%s (implemented as %d-LUT).\n", GetSize(input_nodes), module, lut, minlut); } for (auto node : mapped_nodes) diff --git a/passes/techmap/insbuf.cc b/passes/techmap/insbuf.cc index f288987a1..5674de71f 100644 --- a/passes/techmap/insbuf.cc +++ b/passes/techmap/insbuf.cc @@ -83,7 +83,7 @@ struct InsbufPass : public Pass { if (!lhs.wire || !design->selected(module, lhs.wire)) { new_conn.first.append(lhs); new_conn.second.append(rhs); - log("Skip %s: %s -> %s\n", log_id(module), log_signal(rhs), log_signal(lhs)); + log("Skip %s: %s -> %s\n", module, log_signal(rhs), log_signal(lhs)); continue; } @@ -98,7 +98,7 @@ struct InsbufPass : public Pass { cell->setPort(in_portname, rhs); cell->setPort(out_portname, lhs); - log("Add %s/%s: %s -> %s\n", log_id(module), log_id(cell), log_signal(rhs), log_signal(lhs)); + log("Add %s/%s: %s -> %s\n", module, cell, log_signal(rhs), log_signal(lhs)); bufcells.insert(cell); } @@ -115,8 +115,8 @@ struct InsbufPass : public Pass { auto s = sigmap(port.second); if (s == port.second) continue; - log("Rewrite %s/%s/%s: %s -> %s\n", log_id(module), log_id(cell), - log_id(port.first), log_signal(port.second), log_signal(s)); + log("Rewrite %s/%s/%s: %s -> %s\n", module, cell, + port.first.unescape(), log_signal(port.second), log_signal(s)); cell->setPort(port.first, s); } } diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index d929de300..d7667d6f5 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -231,7 +231,7 @@ struct IopadmapPass : public Pass { for (int i = 0; i < GetSize(wire); i++) if (buf_bits.count(sigmap(SigBit(wire, i)))) { buf_ports.insert(make_pair(module->name, make_pair(wire->name, i))); - log("Marking already mapped port: %s.%s[%d].\n", log_id(module), log_id(wire), i); + log("Marking already mapped port: %s.%s[%d].\n", module, wire, i); } } @@ -324,10 +324,10 @@ struct IopadmapPass : public Pass { if (wire->port_input) { - log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype); + log("Mapping port %s.%s[%d] using %s.\n", module, wire, i, tinoutpad_celltype); Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), + module->uniquify(stringf("$iopadmap$%s.%s[%d]", module, wire, i)), RTLIL::escape_id(tinoutpad_celltype)); if (tinoutpad_neg_oe) @@ -348,10 +348,10 @@ struct IopadmapPass : public Pass { if (!tinoutpad_portname_pad.empty()) rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(tinoutpad_portname_pad)); } else { - log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, toutpad_celltype); + log("Mapping port %s.%s[%d] using %s.\n", module, wire, i, toutpad_celltype); Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), + module->uniquify(stringf("$iopadmap$%s.%s[%d]", module, wire, i)), RTLIL::escape_id(toutpad_celltype)); if (toutpad_neg_oe) @@ -433,7 +433,7 @@ struct IopadmapPass : public Pass { SigBit wire_bit(wire, i); RTLIL::Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), + module->uniquify(stringf("$iopadmap$%s.%s", module->name.unescape(), wire->name.unescape())), RTLIL::escape_id(celltype)); cell->setPort(RTLIL::escape_id(portname_int), wire_bit); @@ -449,14 +449,14 @@ struct IopadmapPass : public Pass { else { RTLIL::Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), + module->uniquify(stringf("$iopadmap$%s.%s", module->name.unescape(), wire->name.unescape())), RTLIL::escape_id(celltype)); cell->setPort(RTLIL::escape_id(portname_int), RTLIL::SigSpec(wire)); if (!portname_pad.empty()) { RTLIL::Wire *new_wire = NULL; new_wire = module->addWire( - module->uniquify(stringf("$iopadmap$%s", log_id(wire))), + module->uniquify(stringf("$iopadmap$%s", wire)), wire); module->swap_names(new_wire, wire); wire->attributes.clear(); @@ -500,7 +500,7 @@ struct IopadmapPass : public Pass { for (auto &it : rewrite_bits) { RTLIL::Wire *wire = it.first; RTLIL::Wire *new_wire = module->addWire( - module->uniquify(stringf("$iopadmap$%s", log_id(wire))), + module->uniquify(stringf("$iopadmap$%s", wire)), wire); module->swap_names(new_wire, wire); wire->attributes.clear(); diff --git a/passes/techmap/liberty_cache.h b/passes/techmap/liberty_cache.h new file mode 100644 index 000000000..8ae89947f --- /dev/null +++ b/passes/techmap/liberty_cache.h @@ -0,0 +1,145 @@ +#ifndef LIBERTY_CACHE_H +#define LIBERTY_CACHE_H + +#include "kernel/yosys.h" + +#ifdef YOSYS_LINK_ABC +namespace abc { + int Abc_RealMain(int argc, char *argv[]); +} +#endif + +YOSYS_NAMESPACE_BEGIN + +/* + * convert_liberty_files_to_merged_scl() - Convert multiple Liberty files to a single merged SCL cache file. + * @liberty_files: Vector of liberty file paths to merge + * @dont_use_args: Pre-built ABC -X flags string + * @abc_exe: Path to ABC executable for conversion + * + * Return: Path to merged SCL cache file, or empty string if conversion fails + */ +inline std::string convert_liberty_files_to_merged_scl(const std::vector &liberty_files, const std::string &dont_use_args, const std::string &abc_exe) +{ + if (liberty_files.empty()) + return ""; + + std::string cache_dir = get_base_tmpdir() + "/yosys-liberty-scl-cache"; + + if (!create_directory(cache_dir)) { + log_warning("ABC: cannot create cache directory %s, falling back to liberty format\n", cache_dir.c_str()); + return ""; + } + + // Sort to ensure consistent hash regardless of order + std::vector sorted_files = liberty_files; + std::sort(sorted_files.begin(), sorted_files.end()); + std::string hash_input; + time_t newest_mtime = 0; + + for (const std::string &liberty_file : sorted_files) { + struct stat liberty_stat; + if (stat(liberty_file.c_str(), &liberty_stat) != 0) { + log_error("ABC: cannot stat liberty file: %s\n", liberty_file.c_str()); + return ""; + } + hash_input += liberty_file + "|"; + if (liberty_stat.st_mtime > newest_mtime) + newest_mtime = liberty_stat.st_mtime; + } + + hash_input += dont_use_args; + unsigned int hash = 0; + + for (char c : hash_input) + hash = hash * 31 + c; + + std::string merged_scl = stringf("%s/yosys_merged_%08x.scl", cache_dir.c_str(), hash); + bool need_convert = true; + struct stat scl_stat; + + // Check if merged SCL exists and is newer than all liberty files + if (stat(merged_scl.c_str(), &scl_stat) == 0) { + if (scl_stat.st_mtime >= newest_mtime) { + log("ABC: using cached merged SCL: %s (%zu files)\n", merged_scl.c_str(), liberty_files.size()); + need_convert = false; + } + } + + if (need_convert) { + // read_lib -X cell1 -X cell2 file1 ; read_lib -X cell1 -X cell2 -m file2 ; ... ; write_scl merged.scl + std::string temp_scl = merged_scl + ".tmp"; + +#ifdef YOSYS_LINK_ABC + std::string script_path = stringf("%s/yosys_merged_scl_convert_%08x.script", cache_dir.c_str(), hash); + FILE *f = fopen(script_path.c_str(), "w"); + + if (f == NULL) { + log_warning("ABC: cannot open %s for writing, falling back to liberty format\n", script_path.c_str()); + return ""; + } + + bool first = true; + + for (const std::string &liberty_file : liberty_files) { + fprintf(f, "read_lib %s%s-w \"%s\"\n", dont_use_args.c_str(), first ? "" : "-m ", liberty_file.c_str()); + first = false; + } + + fprintf(f, "write_scl \"%s\"\n", temp_scl.c_str()); + fclose(f); + + char *abc_argv[5]; + abc_argv[0] = strdup(abc_exe.empty() ? "yosys-abc" : abc_exe.c_str()); + abc_argv[1] = strdup("-s"); + abc_argv[2] = strdup("-f"); + abc_argv[3] = strdup(script_path.c_str()); + abc_argv[4] = 0; + int ret = abc::Abc_RealMain(4, abc_argv); + free(abc_argv[0]); + free(abc_argv[1]); + free(abc_argv[2]); + free(abc_argv[3]); + remove(script_path.c_str()); + + if (ret != 0) { + log_warning("ABC: merged SCL conversion failed (ret=%d), falling back to liberty format\n", ret); + remove(temp_scl.c_str()); + return ""; + } +#else + std::string abc_script; + bool first = true; + + for (const std::string &liberty_file : liberty_files) { + abc_script += stringf("read_lib %s%s-w \\\"%s\\\" ; ", dont_use_args.c_str(), first ? "" : "-m ", liberty_file.c_str()); + first = false; + } + + abc_script += stringf("write_scl \\\"%s\\\"", temp_scl.c_str()); + std::string cmd = stringf("\"%s\" -c \"%s\" 2>&1", abc_exe.c_str(), abc_script.c_str()); + std::string abc_output; + int ret = run_command(cmd, [&abc_output](const std::string &line) { abc_output += line + "\n"; }); + + if (ret != 0) { + log_warning("ABC: merged SCL conversion failed, falling back to liberty format\n"); + if (!abc_output.empty()) { + log("ABC: conversion output:\n%s", abc_output.c_str()); + } + remove(temp_scl.c_str()); + return ""; + } +#endif + if (rename(temp_scl.c_str(), merged_scl.c_str()) != 0) { + log_warning("ABC: failed to rename %s to %s, falling back to liberty format\n", temp_scl.c_str(), merged_scl.c_str()); + remove(temp_scl.c_str()); + return ""; + } + } + + return merged_scl; +} + +YOSYS_NAMESPACE_END + +#endif // LIBERTY_CACHE_H \ No newline at end of file diff --git a/passes/techmap/lut2bmux.cc b/passes/techmap/lut2bmux.cc index 42042c942..1073b1208 100644 --- a/passes/techmap/lut2bmux.cc +++ b/passes/techmap/lut2bmux.cc @@ -49,7 +49,7 @@ struct Lut2BmuxPass : public Pass { cell->setPort(ID::A, cell->getParam(ID::LUT)); cell->unsetParam(ID::LUT); cell->fixup_parameters(); - log("Converted %s.%s to BMUX cell.\n", log_id(module), log_id(cell)); + log("Converted %s.%s to BMUX cell.\n", module, cell); } } } diff --git a/passes/techmap/lut2mux.cc b/passes/techmap/lut2mux.cc index 3d45734ec..2ddb16d61 100644 --- a/passes/techmap/lut2mux.cc +++ b/passes/techmap/lut2mux.cc @@ -97,7 +97,7 @@ struct Lut2muxPass : public Pass { if (cell->type == ID($lut)) { IdString cell_name = cell->name; int count = lut2mux(cell, word_mode); - log("Converted %s.%s to %d MUX cells.\n", log_id(module), log_id(cell_name), count); + log("Converted %s.%s to %d MUX cells.\n", module, cell_name.unescape(), count); } } } diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc index 42b615002..cb041f615 100644 --- a/passes/techmap/maccmap.cc +++ b/passes/techmap/maccmap.cc @@ -404,7 +404,7 @@ struct MaccmapPass : public Pass { for (auto mod : design->selected_modules()) for (auto cell : mod->selected_cells()) if (cell->type.in(ID($macc), ID($macc_v2))) { - log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type)); + log("Mapping %s.%s (%s).\n", mod, cell, cell->type.unescape()); maccmap(mod, cell, unmap_mode); mod->remove(cell); } diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 2656f30ce..719a346d8 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -596,7 +596,7 @@ struct MuxcoverWorker void run() { - log("Covering MUX trees in module %s..\n", log_id(module)); + log("Covering MUX trees in module %s..\n", module); treeify(); diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 928182970..9f4e307f9 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -284,7 +284,7 @@ struct ShregmapWorker Cell *last_cell = chain[cursor+depth-1]; log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", - log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); + module, first_cell, module, last_cell, depth); dff_count += depth; shreg_count += 1; diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 0c7d1930e..2c252deb3 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -438,6 +438,48 @@ void simplemap_ff(RTLIL::Module *, RTLIL::Cell *cell) } } +void simplemap_pmux(RTLIL::Module *module, RTLIL::Cell *cell) +{ + RTLIL::SigSpec sig_a = cell->getPort(ID::A); + RTLIL::SigSpec sig_b = cell->getPort(ID::B); + RTLIL::SigSpec sig_s = cell->getPort(ID::S); + RTLIL::SigSpec sig_y = cell->getPort(ID::Y); + + int width = GetSize(sig_a); + int s_width = GetSize(sig_s); + + // Implement: |S + RTLIL::SigSpec any_s = sig_s; + logic_reduce(module, any_s, cell); + + for (int i = 0; i < width; i++) { + RTLIL::SigSpec b_and_bits; + + // Implement: B_AND_BITS = B_AND_S[WIDTH*j+i] + for (int j = 0; j < s_width; j++) { + RTLIL::Cell *and_gate = module->addCell(NEW_ID, ID($_AND_)); + transfer_src(and_gate, cell); + and_gate->setPort(ID::A, sig_b[j * width + i]); + and_gate->setPort(ID::B, sig_s[j]); + + RTLIL::SigSpec and_y = module->addWire(NEW_ID, 1); + and_gate->setPort(ID::Y, and_y); + b_and_bits.append(and_y); + } + + // Implement: Y_B[i] = |B_AND_BITS + logic_reduce(module, b_and_bits, cell); + + // Implement: Y[i] = |S ? Y_B[i] : A[i] + RTLIL::Cell *mux_gate = module->addCell(NEW_ID, ID($_MUX_)); + transfer_src(mux_gate, cell); + mux_gate->setPort(ID::A, sig_a[i]); + mux_gate->setPort(ID::B, b_and_bits); + mux_gate->setPort(ID::S, any_s); + mux_gate->setPort(ID::Y, sig_y[i]); + } +} + void simplemap_get_mappers(dict &mappers) { mappers[ID($not)] = simplemap_not; @@ -461,6 +503,7 @@ void simplemap_get_mappers(dict mappers[ID($ne)] = simplemap_eqne; mappers[ID($nex)] = simplemap_eqne; mappers[ID($mux)] = simplemap_mux; + mappers[ID($pmux)] = simplemap_pmux; mappers[ID($bwmux)] = simplemap_bwmux; mappers[ID($tribuf)] = simplemap_tribuf; mappers[ID($bmux)] = simplemap_bmux; @@ -515,7 +558,7 @@ struct SimplemapPass : public Pass { log("\n"); log(" $not, $pos, $and, $or, $xor, $xnor\n"); log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n"); - log(" $logic_not, $logic_and, $logic_or, $mux, $tribuf\n"); + log(" $logic_not, $logic_and, $logic_or, $mux, $pmux, $tribuf\n"); log(" $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $aldff, $aldffe, $sdff,\n"); log(" $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\n"); log("\n"); @@ -537,7 +580,7 @@ struct SimplemapPass : public Pass { continue; if (!design->selected(mod, cell)) continue; - log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type)); + log("Mapping %s.%s (%s).\n", mod, cell, cell->type.unescape()); mappers.at(cell->type)(mod, cell); mod->remove(cell); } diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index cf7ce56e2..e975d2fd2 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -93,17 +93,17 @@ struct TechmapWorker RTLIL::SigBit bit = sigmap(conn.second[i]); if (bit.wire == nullptr) { if (verbose) - log(" Constant input on bit %d of port %s: %s\n", i, log_id(conn.first), log_signal(bit)); - constmap_info += stringf("|%s %d %d", log_id(conn.first), i, bit.data); + log(" Constant input on bit %d of port %s: %s\n", i, conn.first.unescape(), log_signal(bit)); + constmap_info += stringf("|%s %d %d", conn.first.unescape(), i, bit.data); } else if (connbits_map.count(bit)) { if (verbose) - log(" Bit %d of port %s and bit %d of port %s are connected.\n", i, log_id(conn.first), - connbits_map.at(bit).second, log_id(connbits_map.at(bit).first)); - constmap_info += stringf("|%s %d %s %d", log_id(conn.first), i, - log_id(connbits_map.at(bit).first), connbits_map.at(bit).second); + log(" Bit %d of port %s and bit %d of port %s are connected.\n", i, conn.first.unescape(), + connbits_map.at(bit).second, connbits_map.at(bit).first.unescape()); + constmap_info += stringf("|%s %d %s %d", conn.first.unescape(), i, + connbits_map.at(bit).first.unescape(), connbits_map.at(bit).second); } else { connbits_map.emplace(bit, std::make_pair(conn.first, i)); - constmap_info += stringf("|%s %d", log_id(conn.first), i); + constmap_info += stringf("|%s %d", conn.first.unescape(), i); } } @@ -146,7 +146,7 @@ struct TechmapWorker if (tpl->processes.size() != 0) { log("Technology map yielded processes:"); for (auto &it : tpl->processes) - log(" %s",log_id(it.first)); + log(" %s",it.first.unescape()); log("\n"); if (autoproc_mode) { Pass::call_on_module(tpl->design, tpl, "proc"); @@ -435,7 +435,7 @@ struct TechmapWorker if (celltypeMap.count(cell->type) == 0) { if (assert_mode && !cell->type.ends_with("_")) - log_error("(ASSERT MODE) No matching template cell for type %s found.\n", log_id(cell->type)); + log_error("(ASSERT MODE) No matching template cell for type %s found.\n", cell->type.unescape()); continue; } @@ -498,10 +498,10 @@ struct TechmapWorker { if ((extern_mode && !in_recursion) || extmapper_name == "wrap") { - std::string m_name = stringf("$extern:%s:%s", extmapper_name, log_id(cell->type)); + std::string m_name = stringf("$extern:%s:%s", extmapper_name, cell->type.unescape()); for (auto &c : cell->parameters) - m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second)); + m_name += stringf(":%s=%s", c.first.unescape(), log_signal(c.second)); if (extmapper_name == "wrap") m_name += ":" + sha1(tpl->attributes.at(ID::techmap_wrap).decode_string()); @@ -531,24 +531,24 @@ struct TechmapWorker extmapper_module->check(); if (extmapper_name == "simplemap") { - log("Creating %s with simplemap.\n", log_id(extmapper_module)); + log("Creating %s with simplemap.\n", extmapper_module); if (simplemap_mappers.count(extmapper_cell->type) == 0) - log_error("No simplemap mapper for cell type %s found!\n", log_id(extmapper_cell->type)); + log_error("No simplemap mapper for cell type %s found!\n", extmapper_cell->type.unescape()); simplemap_mappers.at(extmapper_cell->type)(extmapper_module, extmapper_cell); extmapper_module->remove(extmapper_cell); } if (extmapper_name == "maccmap") { - log("Creating %s with maccmap.\n", log_id(extmapper_module)); + log("Creating %s with maccmap.\n", extmapper_module); if (!extmapper_cell->type.in(ID($macc), ID($macc_v2))) - log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", log_id(extmapper_cell->type)); + log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", extmapper_cell->type.unescape()); maccmap(extmapper_module, extmapper_cell); extmapper_module->remove(extmapper_cell); } if (extmapper_name == "wrap") { std::string cmd_string = tpl->attributes.at(ID::techmap_wrap).decode_string(); - log("Running \"%s\" on wrapper %s.\n", cmd_string, log_id(extmapper_module)); + log("Running \"%s\" on wrapper %s.\n", cmd_string, extmapper_module); mkdebug.on(); Pass::call_on_module(extmapper_design, extmapper_module, cmd_string); log_continue = true; @@ -563,31 +563,31 @@ struct TechmapWorker goto use_wrapper_tpl; } - auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type)); + auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_module, cell->type.unescape()); if (!log_msg_cache.count(msg)) { log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module)); + log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), extmapper_module); } else { - auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name, log_id(cell->type)); + auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name, cell->type.unescape()); if (!log_msg_cache.count(msg)) { log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), extmapper_name); + log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), extmapper_name); if (extmapper_name == "simplemap") { if (simplemap_mappers.count(cell->type) == 0) - log_error("No simplemap mapper for cell type %s found!\n", log_id(cell->type)); + log_error("No simplemap mapper for cell type %s found!\n", cell->type.unescape()); simplemap_mappers.at(cell->type)(module, cell); } if (extmapper_name == "maccmap") { if (!cell->type.in(ID($macc), ID($macc_v2))) - log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", log_id(cell->type)); + log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", cell->type.unescape()); maccmap(module, cell); } @@ -621,21 +621,21 @@ struct TechmapWorker parameters.emplace(ID::_TECHMAP_CELLNAME_, RTLIL::unescape_id(cell->name)); for (auto &conn : cell->connections()) { - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape())) != 0) { std::vector v = sigmap(conn.second).to_sigbit_vector(); for (auto &bit : v) bit = RTLIL::SigBit(bit.wire == nullptr ? RTLIL::State::S1 : RTLIL::State::S0); - parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const()); + parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape()), RTLIL::SigSpec(v).as_const()); } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", conn.first.unescape())) != 0) { std::vector v = sigmap(conn.second).to_sigbit_vector(); for (auto &bit : v) if (bit.wire != nullptr) bit = RTLIL::SigBit(RTLIL::State::Sx); - parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const()); + parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", conn.first.unescape()), RTLIL::SigSpec(v).as_const()); } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first))) != 0) { - parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), initvals(conn.second)); + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", conn.first.unescape())) != 0) { + parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", conn.first.unescape()), initvals(conn.second)); } } @@ -648,7 +648,7 @@ struct TechmapWorker unique_bit_id[RTLIL::State::Sz] = unique_bit_id_counter++; for (auto &conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape())) != 0) { for (auto &bit : sigmap(conn.second)) if (unique_bit_id.count(bit) == 0) unique_bit_id[bit] = unique_bit_id_counter++; @@ -665,7 +665,7 @@ struct TechmapWorker parameters[ID::_TECHMAP_BITS_CONNMAP_] = bits; for (auto &conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape())) != 0) { SigSpec sm = sigmap(conn.second); RTLIL::Const::Builder builder(GetSize(sm) * bits); for (auto &bit : sm) { @@ -675,7 +675,7 @@ struct TechmapWorker val = val >> 1; } } - parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), builder.build()); + parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape()), builder.build()); } } @@ -724,7 +724,7 @@ struct TechmapWorker RTLIL::SigSpec value = elem.value; if (value.is_fully_const() && value.as_bool()) { log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n", - derived_name.c_str(), log_id(elem.wire->name), log_signal(value)); + derived_name.c_str(), elem.wire->name.unescape(), log_signal(value)); techmap_do_cache[tpl] = false; } } @@ -741,7 +741,7 @@ struct TechmapWorker auto &data = it.second.front(); if (!data.value.is_fully_const()) - log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(data.wire->name), log_signal(data.value)); + log_error("Techmap yielded config wire %s with non-const value %s.\n", data.wire->name.unescape(), log_signal(data.value)); techmap_wire_names.erase(it.first); @@ -758,7 +758,7 @@ struct TechmapWorker log("Analyzing pattern of constant bits for this cell:\n"); IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true); - log("Creating constmapped module `%s'.\n", log_id(new_tpl_name)); + log("Creating constmapped module `%s'.\n", new_tpl_name.unescape()); log_assert(map->module(new_tpl_name) == nullptr); RTLIL::Module *new_tpl = map->addModule(new_tpl_name); @@ -865,16 +865,16 @@ struct TechmapWorker TechmapWires twd = techmap_find_special_wires(tpl); for (auto &it : twd) { if (!it.first.ends_with("_TECHMAP_FAIL_") && (!it.first.begins_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !it.first.contains("_TECHMAP_DO_") && !it.first.contains("_TECHMAP_DONE_")) - log_error("Techmap yielded unknown config wire %s.\n", log_id(it.first)); + log_error("Techmap yielded unknown config wire %s.\n", it.first.unescape()); if (techmap_do_cache[tpl]) for (auto &it2 : it.second) if (!it2.value.is_fully_const()) - log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(it2.wire->name), log_signal(it2.value)); + log_error("Techmap yielded config wire %s with non-const value %s.\n", it2.wire->name.unescape(), log_signal(it2.value)); techmap_wire_names.erase(it.first); } for (auto &it : techmap_wire_names) - log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", log_id(it)); + log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", it.unescape()); if (recursive_mode) { if (log_continue) { @@ -914,7 +914,7 @@ struct TechmapWorker if (extern_mode && !in_recursion) { - std::string m_name = stringf("$extern:%s", log_id(tpl)); + std::string m_name = stringf("$extern:%s", tpl); if (!design->module(m_name)) { @@ -924,18 +924,18 @@ struct TechmapWorker module_queue.insert(m); } - log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(m_name)); + log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, module, cell, m_name); cell->type = m_name; cell->parameters.clear(); } else { - auto msg = stringf("Using template %s for cells of type %s.", log_id(tpl), log_id(cell->type)); + auto msg = stringf("Using template %s for cells of type %s.", tpl, cell->type.unescape()); if (!log_msg_cache.count(msg)) { log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(tpl)); + log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), tpl); techmap_module_worker(design, module, cell, tpl); cell = nullptr; } @@ -945,7 +945,7 @@ struct TechmapWorker } if (assert_mode && !mapped_cell) - log_error("(ASSERT MODE) Failed to map cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log_error("(ASSERT MODE) Failed to map cell %s.%s (%s).\n", module, cell, cell->type.unescape()); handled_cells.insert(cell); } @@ -1265,8 +1265,8 @@ struct TechmapPass : public Pass { i.second.sort(RTLIL::sort_by_id_str()); std::string maps = ""; for (auto &map : i.second) - maps += stringf(" %s", log_id(map)); - log_debug(" %s:%s\n", log_id(i.first), maps); + maps += stringf(" %s", map.unescape()); + log_debug(" %s:%s\n", i.first.unescape(), maps); } log_debug("\n"); diff --git a/passes/techmap/tribuf.cc b/passes/techmap/tribuf.cc index b45cd268a..07f51bdae 100644 --- a/passes/techmap/tribuf.cc +++ b/passes/techmap/tribuf.cc @@ -142,7 +142,7 @@ struct TribufWorker { auto conflict = module->And(NEW_ID, cell_s, other_s); - std::string name = stringf("$tribuf_conflict$%s", log_id(cell->name)); + std::string name = stringf("$tribuf_conflict$%s", cell->name.unescape()); auto assert_cell = module->addAssert(name, module->Not(NEW_ID, conflict), SigSpec(true)); assert_cell->set_src_attribute(cell->get_src_attribute()); diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc index 809651ebd..5b6a3adaf 100644 --- a/passes/techmap/zinit.cc +++ b/passes/techmap/zinit.cc @@ -68,7 +68,7 @@ struct ZinitPass : public Pass { FfData ff(&initvals, cell); - log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type), + log("FF init value for cell %s (%s): %s = %s\n", cell, cell->type.unescape(), log_signal(ff.sig_q), log_signal(ff.val_init)); pool bits; diff --git a/passes/tests/raise_error.cc b/passes/tests/raise_error.cc index b21ec7d1d..95b477bc8 100644 --- a/passes/tests/raise_error.cc +++ b/passes/tests/raise_error.cc @@ -71,7 +71,7 @@ struct RaiseErrorPass : public Pass { int err_no = 1; string err_msg = ""; if (err_obj != nullptr) { - log("Raising error from '%s'.\n", log_id(err_obj)); + log("Raising error from '%s'.\n", err_obj); err_no = err_obj->attributes[ID::raise_error].as_int(); if (err_no > 256) { err_msg = err_obj->get_string_attribute(ID::raise_error); diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 4d28e659b..3f2588bd1 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -596,20 +596,20 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: for (auto port : gold_mod->ports) { RTLIL::Wire *wire = gold_mod->wire(port); if (wire->port_input) - vlog_file << stringf(" reg [%d:0] %s;\n", GetSize(wire)-1, log_id(wire)); + vlog_file << stringf(" reg [%d:0] %s;\n", GetSize(wire)-1, wire); else - vlog_file << stringf(" wire [%d:0] %s_expr, %s_noexpr;\n", GetSize(wire)-1, log_id(wire), log_id(wire)); + vlog_file << stringf(" wire [%d:0] %s_expr, %s_noexpr;\n", GetSize(wire)-1, wire, wire); } vlog_file << stringf(" %s_expr uut_expr(", uut_name); for (int i = 0; i < GetSize(gold_mod->ports); i++) - vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", log_id(gold_mod->ports[i]), log_id(gold_mod->ports[i]), + vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", gold_mod->ports[i].unescape(), gold_mod->ports[i].unescape(), gold_mod->wire(gold_mod->ports[i])->port_input ? "" : "_expr"); vlog_file << stringf(");\n"); vlog_file << stringf(" %s_expr uut_noexpr(", uut_name); for (int i = 0; i < GetSize(gold_mod->ports); i++) - vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", log_id(gold_mod->ports[i]), log_id(gold_mod->ports[i]), + vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", gold_mod->ports[i].unescape(), gold_mod->ports[i].unescape(), gold_mod->wire(gold_mod->ports[i])->port_input ? "" : "_noexpr"); vlog_file << stringf(");\n"); @@ -654,7 +654,7 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: } if (verbose) - log("%s: %s\n", log_id(gold_wire), log_signal(in_value)); + log("%s: %s\n", gold_wire, log_signal(in_value)); in_sig.append(gold_wire); in_val.append(in_value); @@ -663,10 +663,10 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: gate_ce.set(gate_wire, in_value); if (vlog_file.is_open() && GetSize(in_value) > 0) { - vlog_file << stringf(" %s = 'b%s;\n", log_id(gold_wire), in_value.as_string()); + vlog_file << stringf(" %s = 'b%s;\n", gold_wire, in_value.as_string()); if (!vlog_pattern_info.empty()) vlog_pattern_info += " "; - vlog_pattern_info += stringf("%s=%s", log_id(gold_wire), log_signal(in_value)); + vlog_pattern_info += stringf("%s=%s", gold_wire, log_signal(in_value)); } } @@ -690,10 +690,10 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: RTLIL::SigSpec gate_outval(gate_wire); if (!gold_ce.eval(gold_outval)) - log_error("Failed to eval %s in gold module.\n", log_id(gold_wire)); + log_error("Failed to eval %s in gold module.\n", gold_wire); if (!gate_ce.eval(gate_outval)) - log_error("Failed to eval %s in gate module.\n", log_id(gate_wire)); + log_error("Failed to eval %s in gate module.\n", gate_wire); bool gold_gate_mismatch = false; for (int i = 0; i < GetSize(gold_wire); i++) { @@ -706,19 +706,19 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: } if (gold_gate_mismatch) - log_error("Mismatch in output %s: gold:%s != gate:%s\n", log_id(gate_wire), log_signal(gold_outval), log_signal(gate_outval)); + log_error("Mismatch in output %s: gold:%s != gate:%s\n", gate_wire, log_signal(gold_outval), log_signal(gate_outval)); if (verbose) - log("%s: %s\n", log_id(gold_wire), log_signal(gold_outval)); + log("%s: %s\n", gold_wire, log_signal(gold_outval)); out_sig.append(gold_wire); out_val.append(gold_outval); if (vlog_file.is_open()) { vlog_file << stringf(" $display(\"[%s] %s expected: %%b, expr: %%b, noexpr: %%b\", %d'b%s, %s_expr, %s_noexpr);\n", - vlog_pattern_info.c_str(), log_id(gold_wire), GetSize(gold_outval), gold_outval.as_string().c_str(), log_id(gold_wire), log_id(gold_wire)); - vlog_file << stringf(" if (%s_expr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire), GetSize(gold_outval), gold_outval.as_string()); - vlog_file << stringf(" if (%s_noexpr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire), GetSize(gold_outval), gold_outval.as_string()); + vlog_pattern_info.c_str(), gold_wire, GetSize(gold_outval), gold_outval.as_string().c_str(), gold_wire, gold_wire); + vlog_file << stringf(" if (%s_expr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", gold_wire, GetSize(gold_outval), gold_outval.as_string()); + vlog_file << stringf(" if (%s_noexpr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", gold_wire, GetSize(gold_outval), gold_outval.as_string()); } } @@ -1102,10 +1102,10 @@ struct TestCellPass : public Pass { int charcount = 100; for (auto &it : cell_types) { if (charcount > 60) { - cell_type_list += stringf("\n%s", + log_id(it.first)); + cell_type_list += stringf("\n%s", it.first.unescape()); charcount = 0; } else - cell_type_list += stringf(" %s", log_id(it.first)); + cell_type_list += stringf(" %s", it.first.unescape()); charcount += GetSize(it.first); } log_cmd_error("The cell type `%s' is currently not supported. Try one of these:%s\n", diff --git a/pyosys/generator.py b/pyosys/generator.py index f1d429724..4fd7a5698 100644 --- a/pyosys/generator.py +++ b/pyosys/generator.py @@ -376,7 +376,7 @@ class PyosysWrapperGenerator(object): def make_preprocessor_options(self): py_include = get_paths()["include"] preprocessor_bin = shutil.which("clang++") or "g++" - cxx_std = os.getenv("CXX_STD", "c++17") + cxx_std = os.getenv("CXX_STD", "c++20") return ParserOptions( preprocessor=make_gcc_preprocessor( defines=["_YOSYS_", "YOSYS_ENABLE_PYTHON"], diff --git a/techlibs/achronix/synth_achronix.cc b/techlibs/achronix/synth_achronix.cc index 1b48f426b..f8993de91 100644 --- a/techlibs/achronix/synth_achronix.cc +++ b/techlibs/achronix/synth_achronix.cc @@ -129,6 +129,7 @@ struct SynthAchronixPass : public ScriptPass { if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/analogdevices/synth_analogdevices.cc b/techlibs/analogdevices/synth_analogdevices.cc index 00d2e18d6..aa27c78b6 100644 --- a/techlibs/analogdevices/synth_analogdevices.cc +++ b/techlibs/analogdevices/synth_analogdevices.cc @@ -277,8 +277,10 @@ struct SynthAnalogDevicesPass : public ScriptPass if (check_label("prepare")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(with '-flatten')"); + } if (active_design) active_design->scratchpad_unset("tribuf.added_something"); run("tribuf -logic"); @@ -447,8 +449,10 @@ struct SynthAnalogDevicesPass : public ScriptPass if (check_label("map_luts")) { run("opt_expr -mux_undef -noclkinv"); - if (flatten_before_abc) + if (flatten_before_abc) { + run("check"); run("flatten"); + } if (help_mode) run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')"); else if (abc9) { diff --git a/techlibs/anlogic/anlogic_fixcarry.cc b/techlibs/anlogic/anlogic_fixcarry.cc index e8d061b93..5d09498f2 100644 --- a/techlibs/anlogic/anlogic_fixcarry.cc +++ b/techlibs/anlogic/anlogic_fixcarry.cc @@ -69,7 +69,7 @@ static void fix_carry_chain(Module *module) continue; adders_to_fix_cells.push_back(cell); - log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell)); + log("Found %s cell named %s with invalid 'c' signal.\n", cell->type.unescape(), cell); } } @@ -78,7 +78,7 @@ static void fix_carry_chain(Module *module) SigBit bit_ci = get_bit_or_zero(cell->getPort(ID(c))); SigBit canonical_bit = sigmap(bit_ci); auto bit = mapping_bits.at(canonical_bit); - log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell)); + log("Fixing %s cell named %s breaking carry chain.\n", cell->type.unescape(), cell); Cell *c = module->addCell(NEW_ID, ID(AL_MAP_ADDER)); SigBit new_bit = module->addWire(NEW_ID); SigBit dummy_bit = module->addWire(NEW_ID); diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc index a03374fb0..5c7c0b532 100644 --- a/techlibs/anlogic/synth_anlogic.cc +++ b/techlibs/anlogic/synth_anlogic.cc @@ -156,6 +156,7 @@ struct SynthAnlogicPass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index e0fb9fbfa..3f34bfd22 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1976,7 +1976,7 @@ endmodule // -------------------------------------------------------- //* group spec -module \$specrule (EN_SRC, EN_DST, SRC, DST); +module \$specrule (SRC_EN, DST_EN, SRC, DST); parameter TYPE = ""; parameter T_LIMIT = 0; @@ -1991,7 +1991,7 @@ parameter SRC_POL = 0; parameter DST_PEN = 0; parameter DST_POL = 0; -input EN_SRC, EN_DST; +input SRC_EN, DST_EN; input [SRC_WIDTH-1:0] SRC; input [DST_WIDTH-1:0] DST; diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 0623bf43d..00d884107 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -67,6 +67,10 @@ struct SynthPass : public ScriptPass { log(" -booth\n"); log(" run the booth pass to map $mul to Booth encoded multipliers\n"); log("\n"); + log(" -arith_tree\n"); + log(" run the arith_tree pass to convert $add/$sub chains and $macc cells to\n"); + log(" carry-save adder trees.\n"); + log("\n"); log(" -noalumacc\n"); log(" do not run 'alumacc' pass. i.e. keep arithmetic operators in\n"); log(" their direct form ($add, $sub, etc.).\n"); @@ -108,7 +112,7 @@ struct SynthPass : public ScriptPass { } string top_module, fsm_opts, memory_opts, abc; - bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, hieropt, relative_share; + bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, arith_tree, hieropt, relative_share; int lut; std::vector techmap_maps; @@ -127,6 +131,7 @@ struct SynthPass : public ScriptPass { noshare = false; flowmap = false; booth = false; + arith_tree = false; hieropt = false; relative_share = false; abc = "abc"; @@ -187,7 +192,10 @@ struct SynthPass : public ScriptPass { booth = true; continue; } - + if (args[argidx] == "-arith_tree") { + arith_tree = true; + continue; + } if (args[argidx] == "-nordff") { memory_opts += " -nordff"; continue; @@ -269,8 +277,10 @@ struct SynthPass : public ScriptPass { if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", " (if -flatten)"); + } run("opt_expr"); run("opt_clean"); run("check"); @@ -289,6 +299,8 @@ struct SynthPass : public ScriptPass { run("booth", " (if -booth)"); if (!noalumacc) run("alumacc", " (unless -noalumacc)"); + if (arith_tree || help_mode) + run("arith_tree", " (if -arith_tree)"); if (!noshare) run("share", " (unless -noshare)"); run("opt" + hieropt_flag); @@ -301,7 +313,7 @@ struct SynthPass : public ScriptPass { run("memory_map"); run("opt -full"); if (help_mode) { - run(techmap_cmd, " (unless -extra-map)"); + run(techmap_cmd, " (unless -extra-map)"); run(techmap_cmd + " -map +/techmap.v -map ", " (if -extra-map)"); } else { std::string techmap_opts; diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index c3364e628..8061b2e81 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -59,7 +59,7 @@ module _90_simplemap_compare_ops; endmodule (* techmap_simplemap *) -(* techmap_celltype = "$buf $pos $slice $concat $mux $tribuf $bmux $bwmux $bweqx" *) +(* techmap_celltype = "$buf $pos $slice $concat $mux $pmux $tribuf $bmux $bwmux $bweqx" *) module _90_simplemap_various; endmodule @@ -563,48 +563,6 @@ module _90_pow (A, B, Y); wire _TECHMAP_FAIL_ = 1; endmodule - -// -------------------------------------------------------- -// Parallel Multiplexers -// -------------------------------------------------------- - -(* techmap_celltype = "$pmux" *) -module _90_pmux (A, B, S, Y); - parameter WIDTH = 1; - parameter S_WIDTH = 1; - - (* force_downto *) - input [WIDTH-1:0] A; - (* force_downto *) - input [WIDTH*S_WIDTH-1:0] B; - (* force_downto *) - input [S_WIDTH-1:0] S; - (* force_downto *) - output [WIDTH-1:0] Y; - - (* force_downto *) - wire [WIDTH-1:0] Y_B; - - genvar i, j; - generate - (* force_downto *) - wire [WIDTH*S_WIDTH-1:0] B_AND_S; - for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND - assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}}; - end:B_AND - for (i = 0; i < WIDTH; i = i + 1) begin:B_OR - (* force_downto *) - wire [S_WIDTH-1:0] B_AND_BITS; - for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT - assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i]; - end:B_AND_BITS_COLLECT - assign Y_B[i] = |B_AND_BITS; - end:B_OR - endgenerate - - assign Y = |S ? Y_B : A; -endmodule - // -------------------------------------------------------- // Demultiplexers // -------------------------------------------------------- diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc index 7ee1393be..1b30f51bc 100644 --- a/techlibs/coolrunner2/synth_coolrunner2.cc +++ b/techlibs/coolrunner2/synth_coolrunner2.cc @@ -132,6 +132,7 @@ struct SynthCoolrunner2Pass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); } diff --git a/techlibs/easic/synth_easic.cc b/techlibs/easic/synth_easic.cc index 6c5df7beb..aea517cc5 100644 --- a/techlibs/easic/synth_easic.cc +++ b/techlibs/easic/synth_easic.cc @@ -142,6 +142,7 @@ struct SynthEasicPass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); } diff --git a/techlibs/efinix/efinix_fixcarry.cc b/techlibs/efinix/efinix_fixcarry.cc index c61fa79b8..5056dec1a 100644 --- a/techlibs/efinix/efinix_fixcarry.cc +++ b/techlibs/efinix/efinix_fixcarry.cc @@ -65,7 +65,7 @@ static void fix_carry_chain(Module *module) continue; adders_to_fix_cells.push_back(cell); - log("Found %s cell named %s with invalid CI signal.\n", log_id(cell->type), log_id(cell)); + log("Found %s cell named %s with invalid CI signal.\n", cell->type.unescape(), cell); } } @@ -74,7 +74,7 @@ static void fix_carry_chain(Module *module) SigBit bit_ci = get_bit_or_zero(cell->getPort(ID::CI)); SigBit canonical_bit = sigmap(bit_ci); auto bit = mapping_bits.at(canonical_bit); - log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell)); + log("Fixing %s cell named %s breaking carry chain.\n", cell->type.unescape(), cell); Cell *c = module->addCell(NEW_ID, ID(EFX_ADD)); SigBit new_bit = module->addWire(NEW_ID); c->setParam(ID(I0_POLARITY), State::S1); diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index ef245e755..14457c64b 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -148,6 +148,7 @@ struct SynthEfinixPass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index f74dc8e26..0074a52af 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -286,6 +286,7 @@ struct SynthPass : public ScriptPass if (check_label("flatten", "(unless -noflatten)")) { if (flatten) { + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/gatemate/synth_gatemate.cc b/techlibs/gatemate/synth_gatemate.cc index 7726e7a15..f7cdcbd12 100644 --- a/techlibs/gatemate/synth_gatemate.cc +++ b/techlibs/gatemate/synth_gatemate.cc @@ -69,7 +69,8 @@ struct SynthGateMatePass : public ScriptPass log(" do not use CC_MX{8,4} multiplexer cells in output netlist.\n"); log("\n"); log(" -luttree\n"); - log(" use new LUT tree mapping approach (EXPERIMENTAL).\n"); + log(" use LUT tree mapping for output to nextpnr. Do not use this if targeting\n"); + log(" legacy p_r.\n"); log("\n"); log(" -dff\n"); log(" run 'abc' with -dff option\n"); @@ -77,6 +78,9 @@ struct SynthGateMatePass : public ScriptPass log(" -retime\n"); log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); + log(" -abc_new\n"); + log(" use 'abc_new' instead of 'abc' for mapping. (EXPERIMENTAL)\n"); + log("\n"); log(" -noiopad\n"); log(" disable I/O buffer insertion (useful for hierarchical or \n"); log(" out-of-context flows).\n"); @@ -90,7 +94,7 @@ struct SynthGateMatePass : public ScriptPass } string top_opt, vlog_file, json_file; - bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, luttree, dff, retime, noiopad, noclkbuf; + bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, luttree, dff, retime, noiopad, noclkbuf, abc_new; void clear_flags() override { @@ -108,6 +112,7 @@ struct SynthGateMatePass : public ScriptPass retime = false; noiopad = false; noclkbuf = false; + abc_new = false; } void execute(std::vector args, RTLIL::Design *design) override @@ -182,6 +187,10 @@ struct SynthGateMatePass : public ScriptPass noclkbuf = true; continue; } + if (args[argidx] == "-abc_new") { + abc_new = true; + continue; + } break; } extra_args(args, argidx, design); @@ -210,6 +219,7 @@ struct SynthGateMatePass : public ScriptPass { run("proc"); if (!noflatten) { + run("check"); run("flatten"); } run("tribuf -logic"); @@ -312,7 +322,11 @@ struct SynthGateMatePass : public ScriptPass if (dff) { abc_args += " -dff"; } - run("abc " + abc_args, "(with -luttree)"); + if (abc_new) { + run("abc_new " + abc_args, "(with -luttree and -abc_new)"); + } else { + run("abc " + abc_args, "(with -luttree, without -abc_new)"); + } run("techmap -map +/gatemate/lut_tree_map.v", "(with -luttree)"); run("gatemate_foldinv", "(with -luttree)"); run("techmap -map +/gatemate/inv_map.v", "(with -luttree)"); diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc index ac028e2a6..d5ebdafea 100644 --- a/techlibs/gowin/synth_gowin.cc +++ b/techlibs/gowin/synth_gowin.cc @@ -265,8 +265,10 @@ struct SynthGowinPass : public ScriptPass if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(unless -noflatten)"); + } run("tribuf -logic"); run("deminout"); run("opt_expr"); diff --git a/techlibs/greenpak4/greenpak4_dffinv.cc b/techlibs/greenpak4/greenpak4_dffinv.cc index 4f60a5c37..691013c8e 100644 --- a/techlibs/greenpak4/greenpak4_dffinv.cc +++ b/techlibs/greenpak4/greenpak4_dffinv.cc @@ -86,7 +86,7 @@ void invert_gp_dff(Cell *cell, bool invert_input) cell->type = stringf("\\GP_DFF%s%s%s", cell_type_s ? "S" : "", cell_type_r ? "R" : "", cell_type_i ? "I" : ""); log("Merged %s inverter into cell %s.%s: %s -> %s\n", invert_input ? "input" : "output", - log_id(cell->module), log_id(cell), cell_type.c_str()+1, log_id(cell->type)); + cell->module, cell, cell_type.c_str()+1, cell->type.unescape()); } struct Greenpak4DffInvPass : public Pass { diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc index fa52ecfc6..7f91d6332 100644 --- a/techlibs/greenpak4/synth_greenpak4.cc +++ b/techlibs/greenpak4/synth_greenpak4.cc @@ -144,6 +144,7 @@ struct SynthGreenPAK4Pass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); } diff --git a/techlibs/ice40/ice40_dsp.cc b/techlibs/ice40/ice40_dsp.cc index 995cdb97e..1d0f98f2f 100644 --- a/techlibs/ice40/ice40_dsp.cc +++ b/techlibs/ice40/ice40_dsp.cc @@ -29,17 +29,17 @@ void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; - log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); + log("Checking %s.%s for iCE40 DSP inference.\n", pm.module, st.mul); - log_debug("ffA: %s\n", log_id(st.ffA, "--")); - log_debug("ffB: %s\n", log_id(st.ffB, "--")); - log_debug("ffCD: %s\n", log_id(st.ffCD, "--")); - log_debug("mul: %s\n", log_id(st.mul, "--")); - log_debug("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); - log_debug("ffH: %s\n", log_id(st.ffH, "--")); - log_debug("add: %s\n", log_id(st.add, "--")); - log_debug("mux: %s\n", log_id(st.mux, "--")); - log_debug("ffO: %s\n", log_id(st.ffO, "--")); + log_debug("ffA: %s\n", st.ffA ? st.ffA->name.unescape() : "--"); + log_debug("ffB: %s\n", st.ffB ? st.ffB->name.unescape() : "--"); + log_debug("ffCD: %s\n", st.ffCD ? st.ffCD->name.unescape() : "--"); + log_debug("mul: %s\n", st.mul ? st.mul->name.unescape() : "--"); + log_debug("ffFJKG: %s\n", st.ffFJKG ? st.ffFJKG->name.unescape() : "--"); + log_debug("ffH: %s\n", st.ffH ? st.ffH->name.unescape() : "--"); + log_debug("add: %s\n", st.add ? st.add->name.unescape() : "--"); + log_debug("mux: %s\n", st.mux ? st.mux->name.unescape() : "--"); + log_debug("ffO: %s\n", st.ffO ? st.ffO->name.unescape() : "--"); log_debug("\n"); if (GetSize(st.sigA) > 16) { @@ -64,7 +64,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) Cell *cell = st.mul; if (cell->type == ID($mul)) { - log(" replacing %s with SB_MAC16 cell.\n", log_id(st.mul->type)); + log(" replacing %s with SB_MAC16 cell.\n", st.mul->type.unescape()); cell = pm.module->addCell(NEW_ID, ID(SB_MAC16)); pm.module->swap_names(cell, st.mul); @@ -135,22 +135,22 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), st.clock_pol ? "posedge" : "negedge"); if (st.ffA) - log(" ffA:%s", log_id(st.ffA)); + log(" ffA:%s", st.ffA); if (st.ffB) - log(" ffB:%s", log_id(st.ffB)); + log(" ffB:%s", st.ffB); if (st.ffCD) - log(" ffCD:%s", log_id(st.ffCD)); + log(" ffCD:%s", st.ffCD); if (st.ffFJKG) - log(" ffFJKG:%s", log_id(st.ffFJKG)); + log(" ffFJKG:%s", st.ffFJKG); if (st.ffH) - log(" ffH:%s", log_id(st.ffH)); + log(" ffH:%s", st.ffH); if (st.ffO) - log(" ffO:%s", log_id(st.ffO)); + log(" ffO:%s", st.ffO); log("\n"); } @@ -196,9 +196,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.add) { accum = (st.ffO && st.add->getPort(st.addAB == ID::A ? ID::B : ID::A) == st.sigO); if (accum) - log(" accumulator %s (%s)\n", log_id(st.add), log_id(st.add->type)); + log(" accumulator %s (%s)\n", st.add, st.add->type.unescape()); else - log(" adder %s (%s)\n", log_id(st.add), log_id(st.add->type)); + log(" adder %s (%s)\n", st.add, st.add->type.unescape()); cell->setPort(ID(ADDSUBTOP), st.add->type == ID($add) ? State::S0 : State::S1); cell->setPort(ID(ADDSUBBOT), st.add->type == ID($add) ? State::S0 : State::S1); } else { diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index c88fd69b6..67d3813a7 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -83,7 +83,7 @@ static void run_ice40_opts(Module *module) module->connect(cell->getPort(ID::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)); + module, cell, log_signal(replacement_output)); module->remove(cell); } continue; @@ -137,7 +137,7 @@ static void run_ice40_opts(Module *module) module->connect(cell->getPort(ID::CO)[0], replacement_output); module->design->scratchpad_set_bool("opt.did_something", true); log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n", - log_id(module), log_id(cell), log_signal(replacement_output)); + module, cell, log_signal(replacement_output)); cell->type = ID($lut); auto I3 = get_bit_or_zero(cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID::CI : ID(I3))); cell->setPort(ID::A, { I3, inbit[1], inbit[0], get_bit_or_zero(cell->getPort(ID(I0))) }); @@ -175,7 +175,7 @@ static void run_ice40_opts(Module *module) remap_lut: module->design->scratchpad_set_bool("opt.did_something", true); - log("Mapping SB_LUT4 cell %s.%s back to logic.\n", log_id(module), log_id(cell)); + log("Mapping SB_LUT4 cell %s.%s back to logic.\n", module, cell); cell->type = ID($lut); cell->setParam(ID::WIDTH, 4); diff --git a/techlibs/ice40/ice40_wrapcarry.cc b/techlibs/ice40/ice40_wrapcarry.cc index f62019617..63ebdbfcf 100644 --- a/techlibs/ice40/ice40_wrapcarry.cc +++ b/techlibs/ice40/ice40_wrapcarry.cc @@ -31,8 +31,8 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) #if 0 log("\n"); - log("carry: %s\n", log_id(st.carry, "--")); - log("lut: %s\n", log_id(st.lut, "--")); + log("carry: %s\n", st.carry ? st.carry->name.unescape() : "--"); + log("lut: %s\n", st.lut ? st.lut->name.unescape() : "--"); #endif log(" replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n"); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 0a4144451..86189c848 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -309,6 +309,7 @@ struct SynthIce40Pass : public ScriptPass if (check_label("flatten", "(unless -noflatten)")) { if (flatten) { + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index e02885cd0..0b0eb6ae9 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -198,9 +198,11 @@ struct SynthIntelPass : public ScriptPass { if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(skip if -noflatten)"); - run("tribuf -logic"); + } + run("tribuf -logic"); run("deminout"); run("opt_expr"); run("opt_clean"); diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc index 28852d7df..95dbb6e35 100644 --- a/techlibs/intel_alm/synth_intel_alm.cc +++ b/techlibs/intel_alm/synth_intel_alm.cc @@ -184,8 +184,10 @@ struct SynthIntelALMPass : public ScriptPass { if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(skip if -noflatten)"); + } run("tribuf -logic"); run("deminout"); run("opt_expr"); diff --git a/techlibs/lattice/lattice_gsr.cc b/techlibs/lattice/lattice_gsr.cc index d7d41eca5..a60b54b16 100644 --- a/techlibs/lattice/lattice_gsr.cc +++ b/techlibs/lattice/lattice_gsr.cc @@ -57,7 +57,7 @@ struct LatticeGsrPass : public Pass { for (auto module : design->selected_modules()) { - log("Handling GSR in %s.\n", log_id(module)); + log("Handling GSR in %s.\n", module); SigMap sigmap(module); @@ -69,11 +69,11 @@ struct LatticeGsrPass : public Pass { if (cell->type != ID(GSR) && cell->type != ID(SGSR)) continue; if (found_gsr) - log_error("Found more than one GSR or SGSR cell in module %s.\n", log_id(module)); + log_error("Found more than one GSR or SGSR cell in module %s.\n", module); found_gsr = true; SigSpec sig_gsr = cell->getPort(ID(GSR)); if (GetSize(sig_gsr) < 1) - log_error("GSR cell %s has disconnected GSR input.\n", log_id(cell)); + log_error("GSR cell %s has disconnected GSR input.\n", cell); gsr = sigmap(sig_gsr[0]); } @@ -97,7 +97,7 @@ struct LatticeGsrPass : public Pass { // For finding active low FF inputs pool inverted_gsr; - log_debug("GSR net in module %s is %s.\n", log_id(module), log_signal(gsr)); + log_debug("GSR net in module %s is %s.\n", module, log_signal(gsr)); for (auto cell : module->selected_cells()) { if (cell->type != ID($_NOT_)) diff --git a/techlibs/lattice/synth_lattice.cc b/techlibs/lattice/synth_lattice.cc index 744beb650..382dae3d8 100644 --- a/techlibs/lattice/synth_lattice.cc +++ b/techlibs/lattice/synth_lattice.cc @@ -402,8 +402,10 @@ struct SynthLatticePass : public ScriptPass if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten"); + } run("tribuf -logic"); run("deminout"); run("opt_expr"); diff --git a/techlibs/microchip/microchip_dffopt.cc b/techlibs/microchip/microchip_dffopt.cc index 98e2f17a7..140ef2c9f 100644 --- a/techlibs/microchip/microchip_dffopt.cc +++ b/techlibs/microchip/microchip_dffopt.cc @@ -121,7 +121,7 @@ struct MicrochipDffOptPass : public Pass { extra_args(args, argidx, design); for (auto module : design->selected_modules()) { - log("Optimizing FFs in %s.\n", log_id(module)); + log("Optimizing FFs in %s.\n", module); SigMap sigmap(module); dict> bit_to_lut; @@ -294,7 +294,7 @@ struct MicrochipDffOptPass : public Pass { ports += " + S"; if (worthy_post_ce) ports += " + CE"; - log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports, log_id(cell), log_id(sig_Q.wire), + log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports, cell, sig_Q.wire, GetSize(lut_d.second), GetSize(final_lut.second)); // Okay, we're doing it. Unmap ports. diff --git a/techlibs/microchip/microchip_dsp.cc b/techlibs/microchip/microchip_dsp.cc index df7093bc5..ff86049eb 100644 --- a/techlibs/microchip/microchip_dsp.cc +++ b/techlibs/microchip/microchip_dsp.cc @@ -31,13 +31,13 @@ void microchip_dsp_pack(microchip_dsp_pm &pm) { auto &st = pm.st_microchip_dsp_pack; - log("Analysing %s.%s for Microchip MACC_PA packing.\n", log_id(pm.module), log_id(st.dsp)); + log("Analysing %s.%s for Microchip MACC_PA packing.\n", pm.module, st.dsp); Cell *cell = st.dsp; // pack pre-adder if (st.preAdderStatic) { SigSpec &pasub = cell->connections_.at(ID(PASUB)); - log(" static PASUB preadder %s (%s)\n", log_id(st.preAdderStatic), log_id(st.preAdderStatic->type)); + log(" static PASUB preadder %s (%s)\n", st.preAdderStatic, st.preAdderStatic->type.unescape()); bool D_SIGNED = st.preAdderStatic->getParam(ID::B_SIGNED).as_bool(); bool B_SIGNED = st.preAdderStatic->getParam(ID::A_SIGNED).as_bool(); st.sigB.extend_u0(18, B_SIGNED); @@ -60,7 +60,7 @@ void microchip_dsp_pack(microchip_dsp_pm &pm) } // pack post-adder if (st.postAdderStatic) { - log(" postadder %s (%s)\n", log_id(st.postAdderStatic), log_id(st.postAdderStatic->type)); + log(" postadder %s (%s)\n", st.postAdderStatic, st.postAdderStatic->type.unescape()); SigSpec &sub = cell->connections_.at(ID(SUB)); // Post-adder in MACC_PA also supports subtraction // Determines the sign of the output from the multiplier. @@ -171,13 +171,13 @@ void microchip_dsp_pack(microchip_dsp_pm &pm) log(" clock: %s (%s)\n", log_signal(st.clock), "posedge"); if (st.ffA) - log(" \t ffA:%s\n", log_id(st.ffA)); + log(" \t ffA:%s\n", st.ffA); if (st.ffB) - log(" \t ffB:%s\n", log_id(st.ffB)); + log(" \t ffB:%s\n", st.ffB); if (st.ffD) - log(" \t ffD:%s\n", log_id(st.ffD)); + log(" \t ffD:%s\n", st.ffD); if (st.ffP) - log(" \t ffP:%s\n", log_id(st.ffP)); + log(" \t ffP:%s\n", st.ffP); } log("\n"); @@ -194,8 +194,8 @@ void microchip_dsp_packC(microchip_dsp_CREG_pm &pm) { auto &st = pm.st_microchip_dsp_packC; - log_debug("Analysing %s.%s for Microchip DSP packing (REG_C).\n", log_id(pm.module), log_id(st.dsp)); - log_debug("ffC: %s\n", log_id(st.ffC, "--")); + log_debug("Analysing %s.%s for Microchip DSP packing (REG_C).\n", pm.module, st.dsp); + log_debug("ffC: %s\n", st.ffC ? st.ffC->name.unescape() : "--"); Cell *cell = st.dsp; @@ -264,7 +264,7 @@ void microchip_dsp_packC(microchip_dsp_CREG_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); if (st.ffC) - log(" ffC:%s", log_id(st.ffC)); + log(" ffC:%s", st.ffC); log("\n"); } diff --git a/techlibs/microchip/microchip_dsp_cascade.pmg b/techlibs/microchip/microchip_dsp_cascade.pmg index fa276d5b5..ad359138d 100644 --- a/techlibs/microchip/microchip_dsp_cascade.pmg +++ b/techlibs/microchip/microchip_dsp_cascade.pmg @@ -135,10 +135,10 @@ finally } - log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + log_debug("PCOUT -> PCIN cascade for %s -> %s\n", dsp, dsp_pcin); } else { - log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", log_id(dsp), log_id(dsp_pcin), MAX_DSP_CASCADE); + log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", dsp, dsp_pcin, MAX_DSP_CASCADE); } dsp = dsp_pcin; diff --git a/techlibs/microchip/synth_microchip.cc b/techlibs/microchip/synth_microchip.cc index e1d3c393a..218ed310f 100644 --- a/techlibs/microchip/synth_microchip.cc +++ b/techlibs/microchip/synth_microchip.cc @@ -267,8 +267,10 @@ struct SynthMicrochipPass : public ScriptPass { if (check_label("prepare")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(with '-flatten')"); + } if (active_design) active_design->scratchpad_unset("tribuf.added_something"); run("tribuf -logic"); diff --git a/techlibs/nanoxplore/synth_nanoxplore.cc b/techlibs/nanoxplore/synth_nanoxplore.cc index 3445ea1be..0b87c98c7 100644 --- a/techlibs/nanoxplore/synth_nanoxplore.cc +++ b/techlibs/nanoxplore/synth_nanoxplore.cc @@ -250,8 +250,10 @@ struct SynthNanoXplorePass : public ScriptPass if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(skip if -noflatten)"); + } run("tribuf -logic"); run("deminout"); run("opt_expr"); diff --git a/techlibs/quicklogic/ql_bram_merge.cc b/techlibs/quicklogic/ql_bram_merge.cc index 7b99d74e5..eeb06060e 100644 --- a/techlibs/quicklogic/ql_bram_merge.cc +++ b/techlibs/quicklogic/ql_bram_merge.cc @@ -128,7 +128,7 @@ struct QlBramMergeWorker { // Create the new cell RTLIL::Cell* merged = module->addCell(NEW_ID, merged_cell_type); - log_debug("Merging split BRAM cells %s and %s -> %s\n", log_id(bram1->name), log_id(bram2->name), log_id(merged->name)); + log_debug("Merging split BRAM cells %s and %s -> %s\n", bram1->name.unescape(), bram2->name.unescape(), merged->name.unescape()); for (auto &it : param_map(false)) { @@ -146,14 +146,14 @@ struct QlBramMergeWorker { if (bram1->hasPort(it.first)) merged->setPort(it.second, bram1->getPort(it.first)); else - log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram1->name)); + log_error("Can't find port %s on cell %s!\n", it.first.unescape(), bram1->name.unescape()); } for (auto &it : port_map(true)) { if (bram2->hasPort(it.first)) merged->setPort(it.second, bram2->getPort(it.first)); else - log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram2->name)); + log_error("Can't find port %s on cell %s!\n", it.first.unescape(), bram2->name.unescape()); } merged->attributes = bram1->attributes; for (auto attr: bram2->attributes) diff --git a/techlibs/quicklogic/ql_bram_types.cc b/techlibs/quicklogic/ql_bram_types.cc index cf42703aa..2599303bd 100644 --- a/techlibs/quicklogic/ql_bram_types.cc +++ b/techlibs/quicklogic/ql_bram_types.cc @@ -155,7 +155,7 @@ struct QlBramTypesPass : public Pass { } cell->type = RTLIL::escape_id(type); - log_debug("Changed type of memory cell %s to %s\n", log_id(cell->name), log_id(cell->type)); + log_debug("Changed type of memory cell %s to %s\n", cell->name.unescape(), cell->type.unescape()); } } diff --git a/techlibs/quicklogic/ql_dsp_io_regs.cc b/techlibs/quicklogic/ql_dsp_io_regs.cc index ecf163dbf..d7255d761 100644 --- a/techlibs/quicklogic/ql_dsp_io_regs.cc +++ b/techlibs/quicklogic/ql_dsp_io_regs.cc @@ -83,19 +83,19 @@ struct QlDspIORegs : public Pass { for (auto cfg_port : {ID(register_inputs), ID(output_select)}) if (!cell->hasPort(cfg_port) || !sigmap(cell->getPort(cfg_port)).is_fully_const()) log_error("Missing or non-constant '%s' port on DSP cell %s\n", - log_id(cfg_port), log_id(cell)); + cfg_port, cell); int reg_in_i = sigmap(cell->getPort(ID(register_inputs))).as_int(); int out_sel_i = sigmap(cell->getPort(ID(output_select))).as_int(); // Get the feedback port if (!cell->hasPort(ID(feedback))) - log_error("Missing 'feedback' port on %s", log_id(cell)); + log_error("Missing 'feedback' port on %s", cell); SigSpec feedback = sigmap(cell->getPort(ID(feedback))); // Check the top two bits on 'feedback' to be constant zero. // That's what we are expecting from inference. if (feedback.extract(1, 2) != SigSpec(0, 2)) - log_error("Unexpected feedback configuration on %s\n", log_id(cell)); + log_error("Unexpected feedback configuration on %s\n", cell); // Build new type name std::string new_type = "\\QL_DSP2_MULT"; diff --git a/techlibs/quicklogic/ql_dsp_macc.cc b/techlibs/quicklogic/ql_dsp_macc.cc index f0669da6c..083dc3ff1 100644 --- a/techlibs/quicklogic/ql_dsp_macc.cc +++ b/techlibs/quicklogic/ql_dsp_macc.cc @@ -73,11 +73,11 @@ static void create_ql_macc_dsp(ql_dsp_macc_pm &pm) } type = RTLIL::escape_id(cell_base_name + cell_size_name + "_cfg_ports"); - log("Inferring MACC %zux%zu->%zu as %s from:\n", a_width, b_width, z_width, log_id(type)); + log("Inferring MACC %zux%zu->%zu as %s from:\n", a_width, b_width, z_width, type.unescape()); for (auto cell : {st.mul, st.add, st.mux, st.ff}) if (cell) - log(" %s (%s)\n", log_id(cell), log_id(cell->type)); + log(" %s (%s)\n", cell, cell->type.unescape()); // Add the DSP cell RTLIL::Cell *cell = pm.module->addCell(NEW_ID, type); diff --git a/techlibs/quicklogic/ql_dsp_simd.cc b/techlibs/quicklogic/ql_dsp_simd.cc index cd509ce7f..da252673f 100644 --- a/techlibs/quicklogic/ql_dsp_simd.cc +++ b/techlibs/quicklogic/ql_dsp_simd.cc @@ -150,13 +150,13 @@ struct QlDspSimdPass : public Pass { // Create the new cell Cell *simd = module->addCell(NEW_ID, m_SimdDspType); - log(" SIMD: %s (%s) + %s (%s) => %s (%s)\n", log_id(dsp_a), log_id(dsp_a->type), - log_id(dsp_b), log_id(dsp_b->type), log_id(simd), log_id(simd->type)); + log(" SIMD: %s (%s) + %s (%s) => %s (%s)\n", dsp_a, dsp_a->type.unescape(), + dsp_b, dsp_b->type.unescape(), simd, simd->type.unescape()); // Check if the target cell is known (important to know // its port widths) if (!simd->known()) - log_error(" The target cell type '%s' is not known!", log_id(simd)); + log_error(" The target cell type '%s' is not known!", simd); // Connect common ports for (const auto &it : m_DspCfgPorts) diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc index 1026dc233..e65be1c58 100644 --- a/techlibs/quicklogic/synth_quicklogic.cc +++ b/techlibs/quicklogic/synth_quicklogic.cc @@ -212,8 +212,10 @@ struct SynthQuickLogicPass : public ScriptPass { if (check_label("prepare")) { run("proc"); - if (flatten) + if (flatten) { + run("check"); run("flatten", "(unless -noflatten)"); + } if (help_mode || family == "pp3") { run("tribuf -logic", " (for pp3)"); } diff --git a/techlibs/sf2/NOTES.txt b/techlibs/sf2/NOTES.txt index 67784b546..6204d8fee 100644 --- a/techlibs/sf2/NOTES.txt +++ b/techlibs/sf2/NOTES.txt @@ -12,7 +12,7 @@ You'd better to write a simple script, like this one (assuming the top module is top): ----------- run_yosys.sh -------------- -#!/bin/sh +#!/usr/bin/env sh set -e diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index ad335536b..7a7f87466 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -172,6 +172,7 @@ struct SynthSf2Pass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/xilinx/brams_xc6v_map.v b/techlibs/xilinx/brams_xc6v_map.v index b2698a3aa..dfd6dfc9e 100644 --- a/techlibs/xilinx/brams_xc6v_map.v +++ b/techlibs/xilinx/brams_xc6v_map.v @@ -275,7 +275,7 @@ end else if (OPTION_MODE == "FULL") begin .DIADI(DI[31:0]), .DIBDI(PORT_W_WIDTH == 72 ? DI[63:32] : DI[31:0]), .DIPADIP(DIP[3:0]), - .DIPBDIP(PORT_W_WIDTH == 71 ? DIP[7:4] : DIP[3:0]), + .DIPBDIP(PORT_W_WIDTH == 72 ? DIP[7:4] : DIP[3:0]), ); end diff --git a/techlibs/xilinx/brams_xcu_map.v b/techlibs/xilinx/brams_xcu_map.v index d48c21a59..01ee8a953 100644 --- a/techlibs/xilinx/brams_xcu_map.v +++ b/techlibs/xilinx/brams_xcu_map.v @@ -215,7 +215,7 @@ end else if (OPTION_MODE == "FULL") begin .DINADIN(DI[31:0]), .DINBDIN(PORT_W_WIDTH == 72 ? DI[63:32] : DI[31:0]), .DINPADINP(DIP[3:0]), - .DINPBDINP(PORT_W_WIDTH == 71 ? DIP[7:4] : DIP[3:0]), + .DINPBDINP(PORT_W_WIDTH == 72 ? DIP[7:4] : DIP[3:0]), ); end diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c487206db..b08fbe499 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -355,8 +355,10 @@ struct SynthXilinxPass : public ScriptPass if (check_label("prepare")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(with '-flatten')"); + } if (active_design) active_design->scratchpad_unset("tribuf.added_something"); run("tribuf -logic"); @@ -637,8 +639,10 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { run("opt_expr -mux_undef -noclkinv"); - if (flatten_before_abc) + if (flatten_before_abc) { + run("check"); run("flatten"); + } if (help_mode) run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')"); else if (abc9) { diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc index 8a6d3e015..96420be6a 100644 --- a/techlibs/xilinx/xilinx_dffopt.cc +++ b/techlibs/xilinx/xilinx_dffopt.cc @@ -131,7 +131,7 @@ struct XilinxDffOptPass : public Pass { for (auto module : design->selected_modules()) { - log("Optimizing FFs in %s.\n", log_id(module)); + log("Optimizing FFs in %s.\n", module); SigMap sigmap(module); dict> bit_to_lut; @@ -305,7 +305,7 @@ unmap: if (worthy_post_r) ports += " + R"; if (worthy_post_s) ports += " + S"; if (worthy_post_ce) ports += " + CE"; - log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports, log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second)); + log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports, cell, sig_Q.wire, GetSize(lut_d.second), GetSize(final_lut.second)); // Okay, we're doing it. Unmap ports. if (worthy_post_r) { diff --git a/techlibs/xilinx/xilinx_dsp.cc b/techlibs/xilinx/xilinx_dsp.cc index 194b9ac10..5c81bff22 100644 --- a/techlibs/xilinx/xilinx_dsp.cc +++ b/techlibs/xilinx/xilinx_dsp.cc @@ -140,7 +140,7 @@ void xilinx_simd_pack(Module *module, const std::vector &selected_cells) } } - log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1)); + log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", module, lane1); Cell *cell = addDsp(module); cell->setParam(ID(USE_SIMD), Const("FOUR12")); @@ -221,7 +221,7 @@ void xilinx_simd_pack(Module *module, const std::vector &selected_cells) Cell *lane2 = simd24.front(); simd24.pop_front(); - log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1)); + log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", module, lane1); Cell *cell = addDsp(module); cell->setParam(ID(USE_SIMD), Const("TWO24")); @@ -260,29 +260,29 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) { auto &st = pm.st_xilinx_dsp_pack; - log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); + log("Analysing %s.%s for Xilinx DSP packing.\n", pm.module, st.dsp); - log_debug("preAdd: %s\n", log_id(st.preAdd, "--")); - log_debug("preSub: %s\n", log_id(st.preSub, "--")); - log_debug("ffAD: %s\n", log_id(st.ffAD, "--")); - log_debug("ffA2: %s\n", log_id(st.ffA2, "--")); - log_debug("ffA1: %s\n", log_id(st.ffA1, "--")); - log_debug("ffB2: %s\n", log_id(st.ffB2, "--")); - log_debug("ffB1: %s\n", log_id(st.ffB1, "--")); - log_debug("ffD: %s\n", log_id(st.ffD, "--")); - log_debug("dsp: %s\n", log_id(st.dsp, "--")); - log_debug("ffM: %s\n", log_id(st.ffM, "--")); - log_debug("postAdd: %s\n", log_id(st.postAdd, "--")); - log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--")); - log_debug("ffP: %s\n", log_id(st.ffP, "--")); - log_debug("overflow: %s\n", log_id(st.overflow, "--")); + log_debug("preAdd: %s\n", st.preAdd ? st.preAdd->name.unescape() : "--"); + log_debug("preSub: %s\n", st.preSub ? st.preSub->name.unescape() : "--"); + log_debug("ffAD: %s\n", st.ffAD ? st.ffAD->name.unescape() : "--"); + log_debug("ffA2: %s\n", st.ffA2 ? st.ffA2->name.unescape() : "--"); + log_debug("ffA1: %s\n", st.ffA1 ? st.ffA1->name.unescape() : "--"); + log_debug("ffB2: %s\n", st.ffB2 ? st.ffB2->name.unescape() : "--"); + log_debug("ffB1: %s\n", st.ffB1 ? st.ffB1->name.unescape() : "--"); + log_debug("ffD: %s\n", st.ffD ? st.ffD->name.unescape() : "--"); + log_debug("dsp: %s\n", st.dsp ? st.dsp->name.unescape() : "--"); + log_debug("ffM: %s\n", st.ffM ? st.ffM->name.unescape() : "--"); + log_debug("postAdd: %s\n", st.postAdd ? st.postAdd->name.unescape() : "--"); + log_debug("postAddMux: %s\n", st.postAddMux ? st.postAddMux->name.unescape() : "--"); + log_debug("ffP: %s\n", st.ffP ? st.ffP->name.unescape() : "--"); + log_debug("overflow: %s\n", st.overflow ? st.overflow->name.unescape() : "--"); Cell *cell = st.dsp; if (st.preAdd || st.preSub) { Cell* preAdder = st.preAdd ? st.preAdd : st.preSub; - log(" preadder %s (%s)\n", log_id(preAdder), log_id(preAdder->type)); + log(" preadder %s (%s)\n", preAdder, preAdder->type.unescape()); bool A_SIGNED = preAdder->getParam(ID::A_SIGNED).as_bool(); bool D_SIGNED = preAdder->getParam(ID::B_SIGNED).as_bool(); if (st.sigA == preAdder->getPort(ID::B)) @@ -312,7 +312,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) pm.autoremove(preAdder); } if (st.postAdd) { - log(" postadder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); + log(" postadder %s (%s)\n", st.postAdd, st.postAdd->type.unescape()); SigSpec &opmode = cell->connections_.at(ID(OPMODE)); if (st.postAddMux) { @@ -338,7 +338,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) pm.autoremove(st.postAdd); } if (st.overflow) { - log(" overflow %s (%s)\n", log_id(st.overflow), log_id(st.overflow->type)); + log(" overflow %s (%s)\n", st.overflow, st.overflow->type.unescape()); cell->setParam(ID(USE_PATTERN_DETECT), Const("PATDET")); cell->setParam(ID(SEL_PATTERN), Const("PATTERN")); cell->setParam(ID(SEL_MASK), Const("MASK")); @@ -456,28 +456,28 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); if (st.ffA2) { - log(" ffA2:%s", log_id(st.ffA2)); + log(" ffA2:%s", st.ffA2); if (st.ffA1) - log(" ffA1:%s", log_id(st.ffA1)); + log(" ffA1:%s", st.ffA1); } if (st.ffAD) - log(" ffAD:%s", log_id(st.ffAD)); + log(" ffAD:%s", st.ffAD); if (st.ffB2) { - log(" ffB2:%s", log_id(st.ffB2)); + log(" ffB2:%s", st.ffB2); if (st.ffB1) - log(" ffB1:%s", log_id(st.ffB1)); + log(" ffB1:%s", st.ffB1); } if (st.ffD) - log(" ffD:%s", log_id(st.ffD)); + log(" ffD:%s", st.ffD); if (st.ffM) - log(" ffM:%s", log_id(st.ffM)); + log(" ffM:%s", st.ffM); if (st.ffP) - log(" ffP:%s", log_id(st.ffP)); + log(" ffP:%s", st.ffP); } log("\n"); @@ -493,25 +493,25 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) { auto &st = pm.st_xilinx_dsp48a_pack; - log("Analysing %s.%s for Xilinx DSP48A/DSP48A1 packing.\n", log_id(pm.module), log_id(st.dsp)); + log("Analysing %s.%s for Xilinx DSP48A/DSP48A1 packing.\n", pm.module, st.dsp); - log_debug("preAdd: %s\n", log_id(st.preAdd, "--")); - log_debug("ffA1: %s\n", log_id(st.ffA1, "--")); - log_debug("ffA0: %s\n", log_id(st.ffA0, "--")); - log_debug("ffB1: %s\n", log_id(st.ffB1, "--")); - log_debug("ffB0: %s\n", log_id(st.ffB0, "--")); - log_debug("ffD: %s\n", log_id(st.ffD, "--")); - log_debug("dsp: %s\n", log_id(st.dsp, "--")); - log_debug("ffM: %s\n", log_id(st.ffM, "--")); - log_debug("postAdd: %s\n", log_id(st.postAdd, "--")); - log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--")); - log_debug("ffP: %s\n", log_id(st.ffP, "--")); + log_debug("preAdd: %s\n", st.preAdd ? st.preAdd->name.unescape() : "--"); + log_debug("ffA1: %s\n", st.ffA1 ? st.ffA1->name.unescape() : "--"); + log_debug("ffA0: %s\n", st.ffA0 ? st.ffA0->name.unescape() : "--"); + log_debug("ffB1: %s\n", st.ffB1 ? st.ffB1->name.unescape() : "--"); + log_debug("ffB0: %s\n", st.ffB0 ? st.ffB0->name.unescape() : "--"); + log_debug("ffD: %s\n", st.ffD ? st.ffD->name.unescape() : "--"); + log_debug("dsp: %s\n", st.dsp ? st.dsp->name.unescape() : "--"); + log_debug("ffM: %s\n", st.ffM ? st.ffM->name.unescape() : "--"); + log_debug("postAdd: %s\n", st.postAdd ? st.postAdd->name.unescape() : "--"); + log_debug("postAddMux: %s\n", st.postAddMux ? st.postAddMux->name.unescape() : "--"); + log_debug("ffP: %s\n", st.ffP ? st.ffP->name.unescape() : "--"); Cell *cell = st.dsp; SigSpec &opmode = cell->connections_.at(ID(OPMODE)); if (st.preAdd) { - log(" preadder %s (%s)\n", log_id(st.preAdd), log_id(st.preAdd->type)); + log(" preadder %s (%s)\n", st.preAdd, st.preAdd->type.unescape()); bool D_SIGNED = st.preAdd->getParam(ID::A_SIGNED).as_bool(); bool B_SIGNED = st.preAdd->getParam(ID::B_SIGNED).as_bool(); st.sigB.extend_u0(18, B_SIGNED); @@ -529,7 +529,7 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) pm.autoremove(st.preAdd); } if (st.postAdd) { - log(" postadder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); + log(" postadder %s (%s)\n", st.postAdd, st.postAdd->type.unescape()); if (st.postAddMux) { log_assert(st.ffP); @@ -639,23 +639,23 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); if (st.ffA0) - log(" ffA0:%s", log_id(st.ffA0)); + log(" ffA0:%s", st.ffA0); if (st.ffA1) - log(" ffA1:%s", log_id(st.ffA1)); + log(" ffA1:%s", st.ffA1); if (st.ffB0) - log(" ffB0:%s", log_id(st.ffB0)); + log(" ffB0:%s", st.ffB0); if (st.ffB1) - log(" ffB1:%s", log_id(st.ffB1)); + log(" ffB1:%s", st.ffB1); if (st.ffD) - log(" ffD:%s", log_id(st.ffD)); + log(" ffD:%s", st.ffD); if (st.ffM) - log(" ffM:%s", log_id(st.ffM)); + log(" ffM:%s", st.ffM); if (st.ffP) - log(" ffP:%s", log_id(st.ffP)); + log(" ffP:%s", st.ffP); } log("\n"); @@ -671,8 +671,8 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) { auto &st = pm.st_xilinx_dsp_packC; - log_debug("Analysing %s.%s for Xilinx DSP packing (CREG).\n", log_id(pm.module), log_id(st.dsp)); - log_debug("ffC: %s\n", log_id(st.ffC, "--")); + log_debug("Analysing %s.%s for Xilinx DSP packing (CREG).\n", pm.module, st.dsp); + log_debug("ffC: %s\n", st.ffC ? st.ffC->name.unescape() : "--"); Cell *cell = st.dsp; @@ -724,7 +724,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); if (st.ffC) - log(" ffC:%s", log_id(st.ffC)); + log(" ffC:%s", st.ffC); log("\n"); } diff --git a/techlibs/xilinx/xilinx_dsp_cascade.pmg b/techlibs/xilinx/xilinx_dsp_cascade.pmg index 9eebd33c3..587de4713 100644 --- a/techlibs/xilinx/xilinx_dsp_cascade.pmg +++ b/techlibs/xilinx/xilinx_dsp_cascade.pmg @@ -114,7 +114,7 @@ finally } dsp_pcin->setPort(\OPMODE, opmode); - log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + log_debug("PCOUT -> PCIN cascade for %s -> %s\n", dsp, dsp_pcin); } if (AREG >= 0) { Wire *cascade = module->addWire(NEW_ID, 30); @@ -128,7 +128,7 @@ finally dsp->setParam(\ACASCREG, AREG); dsp_pcin->setParam(\A_INPUT, Const("CASCADE")); - log_debug("ACOUT -> ACIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + log_debug("ACOUT -> ACIN cascade for %s -> %s\n", dsp, dsp_pcin); } if (BREG >= 0) { Wire *cascade = module->addWire(NEW_ID, 18); @@ -161,11 +161,11 @@ finally dsp_pcin->setParam(\B_INPUT, Const("CASCADE")); } - log_debug("BCOUT -> BCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + log_debug("BCOUT -> BCIN cascade for %s -> %s\n", dsp, dsp_pcin); } } else { - log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", log_id(dsp), log_id(dsp_pcin), MAX_DSP_CASCADE); + log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", dsp, dsp_pcin, MAX_DSP_CASCADE); } dsp = dsp_pcin; diff --git a/techlibs/xilinx/xilinx_srl.cc b/techlibs/xilinx/xilinx_srl.cc index 2c23f8f42..e23062eb7 100644 --- a/techlibs/xilinx/xilinx_srl.cc +++ b/techlibs/xilinx/xilinx_srl.cc @@ -30,11 +30,11 @@ void run_fixed(xilinx_srl_pm &pm) { auto &st = pm.st_fixed; auto &ud = pm.ud_fixed; - log("Found fixed chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); + log("Found fixed chain of length %d (%s):\n", GetSize(ud.longest_chain), st.first->type.unescape()); SigSpec initval; for (auto cell : ud.longest_chain) { - log_debug(" %s\n", log_id(cell)); + log_debug(" %s\n", cell); if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) { SigBit Q = cell->getPort(ID::Q); log_assert(Q.wire); @@ -100,7 +100,7 @@ void run_fixed(xilinx_srl_pm &pm) else log_abort(); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } void run_variable(xilinx_srl_pm &pm) @@ -108,13 +108,13 @@ void run_variable(xilinx_srl_pm &pm) auto &st = pm.st_variable; auto &ud = pm.ud_variable; - log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), log_id(st.first->type)); + log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), st.first->type.unescape()); SigSpec initval; for (const auto &i : ud.chain) { auto cell = i.first; auto slice = i.second; - log_debug(" %s\n", log_id(cell)); + log_debug(" %s\n", cell); if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { SigBit Q = cell->getPort(ID::Q)[slice]; log_assert(Q.wire); @@ -181,7 +181,7 @@ void run_variable(xilinx_srl_pm &pm) else log_abort(); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } struct XilinxSrlPass : public Pass { diff --git a/tests/.gitignore b/tests/.gitignore index d8e01e026..8fa73e3d6 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -2,3 +2,5 @@ *.out *.err run-test.mk +**/Makefile +*.result diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 000000000..794e99c46 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,127 @@ +ifneq ($(wildcard ../Makefile.conf),) +include ../Makefile.conf +endif + +OVERRIDE_MAIN=1 +include ./common.mk + +# Directories with tests not run: +# errors +# lut +# pyosys +# smv +# sva +# tools +# unit +# vloghtb + +# Tests that generate Makefile with gen_tests_makefile.py +MK_TEST_DIRS = +MK_TEST_DIRS += ./arch/analogdevices +MK_TEST_DIRS += ./arch/anlogic +MK_TEST_DIRS += ./arch/ecp5 +MK_TEST_DIRS += ./arch/efinix +MK_TEST_DIRS += ./arch/fabulous +MK_TEST_DIRS += ./arch/gatemate +MK_TEST_DIRS += ./arch/gowin +MK_TEST_DIRS += ./arch/ice40 +MK_TEST_DIRS += ./arch/intel_alm +MK_TEST_DIRS += ./arch/machxo2 +MK_TEST_DIRS += ./arch/microchip +MK_TEST_DIRS += ./arch/nanoxplore +MK_TEST_DIRS += ./arch/nexus +MK_TEST_DIRS += ./arch/quicklogic/pp3 +MK_TEST_DIRS += ./arch/quicklogic/qlf_k6n10f +MK_TEST_DIRS += ./arch/xilinx +MK_TEST_DIRS += ./bind +MK_TEST_DIRS += ./bugpoint +MK_TEST_DIRS += ./opt +MK_TEST_DIRS += ./sat +MK_TEST_DIRS += ./sdc +MK_TEST_DIRS += ./sim +MK_TEST_DIRS += ./svtypes +MK_TEST_DIRS += ./techmap +MK_TEST_DIRS += ./various +MK_TEST_DIRS += ./rtlil +ifeq ($(ENABLE_VERIFIC),1) +ifneq ($(YOSYS_NOVERIFIC),1) +MK_TEST_DIRS += ./verific +endif +endif +MK_TEST_DIRS += ./verilog +MK_TEST_DIRS += ./arith_tree +MK_TEST_DIRS += ./simple +MK_TEST_DIRS += ./simple_abc9 +MK_TEST_DIRS += ./hana +MK_TEST_DIRS += ./asicworld +MK_TEST_DIRS += ./realmath +MK_TEST_DIRS += ./share +MK_TEST_DIRS += ./opt_share +MK_TEST_DIRS += ./fsm +MK_TEST_DIRS += ./memlib +MK_TEST_DIRS += ./bram +MK_TEST_DIRS += ./svinterfaces +MK_TEST_DIRS += ./xprop +MK_TEST_DIRS += ./select +MK_TEST_DIRS += ./peepopt +MK_TEST_DIRS += ./proc +MK_TEST_DIRS += ./blif +MK_TEST_DIRS += ./arch +MK_TEST_DIRS += ./rpc +MK_TEST_DIRS += ./memfile +MK_TEST_DIRS += ./fmt +MK_TEST_DIRS += ./cxxrtl +MK_TEST_DIRS += ./liberty +#ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) +#MK_TEST_DIRS += ./functional +#endif +MK_TEST_DIRS += ./memories +MK_TEST_DIRS += ./aiger +MK_TEST_DIRS += ./alumacc + +all: vanilla-test + +# makefile-./ is a dummy string, not a directory +.PHONY: makefile-tests +.SILENT: $(MK_TEST_DIRS:%=%/Makefile) +makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) +prep: $(MK_TEST_DIRS:%=%/Makefile) + @echo "All Makefiles generated." + +.PHONY: force-create +# this target actually emits Makefile files +%/Makefile: force-create + +@cd $* && python3 generate_mk.py + +makefile-./%: %/Makefile + @$(MAKE) -C $* + @echo "...passed tests in $*" + +.PHONY: functional +functional: +ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) + @cd functional && ./run-test.sh +endif + +vanilla-test: prep makefile-tests functional + @echo "" + @echo " Passed \"make vanilla-test\"." +ifeq ($(ENABLE_VERIFIC),1) +ifeq ($(YOSYS_NOVERIFIC),1) + @echo " Ran tests without verific support due to YOSYS_NOVERIFIC=1." +endif +endif + @echo "" + @$(MAKE) --no-print-directory summary + +clean: + @rm -rf ./asicworld/*.out ./asicworld/*.log + @rm -rf ./hana/*.out ./hana/*.log + @rm -rf ./simple/*.out ./simple/*.log + @rm -rf ./memories/*.out ./memories/*.log ./memories/*.dmp + @rm -rf ./sat/*.log ./techmap/*.log ./various/*.log + @rm -rf ./bram/temp ./fsm/temp ./realmath/temp ./share/temp ./smv/temp ./various/temp + @rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff + @rm -f ./tools/cmp_tbdata + @rm -f $(addsuffix /Makefile,$(MK_TEST_DIRS)) + @find . -name '*.result' -type f -exec rm -f {} + diff --git a/tests/aiger/generate_mk.py b/tests/aiger/generate_mk.py new file mode 100644 index 000000000..a90a63527 --- /dev/null +++ b/tests/aiger/generate_mk.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +import glob +import os + +def base(fn): + return os.path.splitext(fn)[0] + +def cmd(lines): + return " \\\n".join(lines) + +# NB: *.aag and *.aig must contain a symbol table naming the primary +# inputs and outputs, otherwise ABC and Yosys will name them +# arbitrarily (and inconsistently with each other). + +# Since ABC cannot read *.aag, read the *.aig instead +# (which would have been created by the reference aig2aig utility, +# available from http://fmv.jku.at/aiger/) +def create_tests(): + aags = sorted(glob.glob("*.aag")) + yss = sorted(glob.glob("*.ys")) + for aag in aags: + b = base(aag) + + gen_tests_makefile.generate_target(aag, cmd([ + f"$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\";", + "$(YOSYS) -qp \"", + f"read_verilog {b}_ref.v;", + "prep;", + "design -stash gold;", + f"read_aiger -clk_name clock {aag};", + "prep;", + "design -stash gate;", + "design -import gold -as gold;", + "design -import gate -as gate;", + "miter -equiv -flatten -make_assert -make_outputs gold gate miter;", + "sat -verify -prove-asserts -show-ports -seq 16 miter;", + f"\" -l {aag}.log" + ])) + + # ---- Yosys script tests ---- + for ys in yss: + gen_tests_makefile.generate_ys_test(ys) + + gen_tests_makefile.generate_target("aigmap", cmd([ + "rm -rf gate; mkdir gate;", + "$(YOSYS) --no-version -p \"test_cell -aigmap -w gate/ -n 1 -s 1 all\";", + "set -o pipefail; diff --brief gold gate | tee aigmap.err;", + "rm -f aigmap.err" + ])) + +extra = [ f"ABC ?= {gen_tests_makefile.yosys_basedir}/yosys-abc", "SHELL := /usr/bin/env bash" ] + +gen_tests_makefile.generate_custom(create_tests, extra) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh deleted file mode 100755 index 94d83ede4..000000000 --- a/tests/aiger/run-test.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -OPTIND=1 -abcprog="../../yosys-abc" # default to built-in version of abc -while getopts "A:" opt -do - case "$opt" in - A) abcprog="$OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -# NB: *.aag and *.aig must contain a symbol table naming the primary -# inputs and outputs, otherwise ABC and Yosys will name them -# arbitrarily (and inconsistently with each other). - -for aag in *.aag; do - # Since ABC cannot read *.aag, read the *.aig instead - # (which would have been created by the reference aig2aig utility, - # available from http://fmv.jku.at/aiger/) - echo "Checking $aag." - $abcprog -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" - ../../yosys -qp " -read_verilog ${aag%.*}_ref.v -prep -design -stash gold -read_aiger -clk_name clock $aag -prep -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aag}.log -done - -for aig in *.aig; do - echo "Checking $aig." - $abcprog -q "read -c $aig; write ${aig%.*}_ref.v" - ../../yosys -qp " -read_verilog ${aig%.*}_ref.v -prep -design -stash gold -read_aiger -clk_name clock $aig -prep -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aig}.log -done - -for y in *.ys; do - echo "Running $y." - ../../yosys -ql ${y%.*}.log $y -done - -# compare aigmap with reference -# make gold with: rm gold/*; yosys --no-version -p "test_cell -aigmap -w gold/ -n 1 -s 1 all" -rm -rf gate; mkdir gate -../../yosys --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" -( - set -o pipefail - diff --brief gold gate | tee aigmap.err -) -rm aigmap.err diff --git a/tests/alumacc/generate_mk.py b/tests/alumacc/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/alumacc/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/alumacc/run-test.sh b/tests/alumacc/run-test.sh deleted file mode 100644 index 2e3f5235c..000000000 --- a/tests/alumacc/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done diff --git a/tests/arch/analogdevices/generate_mk.py b/tests/arch/analogdevices/generate_mk.py new file mode 100644 index 000000000..b453168c0 --- /dev/null +++ b/tests/arch/analogdevices/generate_mk.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile +import mem_gen + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/analogdevices/logic.ys b/tests/arch/analogdevices/logic.ys index 2289685ac..9314c7825 100644 --- a/tests/arch/analogdevices/logic.ys +++ b/tests/arch/analogdevices/logic.ys @@ -6,5 +6,6 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd top # Constrain all select calls below inside the top module select -assert-count 1 t:LUT1 -select -assert-count 9 t:LUT2 -select -assert-none t:LUT1 t:LUT2 %% t:* %D +select -assert-count 6 t:LUT2 +select -assert-count 2 t:LUT4 +select -assert-none t:LUT1 t:LUT2 t:LUT4 %% t:* %D diff --git a/tests/arch/analogdevices/mux.ys b/tests/arch/analogdevices/mux.ys index 3244b0dc3..375ce90f2 100644 --- a/tests/arch/analogdevices/mux.ys +++ b/tests/arch/analogdevices/mux.ys @@ -41,8 +41,10 @@ equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module select -assert-max 2 t:LUT3 -select -assert-max 1 t:LUT5 +select -assert-max 2 t:LUT4 select -assert-min 4 t:LUT6 +select -assert-max 7 t:LUT6 +select -assert-max 2 t:LUTMUX7 dump -select -assert-none t:LUT6 t:LUT5 t:LUT3 %% t:* %D +select -assert-none t:LUT6 t:LUT4 t:LUT3 t:LUTMUX7 %% t:* %D diff --git a/tests/arch/analogdevices/run-test.sh b/tests/arch/analogdevices/run-test.sh deleted file mode 100755 index 9b5e2f7f4..000000000 --- a/tests/arch/analogdevices/run-test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu -python3 mem_gen.py -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/arch/anlogic/generate_mk.py b/tests/arch/anlogic/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/anlogic/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/anlogic/run-test.sh b/tests/arch/anlogic/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/anlogic/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/ecp5/add_sub.ys b/tests/arch/ecp5/add_sub.ys index 9c3c03499..c3ce8c56d 100644 --- a/tests/arch/ecp5/add_sub.ys +++ b/tests/arch/ecp5/add_sub.ys @@ -4,7 +4,9 @@ proc equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module -select -assert-min 11 t:LUT4 -select -assert-count 2 t:PFUMX -select -assert-none t:LUT4 t:PFUMX %% t:* %D +select -assert-min 25 t:LUT4 +select -assert-max 26 t:LUT4 +select -assert-count 10 t:PFUMX +select -assert-count 6 t:L6MUX21 +select -assert-none t:LUT4 t:PFUMX t:L6MUX21 %% t:* %D diff --git a/tests/arch/ecp5/generate_mk.py b/tests/arch/ecp5/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/ecp5/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/ecp5/lutram.ys b/tests/arch/ecp5/lutram.ys index e83890a54..9bef37c68 100644 --- a/tests/arch/ecp5/lutram.ys +++ b/tests/arch/ecp5/lutram.ys @@ -11,8 +11,9 @@ sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w1r -select -assert-count 28 t:LUT4 -select -assert-count 8 t:PFUMX +select -assert-count 8 t:L6MUX21 +select -assert-count 36 t:LUT4 +select -assert-count 16 t:PFUMX select -assert-count 8 t:TRELLIS_DPR16X4 select -assert-count 8 t:TRELLIS_FF -select -assert-none t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D +select -assert-none t:L6MUX21 t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D diff --git a/tests/arch/ecp5/run-test.sh b/tests/arch/ecp5/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/ecp5/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/efinix/generate_mk.py b/tests/arch/efinix/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/efinix/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/efinix/run-test.sh b/tests/arch/efinix/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/efinix/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/fabulous/fsm.ys b/tests/arch/fabulous/fsm.ys index 9c3831682..5f7ae28dd 100644 --- a/tests/arch/fabulous/fsm.ys +++ b/tests/arch/fabulous/fsm.ys @@ -13,7 +13,7 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd fsm # Constrain all select calls below inside the top module select -assert-count 6 t:LUTFF -select -assert-max 4 t:LUT2 -select -assert-max 2 t:LUT3 -select -assert-max 9 t:LUT4 +select -assert-max 5 t:LUT2 +select -assert-max 4 t:LUT3 +select -assert-max 8 t:LUT4 select -assert-none t:LUT2 t:LUT3 t:LUT4 t:LUTFF %% t:* %D diff --git a/tests/arch/fabulous/generate_mk.py b/tests/arch/fabulous/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/fabulous/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/gatemate/add_sub.ys b/tests/arch/gatemate/add_sub.ys index bf261ba5a..6720e08a0 100644 --- a/tests/arch/gatemate/add_sub.ys +++ b/tests/arch/gatemate/add_sub.ys @@ -1,9 +1,29 @@ read_verilog ../common/add_sub.v hierarchy -top top proc +design -save orig + equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 8 t:CC_ADDF select -assert-max 4 t:CC_LUT1 select -assert-none t:CC_ADDF t:CC_LUT1 %% t:* %D + +design -load orig + +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 8 t:CC_ADDF +select -assert-max 4 t:CC_LUT1 +select -assert-none t:CC_ADDF t:CC_LUT1 %% t:* %D + +design -load orig + +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 8 t:CC_ADDF +select -assert-max 4 t:CC_LUT1 +select -assert-none t:CC_ADDF t:CC_LUT1 %% t:* %D diff --git a/tests/arch/gatemate/adffs.ys b/tests/arch/gatemate/adffs.ys index b2ded6e9d..0a80a4b48 100644 --- a/tests/arch/gatemate/adffs.ys +++ b/tests/arch/gatemate/adffs.ys @@ -31,6 +31,28 @@ select -assert-count 1 t:CC_DFF select -assert-max 1 t:CC_LUT2 select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D +design -load read +hierarchy -top dffs +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffs # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_BUFG +select -assert-count 1 t:CC_DFF +select -assert-max 1 t:CC_LUT2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D + +design -load read +hierarchy -top dffs +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffs # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_BUFG +select -assert-count 1 t:CC_DFF +select -assert-max 1 t:CC_LUT2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D + design -load read hierarchy -top ndffnr proc @@ -41,3 +63,25 @@ select -assert-count 1 t:CC_BUFG select -assert-count 1 t:CC_DFF select -assert-max 1 t:CC_LUT2 select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D + +design -load read +hierarchy -top ndffnr +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd ndffnr # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_BUFG +select -assert-count 1 t:CC_DFF +select -assert-max 1 t:CC_LUT2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D + +design -load read +hierarchy -top ndffnr +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd ndffnr # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_BUFG +select -assert-count 1 t:CC_DFF +select -assert-max 1 t:CC_LUT2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D diff --git a/tests/arch/gatemate/counter.ys b/tests/arch/gatemate/counter.ys index 77ed858b3..8aa04e5cb 100644 --- a/tests/arch/gatemate/counter.ys +++ b/tests/arch/gatemate/counter.ys @@ -2,6 +2,9 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten + +design -save orig + equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module @@ -10,3 +13,25 @@ select -assert-count 8 t:CC_ADDF select -assert-count 1 t:CC_BUFG select -assert-count 8 t:CC_DFF select -assert-none t:CC_ADDF t:CC_BUFG t:CC_DFF %% t:* %D + +design -load orig + +equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 8 t:CC_ADDF +select -assert-count 1 t:CC_BUFG +select -assert-count 8 t:CC_DFF +select -assert-none t:CC_ADDF t:CC_BUFG t:CC_DFF %% t:* %D + +design -load orig + +equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 8 t:CC_ADDF +select -assert-count 1 t:CC_BUFG +select -assert-count 8 t:CC_DFF +select -assert-none t:CC_ADDF t:CC_BUFG t:CC_DFF %% t:* %D diff --git a/tests/arch/gatemate/fsm.ys b/tests/arch/gatemate/fsm.ys index 506862c90..8af1a0a47 100644 --- a/tests/arch/gatemate/fsm.ys +++ b/tests/arch/gatemate/fsm.ys @@ -3,6 +3,8 @@ hierarchy -top fsm proc flatten +design -save orig + equiv_opt -run :prove -map +/gatemate/cells_sim.v synth_gatemate -noiopad async2sync miter -equiv -make_assert -flatten gold gate miter @@ -18,3 +20,42 @@ select -assert-max 5 t:CC_LUT2 select -assert-max 6 t:CC_LUT3 select -assert-max 9 t:CC_LUT4 select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 t:CC_LUT3 t:CC_LUT4 %% t:* %D + +design -load orig + +equiv_opt -run :prove -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree +async2sync +miter -equiv -make_assert -flatten gold gate miter +stat +sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter + +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd fsm # Constrain all select calls below inside the top module + +select -assert-count 1 t:CC_BUFG +select -assert-count 6 t:CC_DFF +select -assert-max 2 t:CC_LUT1 +select -assert-count 1 t:CC_LUT2 +select -assert-max 14 t:CC_L2T4 +select -assert-max 5 t:CC_L2T5 +select -assert-max 1 t:CC_MX2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT1 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 t:CC_MX2 %% t:* %D + +design -load orig + +equiv_opt -run :prove -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new +async2sync +miter -equiv -make_assert -flatten gold gate miter +stat +sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter + +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd fsm # Constrain all select calls below inside the top module + +select -assert-count 1 t:CC_BUFG +select -assert-count 6 t:CC_DFF +select -assert-count 2 t:CC_LUT2 +select -assert-count 9 t:CC_L2T4 +select -assert-count 6 t:CC_L2T5 +select -assert-count 1 t:CC_MX2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 t:CC_MX2 %% t:* %D diff --git a/tests/arch/gatemate/generate_mk.py b/tests/arch/gatemate/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/gatemate/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/gatemate/latches.ys b/tests/arch/gatemate/latches.ys index 5f64c6db5..a044bf5d6 100644 --- a/tests/arch/gatemate/latches.ys +++ b/tests/arch/gatemate/latches.ys @@ -27,3 +27,23 @@ cd latchsr # Constrain all select calls below inside the top module select -assert-count 1 t:CC_DLT select -assert-max 2 t:CC_LUT3 select -assert-none t:CC_DLT t:CC_LUT3 %% t:* %D + +design -load read +hierarchy -top latchsr +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd latchsr # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_DLT +select -assert-max 2 t:CC_L2T4 +select -assert-none t:CC_DLT t:CC_L2T4 %% t:* %D + +design -load read +hierarchy -top latchsr +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd latchsr # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_DLT +select -assert-max 2 t:CC_L2T4 +select -assert-none t:CC_DLT t:CC_L2T4 %% t:* %D diff --git a/tests/arch/gatemate/logic.ys b/tests/arch/gatemate/logic.ys index 026406bc8..e6204cdca 100644 --- a/tests/arch/gatemate/logic.ys +++ b/tests/arch/gatemate/logic.ys @@ -1,6 +1,9 @@ read_verilog ../common/logic.v hierarchy -top top proc + +design -save orig + equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module @@ -8,3 +11,23 @@ select -assert-max 1 t:CC_LUT1 select -assert-max 6 t:CC_LUT2 select -assert-max 2 t:CC_LUT4 select -assert-none t:CC_LUT1 t:CC_LUT2 t:CC_LUT4 %% t:* %D + +design -load orig + +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_LUT1 +select -assert-count 6 t:CC_LUT2 +select -assert-count 2 t:CC_L2T4 +select -assert-none t:CC_LUT1 t:CC_LUT2 t:CC_L2T4 %% t:* %D + +design -load orig + +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_LUT1 +select -assert-count 6 t:CC_LUT2 +select -assert-count 2 t:CC_L2T4 +select -assert-none t:CC_LUT1 t:CC_LUT2 t:CC_L2T4 %% t:* %D diff --git a/tests/arch/gatemate/luttrees.ys b/tests/arch/gatemate/luttrees.ys index 545643226..f3a61ee60 100644 --- a/tests/arch/gatemate/luttrees.ys +++ b/tests/arch/gatemate/luttrees.ys @@ -11,3 +11,24 @@ cd luttrees # Constrain all select calls below inside the top module select -assert-count 750 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% select -assert-none t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% t:* %D +design -load read + +hierarchy -top luttrees +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -nomx4 -nomx8 -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd luttrees # Constrain all select calls below inside the top module + +select -assert-count 750 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% +select -assert-none t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% t:* %D + +design -load read + +hierarchy -top luttrees +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -nomx4 -nomx8 -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd luttrees # Constrain all select calls below inside the top module + +select -assert-count 750 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% +select -assert-none t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% t:* %D diff --git a/tests/arch/gatemate/mul.ys b/tests/arch/gatemate/mul.ys index ded5fe729..ef2255a76 100644 --- a/tests/arch/gatemate/mul.ys +++ b/tests/arch/gatemate/mul.ys @@ -31,3 +31,29 @@ select -assert-count 1 t:CC_BUFG select -assert-max 18 t:CC_LUT4 select -assert-count 18 t:CC_DFF select -assert-none t:CC_MULT t:CC_BUFG t:CC_LUT4 t:CC_DFF %% t:* %D + +design -load read +hierarchy -top mul_unsigned_sync +proc +equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mul_unsigned_sync # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_MULT +select -assert-count 1 t:CC_BUFG +select -assert-count 18 t:CC_LUT2 +select -assert-count 18 t:CC_MX2 +select -assert-count 18 t:CC_DFF +select -assert-none t:CC_MULT t:CC_BUFG t:CC_LUT2 t:CC_MX2 t:CC_DFF %% t:* %D + +design -load read +hierarchy -top mul_unsigned_sync +proc +# equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check (fails) +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mul_unsigned_sync # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_MULT +select -assert-count 1 t:CC_BUFG +select -assert-count 18 t:CC_LUT2 +select -assert-count 18 t:CC_MX2 +select -assert-count 18 t:CC_DFF +select -assert-none t:CC_MULT t:CC_BUFG t:CC_LUT2 t:CC_MX2 t:CC_DFF %% t:* %D diff --git a/tests/arch/gatemate/mux.ys b/tests/arch/gatemate/mux.ys index 320ff33d7..51c3b5daf 100644 --- a/tests/arch/gatemate/mux.ys +++ b/tests/arch/gatemate/mux.ys @@ -12,6 +12,25 @@ select -assert-max 2 t:CC_LUT4 select -assert-max 1 t:CC_MX2 select -assert-none t:CC_LUT2 t:CC_LUT4 t:CC_MX2 %% t:* %D +design -load read +hierarchy -top mux4 +proc +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux4 # Constrain all select calls below inside the top module +select -assert-count 3 t:CC_MX2 +select -assert-none t:CC_MX2 %% t:* %D + +design -load read +hierarchy -top mux4 +proc +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux4 # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_LUT1 +select -assert-count 3 t:CC_MX2 +select -assert-none t:CC_LUT1 t:CC_MX2 %% t:* %D + design -load read hierarchy -top mux8 proc @@ -22,3 +41,21 @@ select -assert-max 1 t:CC_LUT3 select -assert-max 5 t:CC_LUT4 select -assert-max 1 t:CC_MX2 select -assert-none t:CC_LUT3 t:CC_LUT4 t:CC_MX2 %% t:* %D + +design -load read +hierarchy -top mux8 +proc +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux8 # Constrain all select calls below inside the top module +select -assert-count 7 t:CC_MX2 +select -assert-none t:CC_MX2 %% t:* %D + +design -load read +hierarchy -top mux8 +proc +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux8 # Constrain all select calls below inside the top module +select -assert-count 7 t:CC_MX2 +select -assert-none t:CC_MX2 %% t:* %D diff --git a/tests/arch/gatemate/run-test.sh b/tests/arch/gatemate/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/gatemate/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/generate_mk.py b/tests/arch/generate_mk.py new file mode 100644 index 000000000..4c12a497c --- /dev/null +++ b/tests/arch/generate_mk.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +from pathlib import Path +import sys +sys.path.append("..") + +import gen_tests_makefile + +techlibs_dir = Path("../../techlibs") + +# Architecture-specific defines +defines = { + "ice40": ["ICE40_HX", "ICE40_LP", "ICE40_U"] +} + +def archs(): + # Loop over architectures + for arch in techlibs_dir.iterdir(): + if not arch.is_dir(): + continue + arch_name = arch.name + + for path in arch.rglob("cells_sim.v"): + rel_parts = path.relative_to(techlibs_dir).parts + target_base = "_".join(rel_parts[-len(rel_parts):]).replace(".v", "") + path_str = str(path) + if arch_name in defines: + for defn in defines[arch_name]: + target_name = f"{target_base}_{defn}" + cmd = f"iverilog -t null -I{arch} -D{defn} -DNO_ICE40_DEFAULT_ASSIGNMENTS {path_str}" + gen_tests_makefile.generate_target(target_name, cmd) + else: + target_name = f"{target_base}" + cmd = f"iverilog -t null -I{arch} -g2005-sv {path_str}" + gen_tests_makefile.generate_target(target_name, cmd) + +def common(): + for path in ["../../techlibs/common/simcells.v", "../../techlibs/common/simlib.v"]: + path_obj = Path(path) + target_name = path_obj.stem + cmd = f"iverilog -t null {path}" + gen_tests_makefile.generate_target(target_name, cmd) + +def main(): + def callback(): + archs() + common() + + gen_tests_makefile.generate_custom(callback) + +if __name__ == "__main__": + main() diff --git a/tests/arch/gowin/generate_mk.py b/tests/arch/gowin/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/gowin/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/gowin/logic.ys b/tests/arch/gowin/logic.ys index 15f050e9b..d2b9e4540 100644 --- a/tests/arch/gowin/logic.ys +++ b/tests/arch/gowin/logic.ys @@ -7,7 +7,7 @@ cd top # Constrain all select calls below inside the top module select -assert-count 1 t:LUT1 select -assert-count 6 t:LUT2 -select -assert-count 2 t:LUT3 +select -assert-count 2 t:LUT4 select -assert-count 8 t:IBUF select -assert-count 10 t:OBUF -select -assert-none t:LUT1 t:LUT2 t:LUT3 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT1 t:LUT2 t:LUT4 t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/gowin/mux.ys b/tests/arch/gowin/mux.ys index fddf91d0e..2ca973520 100644 --- a/tests/arch/gowin/mux.ys +++ b/tests/arch/gowin/mux.ys @@ -18,12 +18,13 @@ proc equiv_opt -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux4 # Constrain all select calls below inside the top module -select -assert-count 3 t:LUT* -select -assert-count 1 t:MUX2_LUT5 +select -assert-count 4 t:LUT* +select -assert-count 2 t:MUX2_LUT5 +select -assert-count 1 t:MUX2_LUT6 select -assert-count 6 t:IBUF select -assert-count 1 t:OBUF -select -assert-none t:LUT* t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT* t:MUX2_LUT6 t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D design -load read hierarchy -top mux8 @@ -31,13 +32,17 @@ proc equiv_opt -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module -select -assert-count 1 t:LUT3 -select -assert-count 5 t:LUT4 -select -assert-count 1 t:MUX2_LUT5 +select -assert-count 3 t:LUT1 +select -assert-count 2 t:LUT3 +select -assert-count 1 t:LUT4 +select -assert-count 5 t:MUX2_LUT5 +select -assert-count 2 t:MUX2_LUT6 +select -assert-count 1 t:MUX2_LUT7 select -assert-count 11 t:IBUF select -assert-count 1 t:OBUF +select -assert-count 1 t:GND -select -assert-none t:LUT* t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT* t:MUX2_LUT7 t:MUX2_LUT6 t:MUX2_LUT5 t:IBUF t:OBUF t:GND %% t:* %D design -load read hierarchy -top mux16 diff --git a/tests/arch/gowin/run-test.sh b/tests/arch/gowin/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/gowin/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/ice40/generate_mk.py b/tests/arch/ice40/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/ice40/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/ice40/run-test.sh b/tests/arch/ice40/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/ice40/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/intel_alm/generate_mk.py b/tests/arch/intel_alm/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/intel_alm/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/intel_alm/logic.ys b/tests/arch/intel_alm/logic.ys index 91d6043e0..831f9f174 100644 --- a/tests/arch/intel_alm/logic.ys +++ b/tests/arch/intel_alm/logic.ys @@ -7,6 +7,6 @@ cd top # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_NOT select -assert-count 6 t:MISTRAL_ALUT2 -select -assert-count 2 t:MISTRAL_ALUT3 -select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 %% t:* %D +select -assert-count 2 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D diff --git a/tests/arch/intel_alm/run-test.sh b/tests/arch/intel_alm/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/intel_alm/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/machxo2/generate_mk.py b/tests/arch/machxo2/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/machxo2/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/machxo2/run-test.sh b/tests/arch/machxo2/run-test.sh deleted file mode 100644 index 691b70966..000000000 --- a/tests/arch/machxo2/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/microchip/generate_mk.py b/tests/arch/microchip/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/microchip/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/microchip/run-test.sh b/tests/arch/microchip/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/microchip/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/nanoxplore/generate_mk.py b/tests/arch/nanoxplore/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/nanoxplore/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/nanoxplore/run-test.sh b/tests/arch/nanoxplore/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/nanoxplore/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/nexus/add_sub.ys b/tests/arch/nexus/add_sub.ys index c1599c57e..4317bab81 100644 --- a/tests/arch/nexus/add_sub.ys +++ b/tests/arch/nexus/add_sub.ys @@ -16,6 +16,6 @@ equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module stat -select -assert-count 7 t:LUT4 -select -assert-count 2 t:WIDEFN9 +select -assert-count 6 t:LUT4 +select -assert-count 4 t:WIDEFN9 select -assert-none t:IB t:OB t:VLO t:LUT4 t:WIDEFN9 %% t:* %D diff --git a/tests/arch/nexus/generate_mk.py b/tests/arch/nexus/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/nexus/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/nexus/run-test.sh b/tests/arch/nexus/run-test.sh deleted file mode 100644 index 691b70966..000000000 --- a/tests/arch/nexus/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/quicklogic/pp3/generate_mk.py b/tests/arch/quicklogic/pp3/generate_mk.py new file mode 100644 index 000000000..e001d7e4a --- /dev/null +++ b/tests/arch/quicklogic/pp3/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/quicklogic/pp3/run-test.sh b/tests/arch/quicklogic/pp3/run-test.sh deleted file mode 100755 index 43a7874b2..000000000 --- a/tests/arch/quicklogic/pp3/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/quicklogic/qlf_k6n10f/generate_mk.py b/tests/arch/quicklogic/qlf_k6n10f/generate_mk.py new file mode 100644 index 000000000..e9abad21a --- /dev/null +++ b/tests/arch/quicklogic/qlf_k6n10f/generate_mk.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../../..") + +import gen_tests_makefile +import mem_gen + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/quicklogic/qlf_k6n10f/run-test.sh b/tests/arch/quicklogic/qlf_k6n10f/run-test.sh deleted file mode 100755 index c7daba12d..000000000 --- a/tests/arch/quicklogic/qlf_k6n10f/run-test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu -python3 mem_gen.py -source ../../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/arch/run-test.sh b/tests/arch/run-test.sh deleted file mode 100755 index 7602717d2..000000000 --- a/tests/arch/run-test.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -declare -A defines=( ["ice40"]="ICE40_HX ICE40_LP ICE40_U" ) - -echo "Running syntax check on arch sim models" -for arch in ../../techlibs/*; do - find $arch -name cells_sim.v | while read path; do - arch_name=$(basename -- $arch) - if [ "${defines[$arch_name]}" ]; then - for def in ${defines[$arch_name]}; do - echo -n "Test $path -D$def ->" - iverilog -t null -I$arch -D$def -DNO_ICE40_DEFAULT_ASSIGNMENTS $path - echo " ok" - done - else - echo -n "Test $path ->" - iverilog -t null -I$arch -g2005-sv $path - echo " ok" - fi - done -done - -for path in "../../techlibs/common/simcells.v" "../../techlibs/common/simlib.v"; do - echo -n "Test $path ->" - iverilog -t null $path - echo " ok" -done diff --git a/tests/arch/xilinx/generate_mk.py b/tests/arch/xilinx/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/xilinx/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/xilinx/run-test.sh b/tests/arch/xilinx/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/xilinx/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arith_tree/arith_tree_add_chains.ys b/tests/arith_tree/arith_tree_add_chains.ys new file mode 100644 index 000000000..f293ed9da --- /dev/null +++ b/tests/arith_tree/arith_tree_add_chains.ys @@ -0,0 +1,197 @@ +read_verilog < run-test.mk -exec ${MAKE:-make} -f run-test.mk diff --git a/tests/blif/gatesi.blif.ok b/tests/blif/gatesi.blif.ok index e99d7906f..8213a8a89 100644 --- a/tests/blif/gatesi.blif.ok +++ b/tests/blif/gatesi.blif.ok @@ -1,4 +1,3 @@ -# Generated by Yosys .model test .inputs clk in_a_var[0] in_a_var[1] in_a_var[2] in_a_var[3] in_a_var[4] in_a_var[5] in_a_var[6] in_a_var[7] in_b_var[0] in_b_var[1] in_b_var[2] in_b_var[3] in_b_var[4] in_b_var[5] in_b_var[6] in_b_var[7] diff --git a/tests/blif/gatesi.ys b/tests/blif/gatesi.ys index 44c022bb9..0f1ebd911 100644 --- a/tests/blif/gatesi.ys +++ b/tests/blif/gatesi.ys @@ -1,2 +1,4 @@ read_blif gatesi.blif -write_blif -gatesi gatesi.blif.out \ No newline at end of file +write_blif -gatesi gatesi.blif.out +! tail -n +2 gatesi.blif.out > gatesi.blif.out.tmp && mv gatesi.blif.out.tmp gatesi.blif.out +! diff gatesi.blif.out gatesi.blif.ok diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/blif/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/blif/run-test.sh b/tests/blif/run-test.sh deleted file mode 100755 index 14b9ead8e..000000000 --- a/tests/blif/run-test.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys --no-version -ql ${x%.ys}.log $x -done - -for x in *.blif; do - diff $x.out $x.ok -done \ No newline at end of file diff --git a/tests/bram/generate.py b/tests/bram/generate_mk.py similarity index 95% rename from tests/bram/generate.py rename to tests/bram/generate_mk.py index 79dd500a3..09f5c650b 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate_mk.py @@ -4,6 +4,10 @@ import argparse import os import sys import random +import glob + +sys.path.append("..") +import gen_tests_makefile debug_mode = False @@ -287,9 +291,11 @@ if args.seed is not None: else: seed = (int(os.times()[4]*100) + os.getpid()) % 900000 + 100000 -print("PRNG seed: %d" % seed) +print("bram PRNG seed: %d" % seed) random.seed(seed) +os.makedirs("temp", exist_ok=True) + for k1 in range(args.count): dsc_f = open("temp/brams_%02d.txt" % k1, "w") sim_f = open("temp/brams_%02d.v" % k1, "w") @@ -303,3 +309,19 @@ for k1 in range(args.count): for k2 in range(lenk2): create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2, random.randrange(2 if k2+1 < lenk2 else 1)) +configs = sorted(set( + os.path.basename(f).replace("brams_", "").replace(".txt", "") + for f in glob.glob("temp/brams_*.txt") +)) + +def create_tests(): + for i in configs: + for j in configs: + if i != j: + gen_tests_makefile.generate_cmd_test( + f"bram_{i}_{j}", + f"bash run-single.sh {i} {j}" + ) + +gen_tests_makefile.generate_custom(create_tests) + diff --git a/tests/bram/run-test.sh b/tests/bram/run-test.sh deleted file mode 100755 index 47f24f5dd..000000000 --- a/tests/bram/run-test.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# MAKE="make -j8" time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=5 -seed="" # default to no seed specified -debug="" -while getopts "c:dS:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - d) debug="-d" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp - -echo "generating tests.." -python3 generate.py $debug -c $count $seed - -{ - echo -n "all:" - for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do - for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do - echo -n " temp/job_${i}_${j}.ok" - done; done - echo - for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do - for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do - echo "temp/job_${i}_${j}.ok:" - echo " @bash run-single.sh ${i} ${j}" - echo " @echo 'Passed memory_bram test ${i}_${j}.'" - echo " @touch \$@" - done; done -} > temp/makefile - -echo "running tests.." -${MAKE:-make} -f temp/makefile - -exit 0 diff --git a/tests/bugpoint/generate_mk.py b/tests/bugpoint/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/bugpoint/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/bugpoint/run-test.sh b/tests/bugpoint/run-test.sh deleted file mode 100755 index 006c731e3..000000000 --- a/tests/bugpoint/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts diff --git a/tests/common-env.sh b/tests/common-env.sh deleted file mode 100644 index f3a411280..000000000 --- a/tests/common-env.sh +++ /dev/null @@ -1 +0,0 @@ -export YOSYS_MAX_THREADS=4 diff --git a/tests/common.mk b/tests/common.mk new file mode 100644 index 000000000..044054e0c --- /dev/null +++ b/tests/common.mk @@ -0,0 +1,44 @@ +all: + +ifndef OVERRIDE_MAIN +clean: + @rm -f *.log *.result +endif + +define run_test + @set -e; \ + rc=0; \ + ( set -e; $(2) ) >/dev/null 2>&1 || rc=$$?; \ + if [ $$rc -eq 0 ]; then \ + echo "PASS $1"; \ + echo PASS > $1.result; \ + else \ + echo "FAIL $1"; \ + echo FAIL > $1.result; \ + fi +endef + +.PHONY: summary +summary: + @pass=$$(find . -type f -name '*.result' -exec grep '^PASS$$' {} + | wc -l); \ + fail=$$(find . -type f -name '*.result' -exec grep '^FAIL$$' {} + | wc -l); \ + total=$$((pass + fail)); \ + echo "=========================="; \ + echo "Tests: $$total"; \ + echo "Passed: $$pass"; \ + echo "Failed: $$fail"; \ + echo "=========================="; \ + if [ $$fail -ne 0 ]; then \ + echo; \ + $(MAKE) --no-print-directory report; \ + fi; \ + test $$fail -eq 0 + +.PHONY: report +report: + @echo "==========================" + @echo "Failing tests:" + @find . -name '*.result' -type f -exec grep -H '^FAIL$$' {} + \ + | cut -d: -f1 \ + | sed 's|^\./||; s|\.result$$||' + @echo "==========================" diff --git a/tests/cxxrtl/generate_mk.py b/tests/cxxrtl/generate_mk.py new file mode 100644 index 000000000..b75c78e97 --- /dev/null +++ b/tests/cxxrtl/generate_mk.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +def run_subtest(name): + gen_tests_makefile.generate_cmd_test(f"cxxrtl_{name}", [ + f"$${{CXX:-g++}} -std=c++11 -O2 -o cxxrtl-test-{name} -I../../backends/cxxrtl/runtime test_{name}.cc -lstdc++", + f"./cxxrtl-test-{name}", + ]) + +def compile_only(): + gen_tests_makefile.generate_cmd_test("cxxrtl_unconnected_output", [ + '$(YOSYS) -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc"', + f'$${{CXX:-g++}} -std=c++11 -c -o cxxrtl-test-unconnected_output -I../../backends/cxxrtl/runtime cxxrtl-test-unconnected_output.cc', + ]) + +def main(): + def callback(): + run_subtest("value") + run_subtest("value_fuzz") + compile_only() + + gen_tests_makefile.generate_custom(callback) + +if __name__ == "__main__": + main() diff --git a/tests/cxxrtl/run-test.sh b/tests/cxxrtl/run-test.sh deleted file mode 100755 index aa7a0c26c..000000000 --- a/tests/cxxrtl/run-test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -source ../common-env.sh - -set -ex - -run_subtest () { - local subtest=$1; shift - - ${CXX:-g++} -std=c++11 -O2 -o cxxrtl-test-${subtest} -I../../backends/cxxrtl/runtime test_${subtest}.cc -lstdc++ - ./cxxrtl-test-${subtest} -} - -run_subtest value -run_subtest value_fuzz - -# Compile-only test. -../../yosys -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" -${CXX:-g++} -std=c++11 -c -o cxxrtl-test-unconnected_output -I../../backends/cxxrtl/runtime cxxrtl-test-unconnected_output.cc diff --git a/tests/fmt/generate_mk.py b/tests/fmt/generate_mk.py new file mode 100644 index 000000000..2e94d4500 --- /dev/null +++ b/tests/fmt/generate_mk.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +def initial_display(): + gen_tests_makefile.generate_cmd_test("initial_display", [ + f"$(YOSYS) -p \"read_verilog initial_display.v\" | awk '/<<>>/,/<<>>/ {{print $$0}}' >yosys-initial_display.log 2>&1", + "iverilog -o iverilog-initial_display initial_display.v", + "./iverilog-initial_display >iverilog-initial_display.log", + "diff yosys-initial_display.log iverilog-initial_display.log", + ]) + + +def always_display(): + cases = [ + ("clk", "-DEVENT_CLK"), + ("clk_rst", "-DEVENT_CLK_RST"), + ("star", "-DEVENT_STAR"), + ("clk_en", "-DEVENT_CLK -DCOND_EN"), + ("clk_rst_en", "-DEVENT_CLK_RST -DCOND_EN"), + ("star_en", "-DEVENT_STAR -DCOND_EN"), + ] + + for name, defs in cases: + gen_tests_makefile.generate_cmd_test(f"always_display_{name}", [ + f"$(YOSYS) -p \"read_verilog {defs} always_display.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-1.v", + f"$(YOSYS) -p \"read_verilog yosys-always_display-{name}-1.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-2.v", + f"diff yosys-always_display-{name}-1.v yosys-always_display-{name}-2.v", + ]) + + +def roundtrip(): + cases = [ + ("dec_unsigned", '-DBASE_DEC -DSIGN=""'), + ("dec_signed", '-DBASE_DEC -DSIGN="signed"'), + ("hex_unsigned", '-DBASE_HEX -DSIGN=""'), + ("hex_signed", '-DBASE_HEX -DSIGN="signed"'), + ("oct_unsigned", '-DBASE_HEX -DSIGN=""'), + ("oct_signed", '-DBASE_HEX -DSIGN="signed"'), + ("bin_unsigned", '-DBASE_HEX -DSIGN=""'), + ("bin_signed", '-DBASE_HEX -DSIGN="signed"'), + ] + + for name, defs in cases: + gen_tests_makefile.generate_cmd_test(f"roundtrip_{name}", [ + f"$(YOSYS) -p \"read_verilog {defs} roundtrip.v; proc; clean\" -o yosys-roundtrip-{name}-1.v", + f"$(YOSYS) -p \"read_verilog yosys-roundtrip-{name}-1.v; proc; clean\" -o yosys-roundtrip-{name}-2.v", + f"diff yosys-roundtrip-{name}-1.v yosys-roundtrip-{name}-2.v", + + f"iverilog {defs} -o iverilog-roundtrip-{name} roundtrip.v roundtrip_tb.v", + f"./iverilog-roundtrip-{name} >iverilog-roundtrip-{name}.log", + + f"iverilog {defs} -o iverilog-roundtrip-{name}-1 yosys-roundtrip-{name}-1.v roundtrip_tb.v", + f"./iverilog-roundtrip-{name}-1 >iverilog-roundtrip-{name}-1.log", + + f"iverilog {defs} -o iverilog-roundtrip-{name}-2 yosys-roundtrip-{name}-2.v roundtrip_tb.v", + f"./iverilog-roundtrip-{name}-2 >iverilog-roundtrip-{name}-2.log", + + f"diff iverilog-roundtrip-{name}.log iverilog-roundtrip-{name}-1.log", + f"diff iverilog-roundtrip-{name}-1.log iverilog-roundtrip-{name}-2.log", + ]) + + +def cxxrtl(): + cases = ["always_full", "always_comb"] + + for name in cases: + gen_tests_makefile.generate_cmd_test(f"cxxrtl_{name}", [ + f"$(YOSYS) -p \"read_verilog {name}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-{name}.cc\"", + f"$${{CXX:-g++}} -std=c++11 -o yosys-{name} -I../../backends/cxxrtl/runtime {name}_tb.cc -lstdc++", + f"./yosys-{name} 2>yosys-{name}.log", + + f"iverilog -o iverilog-{name} {name}.v {name}_tb.v", + f"./iverilog-{name} | grep -v \"$finish called\" >iverilog-{name}.log", + + f"diff iverilog-{name}.log yosys-{name}.log", + ]) + + +def extra(): + gen_tests_makefile.generate_cmd_test("always_full_equiv", [ + "$(YOSYS) -p \"read_verilog always_full.v; prep; clean\" -o yosys-always_full-1.v", + "iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v", + "./iverilog-always_full-1 > tmp.log", + "grep -v '\\$finish called' tmp.log > iverilog-always_full-1.log", + "diff iverilog-always_full.log iverilog-always_full-1.log", + ], deps=["cxxrtl_always_full"]) + + gen_tests_makefile.generate_cmd_test("display_lm", [ + "$(YOSYS) -p \"read_verilog display_lm.v\" >yosys-display_lm.log 2>&1", + "$(YOSYS) -p \"read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc\"", + f"$${{CXX:-g++}} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++", + "./yosys-display_lm_cc >yosys-display_lm_cc.log", + "grep \"^%l: \\\\\\bot\\$$\" \"yosys-display_lm.log\"", + "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm.log\"", + "grep \"^%l: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\"", + "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\"", + ]) + + +def main(): + def callback(): + initial_display() + always_display() + roundtrip() + cxxrtl() + extra() + + gen_tests_makefile.generate_custom(callback) + + +if __name__ == "__main__": + main() diff --git a/tests/fmt/run-test.sh b/tests/fmt/run-test.sh deleted file mode 100644 index a3402f953..000000000 --- a/tests/fmt/run-test.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -ex - -../../yosys -p 'read_verilog initial_display.v' | awk '/<<>>/,/<<>>/ {print $0}' >yosys-initial_display.log -iverilog -o iverilog-initial_display initial_display.v -./iverilog-initial_display >iverilog-initial_display.log -diff yosys-initial_display.log iverilog-initial_display.log - -test_always_display () { - local subtest=$1; shift - ../../yosys -p "read_verilog $* always_display.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-1.v - ../../yosys -p "read_verilog yosys-always_display-${subtest}-1.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-2.v - diff yosys-always_display-${subtest}-1.v yosys-always_display-${subtest}-2.v -} - -test_always_display clk -DEVENT_CLK -test_always_display clk_rst -DEVENT_CLK_RST -test_always_display star -DEVENT_STAR - -test_always_display clk_en -DEVENT_CLK -DCOND_EN -test_always_display clk_rst_en -DEVENT_CLK_RST -DCOND_EN -test_always_display star_en -DEVENT_STAR -DCOND_EN - -test_roundtrip () { - local subtest=$1; shift - ../../yosys -p "read_verilog $* roundtrip.v; proc; clean" -o yosys-roundtrip-${subtest}-1.v - ../../yosys -p "read_verilog yosys-roundtrip-${subtest}-1.v; proc; clean" -o yosys-roundtrip-${subtest}-2.v - diff yosys-roundtrip-${subtest}-1.v yosys-roundtrip-${subtest}-2.v - - iverilog $* -o iverilog-roundtrip-${subtest} roundtrip.v roundtrip_tb.v - ./iverilog-roundtrip-${subtest} >iverilog-roundtrip-${subtest}.log - iverilog $* -o iverilog-roundtrip-${subtest}-1 yosys-roundtrip-${subtest}-1.v roundtrip_tb.v - ./iverilog-roundtrip-${subtest}-1 >iverilog-roundtrip-${subtest}-1.log - iverilog $* -o iverilog-roundtrip-${subtest}-2 yosys-roundtrip-${subtest}-2.v roundtrip_tb.v - ./iverilog-roundtrip-${subtest}-1 >iverilog-roundtrip-${subtest}-2.log - diff iverilog-roundtrip-${subtest}.log iverilog-roundtrip-${subtest}-1.log - diff iverilog-roundtrip-${subtest}-1.log iverilog-roundtrip-${subtest}-2.log -} - -test_roundtrip dec_unsigned -DBASE_DEC -DSIGN="" -test_roundtrip dec_signed -DBASE_DEC -DSIGN="signed" -test_roundtrip hex_unsigned -DBASE_HEX -DSIGN="" -test_roundtrip hex_signed -DBASE_HEX -DSIGN="signed" -test_roundtrip oct_unsigned -DBASE_HEX -DSIGN="" -test_roundtrip oct_signed -DBASE_HEX -DSIGN="signed" -test_roundtrip bin_unsigned -DBASE_HEX -DSIGN="" -test_roundtrip bin_signed -DBASE_HEX -DSIGN="signed" - -test_cxxrtl () { - local subtest=$1; shift - - ../../yosys -p "read_verilog ${subtest}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-${subtest}.cc" - ${CXX:-g++} -std=c++11 -o yosys-${subtest} -I../../backends/cxxrtl/runtime ${subtest}_tb.cc -lstdc++ - ./yosys-${subtest} 2>yosys-${subtest}.log - iverilog -o iverilog-${subtest} ${subtest}.v ${subtest}_tb.v - ./iverilog-${subtest} |grep -v '\$finish called' >iverilog-${subtest}.log - diff iverilog-${subtest}.log yosys-${subtest}.log -} - -test_cxxrtl always_full -test_cxxrtl always_comb - -# Ensure Verilog backend preserves behaviour of always block with multiple $displays. -../../yosys -p "read_verilog always_full.v; prep; clean" -o yosys-always_full-1.v -iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v -./iverilog-always_full-1 |grep -v '\$finish called' >iverilog-always_full-1.log -diff iverilog-always_full.log iverilog-always_full-1.log - -../../yosys -p "read_verilog display_lm.v" >yosys-display_lm.log -../../yosys -p "read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc" -${CXX:-g++} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++ -./yosys-display_lm_cc >yosys-display_lm_cc.log -for log in yosys-display_lm.log yosys-display_lm_cc.log; do - grep "^%l: \\\\bot\$" "$log" - grep "^%m: \\\\bot\$" "$log" -done diff --git a/tests/fsm/.gitignore b/tests/fsm/.gitignore index 9c595a6fb..90ea6e92a 100644 --- a/tests/fsm/.gitignore +++ b/tests/fsm/.gitignore @@ -1 +1 @@ -temp +uut_*.* diff --git a/tests/fsm/generate.py b/tests/fsm/generate_mk.py similarity index 89% rename from tests/fsm/generate.py rename to tests/fsm/generate_mk.py index 784e5a054..dc3518009 100644 --- a/tests/fsm/generate.py +++ b/tests/fsm/generate_mk.py @@ -1,21 +1,18 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import argparse import sys import random -from contextlib import contextmanager +from pathlib import Path # set to 'True' to compare verific with yosys test_verific = False -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target - def random_expr(variables): c = random.choice(['bin', 'uni', 'var', 'const']) if c == 'bin': @@ -39,12 +36,16 @@ args = parser.parse_args() seed = args.seed if seed is None: seed = random.randrange(sys.maxsize) -print("PRNG seed: %d" % seed) +print("fsm PRNG seed: %d" % seed) random.seed(seed) +for path in Path(".").glob("uut_*.*"): + if path.is_file(): + path.unlink() + for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): rst2 = random.choice([False, True]) if rst2: print('module uut_%05d(clk, rst1, rst2, rst, a, b, c, x, y, z);' % (idx)) @@ -99,16 +100,16 @@ for idx in range(args.count): print(' end') print(' end') print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): if test_verific: - print('read_verilog temp/uut_%05d.v' % idx) + print('read_verilog uut_%05d.v' % idx) print('proc;; rename uut_%05d gold' % idx) - print('verific -vlog2k temp/uut_%05d.v' % idx) + print('verific -vlog2k uut_%05d.v' % idx) print('verific -import uut_%05d' % idx) print('rename uut_%05d gate' % idx) else: - print('read_verilog temp/uut_%05d.v' % idx) + print('read_verilog uut_%05d.v' % idx) print('proc;;') print('copy uut_%05d gold' % idx) print('rename uut_%05d gate' % idx) @@ -118,3 +119,4 @@ for idx in range(args.count): print('miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter') print('sat -verify-no-timeout -timeout 20 -seq 5 -set-at 1 %s_rst 1 -prove trigger 0 -prove-skip 1 -show-inputs -show-outputs miter' % ('gold' if rst2 else 'in')) +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/fsm/run-test.sh b/tests/fsm/run-test.sh deleted file mode 100755 index 139ea8261..000000000 --- a/tests/fsm/run-test.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=50 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -{ - all_targets="all_targets:" - echo "all: all_targets" - echo " @echo" - for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do - idx=$( printf "%05d" $i ) - echo "temp/uut_${idx}.log: temp/uut_${idx}.ys temp/uut_${idx}.v" - echo " @echo -n '[$i]'" - echo " @../../yosys -ql temp/uut_${idx}.out temp/uut_${idx}.ys" - echo " @mv temp/uut_${idx}.out temp/uut_${idx}.log" - echo " @grep -q 'SAT proof finished' temp/uut_${idx}.log && echo -n K || echo -n T" - all_targets="$all_targets temp/uut_${idx}.log" - done - echo "$all_targets" -} > temp/makefile - -echo "running tests.." -${MAKE:-make} -f temp/makefile - -exit 0 diff --git a/tests/functional/generate_mk.py b/tests/functional/generate_mk.py new file mode 100644 index 000000000..3d63d1fe9 --- /dev/null +++ b/tests/functional/generate_mk.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +def callback(): + gen_tests_makefile.generate_cmd_test("functional",f'pytest -v -m "not smt and not rkt" . "$$@"') + +gen_tests_makefile.generate_custom(callback) diff --git a/tests/functional/rtlil_cells.py b/tests/functional/rtlil_cells.py index 964d81ddf..9a44821d3 100644 --- a/tests/functional/rtlil_cells.py +++ b/tests/functional/rtlil_cells.py @@ -337,7 +337,7 @@ rtlil_cells = [ # ("tribuf", ["A", "EN", "Y"]), # ("specify2", ["EN", "SRC", "DST"]), # ("specify3", ["EN", "SRC", "DST", "DAT"]), -# ("specrule", ["EN_SRC", "EN_DST", "SRC", "DST"]), +# ("specrule", ["SRC_EN", "DST_EN", "SRC", "DST"]), BWCell("bweqx", [10, 16, 40]), BWCell("bwmux", [10, 16, 40]), FFCell("ff", [10, 20, 40]), diff --git a/tests/functional/run-test.sh b/tests/functional/run-test.sh index 7c38f3190..8f72f7c1b 100755 --- a/tests/functional/run-test.sh +++ b/tests/functional/run-test.sh @@ -1,6 +1,4 @@ #!/usr/bin/env bash -source ../common-env.sh - SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) pytest -v -m "not smt and not rkt" "$SCRIPT_DIR" "$@" diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py index aa7500f8b..661af14d1 100644 --- a/tests/functional/test_functional.py +++ b/tests/functional/test_functional.py @@ -21,7 +21,7 @@ def yosys(script): run([base_path / 'yosys', '-Q', '-p', script]) def compile_cpp(in_path, out_path, args): - run(['g++', '-g', '-std=c++17'] + args + [str(in_path), '-o', str(out_path)]) + run(['g++', '-g', '-std=c++20'] + args + [str(in_path), '-o', str(out_path)]) def yosys_synth(verilog_file, rtlil_file): yosys(f"read_verilog {quote(verilog_file)} ; prep ; setundef -undriven -undef ; write_rtlil {quote(rtlil_file)}") diff --git a/tests/gen-tests-makefile.sh b/tests/gen-tests-makefile.sh deleted file mode 100755 index a0fb23ac3..000000000 --- a/tests/gen-tests-makefile.sh +++ /dev/null @@ -1,110 +0,0 @@ -set -eu - -YOSYS_BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../ >/dev/null 2>&1 && pwd)" - -# $ generate_target target_name test_command -generate_target() { - target_name=$(basename $PWD)-$1 - test_command=$2 - echo "all: $target_name" - echo ".PHONY: $target_name" - echo "$target_name:" - printf "\t@YOSYS_MAX_THREADS=4 %s\n" "$test_command" - printf "\t@echo 'Passed %s'\n" "$target_name" -} - -# $ generate_ys_test ys_file [yosys_args] -generate_ys_test() { - ys_file=$1 - yosys_args_=${2:-} - generate_target "$ys_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${ys_file}.err $yosys_args_ $ys_file && mv ${ys_file}.err ${ys_file}.log" -} - -# $ generate_tcl_test tcl_file [yosys_args] -generate_tcl_test() { - tcl_file=$1 - yosys_args_=${2:-} - generate_target "$tcl_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${tcl_file}.err $yosys_args_ $tcl_file && mv ${tcl_file}.err ${tcl_file}.log" -} - -# $ generate_bash_test bash_file -generate_bash_test() { - bash_file=$1 - generate_target "$bash_file" "bash -v $bash_file >${bash_file}.err 2>&1 && mv ${bash_file}.err ${bash_file}.log" -} - -# $ generate_tests [-y|--yosys-scripts] [-s|--prove-sv] [-b|--bash] [-a|--yosys-args yosys_args] -generate_tests() { - do_ys=false - do_tcl=false - do_sv=false - do_sh=false - yosys_args="" - - while [[ $# -gt 0 ]]; do - arg="$1" - case "$arg" in - -y|--yosys-scripts) - do_ys=true - shift - ;; - -t|--tcl-scripts) - do_tcl=true - shift - ;; - -s|--prove-sv) - do_sv=true - shift - ;; - -b|--bash) - do_sh=true - shift - ;; - -a|--yosys-args) - yosys_args+="$2" - shift - shift - ;; - *) - echo >&2 "Unknown argument: $1" - exit 1 - esac - done - - if [[ ! ( $do_ys = true || $do_tcl = true || $do_sv = true || $do_sh = true ) ]]; then - echo >&2 "Error: No file types selected" - exit 1 - fi - - echo ".PHONY: all" - echo "all:" - - if [[ $do_ys = true ]]; then - for x in *.ys; do - generate_ys_test "$x" "$yosys_args" - done - fi; - if [[ $do_tcl = true ]]; then - for x in *.tcl; do - generate_tcl_test "$x" "$yosys_args" - done - fi; - if [[ $do_sv = true ]]; then - for x in *.sv; do - if [ ! -f "${x%.sv}.ys" ]; then - generate_ys_test "$x" "-p \"prep -top top; async2sync; sat -enable_undef -verify -prove-asserts\" $yosys_args" - fi; - done - fi; - if [[ $do_sh == true ]]; then - for s in *.sh; do - if [ "$s" != "run-test.sh" ]; then - generate_bash_test "$s" - fi - done - fi -} - -generate_mk() { - generate_tests "$@" > run-test.mk -} diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py new file mode 100644 index 000000000..38596f63b --- /dev/null +++ b/tests/gen_tests_makefile.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 + +import glob +import os +import sys +import argparse +from contextlib import contextmanager + +yosys_basedir = os.path.relpath(os.path.join(os.path.dirname(__file__), "..")) +common_mk = os.path.relpath(os.path.join(os.path.dirname(__file__), "common.mk")) + +def _cwd_base(): + return os.path.basename(os.getcwd()) + +def generate_target(name, command, deps = None): + #target = f"{_cwd_base()}-{name}" + target = f"{name}" + print(f"all: {target}") + print(f".PHONY: {target}") + print(f"{target}_cmd={command}") + if deps: + print(f"{target}: {' '.join(deps)}") + else: + print(f"{target}:") + + print(f"\t@$(call run_test,{target}, $({target}_cmd))") + +def generate_ys_test(ys_file, yosys_args="", commands=""): + cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} && mv {ys_file}.err {ys_file}.log' + if commands: + cmd += f"; \\\n{commands}" + generate_target(ys_file, cmd) + +def generate_tcl_test(tcl_file, yosys_args="", commands=""): + cmd = f'$(YOSYS) -ql {tcl_file}.err {yosys_args} {tcl_file} && mv {tcl_file}.err {tcl_file}.log' + if commands: + cmd += f"; \\\n{commands}" + generate_target(tcl_file, cmd) + +def generate_sv_test(sv_file, yosys_args="", commands=""): + base = os.path.splitext(sv_file)[0] + if not os.path.exists(base + ".ys"): + yosys_cmd = '-p "prep -top top; async2sync; sat -enable_undef -verify -prove-asserts"' + cmd = f'$(YOSYS) -ql {sv_file}.err {yosys_cmd} {yosys_args} {sv_file} && mv {sv_file}.err {sv_file}.log' + if commands: + cmd += f"; \\\n{commands}" + generate_target(sv_file, cmd) + +def generate_bash_test(sh_file, commands=""): + cmd = f"bash -v {sh_file} >{sh_file}.err 2>&1 && mv {sh_file}.err {sh_file}.log" + if commands: + cmd += f"; \\\n{commands}" + generate_target(sh_file, cmd) + +def unpack_cmd(cmd): + if isinstance(cmd, str): + return cmd + if isinstance(cmd, (list, tuple)): + return " && \\\n".join(cmd) + raise TypeError("cmd must be a string or a list/tuple of strings") + +def generate_cmd_test(test_name, cmd, yosys_args="", deps = None): + generate_target(test_name, unpack_cmd(cmd), deps) + +def generate_tests(argv, cmds): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("-y", "--yosys-scripts", action="store_true") + parser.add_argument("-t", "--tcl-scripts", action="store_true") + parser.add_argument("-s", "--prove-sv", action="store_true") + parser.add_argument("-b", "--bash", action="store_true") + parser.add_argument("-a", "--yosys-args", default="") + + args = parser.parse_args(argv) + + if not (args.yosys_scripts or args.tcl_scripts or args.prove_sv or args.bash): + raise RuntimeError("No file types selected") + + if args.yosys_scripts: + for f in sorted(glob.glob("*.ys")): + generate_ys_test(f, args.yosys_args, cmds) + + if args.tcl_scripts: + for f in sorted(glob.glob("*.tcl")): + generate_tcl_test(f, args.yosys_args, cmds) + + if args.prove_sv: + for f in sorted(glob.glob("*.sv")): + generate_sv_test(f, args.yosys_args, cmds) + + if args.bash: + for f in sorted(glob.glob("*.sh")): + if f != "run-test.sh": + generate_bash_test(f, cmds) + +def print_header(extra=None): + print(f"include {common_mk}") + print(f"YOSYS ?= {yosys_basedir}/yosys") + print("") + print("export YOSYS_MAX_THREADS := 4") + if extra: + for line in extra: + print(line) + print("") + print(".PHONY: all") + print("all:") + +@contextmanager +def redirect_stdout(new_target): + old_target, sys.stdout = sys.stdout, new_target + try: + yield new_target + finally: + sys.stdout = old_target + +def generate(argv, extra=None, cmds=""): + with open("Makefile", "w") as f: + with redirect_stdout(f): + print_header(extra) + generate_tests(argv, cmds) + +def generate_custom(callback, extra=None): + with open("Makefile", "w") as f: + with redirect_stdout(f): + print_header(extra) + callback() + +def generate_autotest_file(test_file, commands): + cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file}; \\\n{commands}" + generate_target(test_file, cmd) + +def generate_autotest(pattern, extra_flags, cmds=""): + with open("Makefile", "w") as f: + with redirect_stdout(f): + print_header([ f"EXTRA_FLAGS = {extra_flags}", + "SEED ?=", + "ifneq ($(strip $(SEED)),)", + " SEEDOPT=-S$(SEED)", + "endif", + ]) + for fn in sorted(glob.glob(pattern)): + generate_autotest_file(fn, cmds) diff --git a/tests/hana/generate_mk.py b/tests/hana/generate_mk.py new file mode 100644 index 000000000..0068c590a --- /dev/null +++ b/tests/hana/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("test_*.v", "-l hana_vlib.v -n 300 -e") diff --git a/tests/hana/run-test.sh b/tests/hana/run-test.sh deleted file mode 100755 index 8533e5544..000000000 --- a/tests/hana/run-test.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -exec ${MAKE:-make} -f ../tools/autotest.mk $seed EXTRA_FLAGS="-l hana_vlib.v -n 300 -e" test_*.v diff --git a/tests/liberty/generate_mk.py b/tests/liberty/generate_mk.py new file mode 100644 index 000000000..b2559cced --- /dev/null +++ b/tests/liberty/generate_mk.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 + +import glob +import os +import sys +sys.path.append("..") + +import gen_tests_makefile + +def lib_tests(): + for lib in sorted(glob.glob("*.lib")): + base = os.path.splitext(lib)[0] + + gen_tests_makefile.generate_cmd_test(lib, [ + f'$(YOSYS) -p "read_verilog small.v; synth -top small; dfflibmap -info -liberty {lib}" -ql {base}.log', + + f'$(YOSYS_FILTERLIB) - {lib} > {lib}.filtered', + f'$(YOSYS_FILTERLIB) -verilogsim {lib} > {lib}.verilogsim', + + f'diff {lib}.filtered {lib}.filtered.ok', + f'diff {lib}.verilogsim {lib}.verilogsim.ok', + + f'if [ -e {base}.log.ok ]; then ' + f'$(YOSYS) -p "dfflibmap -info -liberty {lib}" -TqqQl {base}.log; ' + f'diff {base}.log {base}.log.ok; ' + f'fi', + ]) + + +def ys_tests(): + for ys in sorted(glob.glob("*.ys")): + gen_tests_makefile.generate_ys_test(ys) + +def main(): + def callback(): + lib_tests() + ys_tests() + + gen_tests_makefile.generate_custom(callback, + [f"YOSYS_FILTERLIB ?= {gen_tests_makefile.yosys_basedir}/yosys-filterlib"]) + + +if __name__ == "__main__": + main() diff --git a/tests/liberty/run-test.sh b/tests/liberty/run-test.sh deleted file mode 100755 index d5fb65e16..000000000 --- a/tests/liberty/run-test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -eo pipefail - -for x in *.lib; do - echo "Testing on $x.." - ../../yosys -p "read_verilog small.v; synth -top small; dfflibmap -info -liberty ${x}" -ql ${x%.lib}.log - ../../yosys-filterlib - $x 2>/dev/null > $x.filtered - ../../yosys-filterlib -verilogsim $x > $x.verilogsim - diff $x.filtered $x.filtered.ok - diff $x.verilogsim $x.verilogsim.ok - if [[ -e ${x%.lib}.log.ok ]]; then - ../../yosys -p "dfflibmap -info -liberty ${x}" -TqqQl ${x%.lib}.log - diff ${x%.lib}.log ${x%.lib}.log.ok - fi -done - -for x in *.ys; do - echo "Running $x.." - ../../yosys -q -s $x -l ${x%.ys}.log -done - diff --git a/tests/memfile/generate_mk.py b/tests/memfile/generate_mk.py new file mode 100644 index 000000000..e6351bc51 --- /dev/null +++ b/tests/memfile/generate_mk.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +def create_tests(): + setup = "mkdir -p temp && cp content1.dat temp/content2.dat" + + gen_tests_makefile.generate_cmd_test("parent_content1", [ + f"{setup}", + 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v; ' + 'chparam -set MEMFILE \\"content1.dat\\" memory"' + ]) + + gen_tests_makefile.generate_cmd_test("parent_content2_temp", [ + f"{setup}", + 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v; ' + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' + ]) + + gen_tests_makefile.generate_cmd_test("parent_content2_full", [ + f"{setup}", + 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v; ' + 'chparam -set MEMFILE \\"memfile/temp/content2.dat\\" memory"' + ]) + + gen_tests_makefile.generate_cmd_test("same_content1", [ + f"{setup}", + '$(YOSYS) -qp "read_verilog -defer memory.v; ' + 'chparam -set MEMFILE \\"content1.dat\\" memory"' + ]) + + gen_tests_makefile.generate_cmd_test("same_content2", [ + f"{setup}", + '$(YOSYS) -qp "read_verilog -defer memory.v; ' + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' + ]) + + gen_tests_makefile.generate_cmd_test("child_content1", [ + f"{setup}", + 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v; ' + 'chparam -set MEMFILE \\"content1.dat\\" memory"' + ]) + + gen_tests_makefile.generate_cmd_test("child_content2_temp", [ + f"{setup}", + 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v; ' + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' + ]) + + gen_tests_makefile.generate_cmd_test("child_content2_direct", [ + f"{setup}", + 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v; ' + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' + ]) + + gen_tests_makefile.generate_cmd_test("fail_empty_filename", + '! $(YOSYS) -qp "read_verilog memory.v"') + + gen_tests_makefile.generate_cmd_test("fail_missing_file", [ + '! $(YOSYS) -qp "read_verilog -defer memory.v; ' + 'chparam -set MEMFILE \\"content3.dat\\" memory"' + ]) + +extra = ["YOSYS_ABS := $(abspath $(YOSYS))"] +gen_tests_makefile.generate_custom(create_tests, extra) diff --git a/tests/memfile/run-test.sh b/tests/memfile/run-test.sh deleted file mode 100755 index 44c1e4821..000000000 --- a/tests/memfile/run-test.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -mkdir -p temp -cp content1.dat temp/content2.dat - -cd .. - -echo "Running from the parent directory with content1.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"content1.dat\" memory" -echo "Running from the parent directory with temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" -echo "Running from the parent directory with memfile/temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"memfile/temp/content2.dat\" memory" - -cd memfile - -echo "Running from the same directory with content1.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content1.dat\" memory" -echo "Running from the same directory with temp/content2.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" - -cd temp - -echo "Running from a child directory with content1.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"content1.dat\" memory" -echo "Running from a child directory with temp/content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" -echo "Running from a child directory with content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" - -cd .. - -echo "Checking a failure when zero length filename is provided" -if ../../yosys -qp "read_verilog memory.v"; then - echo "The execution should fail but it didn't happen, which is WRONG." - exit 1 -else - echo "Execution failed, which is OK." -fi - -echo "Checking a failure when not existing filename is provided" -if ../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content3.dat\" memory"; then - echo "The execution should fail but it didn't happen, which is WRONG." - exit 1 -else - echo "Execution failed, which is OK." -fi diff --git a/tests/memlib/generate.py b/tests/memlib/generate_mk.py similarity index 96% rename from tests/memlib/generate.py rename to tests/memlib/generate_mk.py index 46eff6b43..5f846a573 100644 --- a/tests/memlib/generate.py +++ b/tests/memlib/generate_mk.py @@ -1,3 +1,9 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") +import gen_tests_makefile + # TODO: # - priority logic @@ -319,8 +325,8 @@ if (OFFSET > 0) begin always @(mem_read, subaddr_r) rd <= mem_read[subaddr_r*RDBITS+:RDBITS]; -end -else +end +else begin always @(posedge clk) case (OFFSET) @@ -970,7 +976,7 @@ for (abits, wbits, words, defs, cells) in [ name, ENABLES.format(abits=abits, wbits=wbits, words=words), ["wren"], defs, cells )) - + # abits/dbits determination (aka general geometry picking) GEOMETRIC = """ module top(clk, rwa, rd, wd, we); @@ -991,7 +997,7 @@ always @(posedge clk) if (we) mem[rwa] <= wd; else - rd <= mem[rwa]; + rd <= mem[rwa]; endmodule """ @@ -1372,7 +1378,7 @@ for (abits, wbits, rwords, cntquad, cntoct) in [ (4, 2, 4, 1, 1), (4, 2, 5, 2, 1), (4, 2, 6, 2, 1), - (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read + (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read (4, 2, 8, 3, 1), # ports per quad port LUT (i.e. 7 ports in 2, 8 ports in 3) (4, 2, 9, 3, 2), (4, 4, 1, 2, 2), @@ -1440,7 +1446,7 @@ for (testname, reset_gate, rdwr, clk_en, add_logic) in [ write = "if (wren) \n\t\tmem[addr] <= wdata;" if rdwr == "new": - read = """if (rden) + read = """if (rden) if (wren) rdata <= wdata; else @@ -1466,7 +1472,7 @@ end""" TESTS.append(Test( testname, PRIORITY.format(code=code, abits=4, wbits=8, words=2), - ["block_sp_full"], ["USE_SRST"], + ["block_sp_full"], ["USE_SRST"], {"RAM_BLOCK_SP": 1, "$*": add_logic} )) @@ -1510,10 +1516,10 @@ end""" TESTS.append(Test( testname, PRIORITY.format(code=code, abits=4, wbits=1, words=2), - ["block_sp_full"], defs, + ["block_sp_full"], defs, {"RAM_BLOCK_SP": 1, "$*": add_logic} )) - + ROM_CASE = """ module rom(input clk, input [2:0] addr, {attr}output reg [7:0] data); @@ -1536,44 +1542,50 @@ endmodule TESTS.append(Test("rom_case", ROM_CASE.format(attr=""), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 0})) TESTS.append(Test("rom_case_block", ROM_CASE.format(attr="(* rom_style = \"block\" *) "), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 1})) -with open("run-test.mk", "w") as mf: - mf.write("ifneq ($(strip $(SEED)),)\n") - mf.write("SEEDOPT=-S$(SEED)\n") - mf.write("endif\n") - mf.write("all:") - for t in TESTS: - mf.write(" " + t.name) - mf.write("\n") - mf.write(".PHONY: all\n") - - for t in TESTS: - with open("t_{}.v".format(t.name), "w") as tf: - tf.write(t.src) - with open("t_{}.ys".format(t.name), "w") as sf: - sf.write("proc\n") - sf.write("opt\n") - sf.write("opt -full\n") - sf.write("memory -nomap\n") - sf.write("dump\n") - sf.write("memory_libmap") - for lib in t.libs: - sf.write(" -lib ../memlib_{}.txt".format(lib)) - for d in t.defs: - sf.write(" -D {}".format(d)) - sf.write("\n") - sf.write("memory_map\n") - for k, v in t.cells.items(): - if isinstance(v, tuple): - (cc, ca) = v - sf.write("select -assert-count {} t:{}\n".format(cc, k)) - for kk, vv in ca.items(): - sf.write("select -assert-count {} t:{} r:{}={} %i\n".format(cc, k, kk, vv)) - else: - sf.write("select -assert-count {} t:{}\n".format(v, k)) - mf.write("{}:\n".format(t.name)) - mf.write("\t@../tools/autotest.sh -G -j $(SEEDOPT) $(EXTRA_FLAGS) -p 'script ../t_{}.ys'".format(t.name)) +for t in TESTS: + with open("t_{}.v".format(t.name), "w") as tf: + tf.write(t.src) + with open("t_{}.ys".format(t.name), "w") as sf: + sf.write("proc\n") + sf.write("opt\n") + sf.write("opt -full\n") + sf.write("memory -nomap\n") + sf.write("dump\n") + sf.write("memory_libmap") for lib in t.libs: - mf.write(" -l memlib_{}.v".format(lib)) - mf.write(" t_{}.v || (cat t_{}.err; exit 1)\n".format(t.name, t.name)) - mf.write(".PHONY: {}\n".format(t.name)) + sf.write(" -lib ../memlib_{}.txt".format(lib)) + for d in t.defs: + sf.write(" -D {}".format(d)) + sf.write("\n") + sf.write("memory_map\n") + for k, v in t.cells.items(): + if isinstance(v, tuple): + (cc, ca) = v + sf.write("select -assert-count {} t:{}\n".format(cc, k)) + for kk, vv in ca.items(): + sf.write("select -assert-count {} t:{} r:{}={} %i\n".format(cc, k, kk, vv)) + else: + sf.write("select -assert-count {} t:{}\n".format(v, k)) + +def create_tests(): + for t in TESTS: + libs_args = "" + for lib in t.libs: + libs_args += f" -l memlib_{lib}.v" + cmd = ( + f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} " + f"-p 'script ../t_{t.name}.ys'" + f"{libs_args} " + f"t_{t.name}.v || (cat t_{t.name}.err; exit 1)" + ) + gen_tests_makefile.generate_target(t.name, cmd) + +extra = [ + "SEED ?=", + "ifneq ($(strip $(SEED)),)", + " SEEDOPT=-S$(SEED)", + "endif", +] +gen_tests_makefile.generate_custom(create_tests, extra) + diff --git a/tests/memlib/run-test.sh b/tests/memlib/run-test.sh deleted file mode 100755 index 9e95fb255..000000000 --- a/tests/memlib/run-test.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -eu - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) seed="$OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -python3 generate.py -exec ${MAKE:-make} -f run-test.mk SEED="$seed" diff --git a/tests/memories/generate_mk.py b/tests/memories/generate_mk.py new file mode 100644 index 000000000..cfb29acb9 --- /dev/null +++ b/tests/memories/generate_mk.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.v", "", +"""if grep -Eq 'expect-(wr-ports|rd-ports|rd-clk)' $@; then \\ + $(YOSYS) -f verilog -qp "proc; opt; memory -nomap; dump -outfile $(@:.v=).dmp t:\\$$mem_v2" $@; \\ + if grep -q expect-wr-ports $@; then \\ + val=$$(gawk '/expect-wr-ports/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\WR_PORTS $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected number of write ports."; exit 1; }; \\ + fi; \\ + if grep -q expect-wr-wide-continuation $@; then \\ + val=$$(gawk '/expect-wr-wide-continuation/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\WR_WIDE_CONTINUATION $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected write wide continuation."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-ports $@; then \\ + val=$$(gawk '/expect-rd-ports/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_PORTS $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected number of read ports."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-clk $@; then \\ + val=$$(gawk '/expect-rd-clk/ { print $$3; }' $@); \\ + grep -Fq "connect \\\\RD_CLK $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read clock."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-en $@; then \\ + val=$$(gawk '/expect-rd-en/ { print $$3; }' $@); \\ + grep -Fq "connect \\\\RD_EN $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read enable."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-srst-sig $@; then \\ + val=$$(gawk '/expect-rd-srst-sig/ { print $$3; }' $@); \\ + grep -Fq "connect \\\\RD_SRST $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read sync reset."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-srst-val $@; then \\ + val=$$(gawk '/expect-rd-srst-val/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_SRST_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read sync reset value."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-arst-sig $@; then \\ + val=$$(gawk '/expect-rd-arst-sig/ { print $$3; }' $@); \\ + grep -Fq "connect \\\\RD_ARST $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read async reset."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-arst-val $@; then \\ + val=$$(gawk '/expect-rd-arst-val/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_ARST_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read async reset value."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-init-val $@; then \\ + val=$$(gawk '/expect-rd-init-val/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_INIT_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read init value."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-wide-continuation $@; then \\ + val=$$(gawk '/expect-rd-wide-continuation/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_WIDE_CONTINUATION $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read wide continuation."; exit 1; }; \\ + fi; \\ + if grep -q expect-no-rd-clk $@; then \\ + grep -Fq "connect \\\\RD_CLK 1'x" $(@:.v=).dmp || { echo " ERROR: Expected no read clock."; exit 1; }; \\ + fi; \\ +fi""") diff --git a/tests/memories/run-test.sh b/tests/memories/run-test.sh deleted file mode 100755 index 8f83e11a1..000000000 --- a/tests/memories/run-test.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -OPTIND=1 -seed="" # default to no seed specified -abcopt="" -while getopts "A:S:" opt -do - case "$opt" in - A) abcopt="-A $OPTARG" ;; - S) seed="$OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -${MAKE:-make} -f ../tools/autotest.mk SEED="$seed" EXTRA_FLAGS="$abcopt" *.v - -for f in `egrep -l 'expect-(wr-ports|rd-ports|rd-clk)' *.v`; do - echo -n "Testing expectations for $f .." - ../../yosys -f verilog -qp "proc; opt; memory -nomap;; dump -outfile ${f%.v}.dmp t:\$mem_v2" $f - if grep -q expect-wr-ports $f; then - grep -q "parameter \\\\WR_PORTS $(gawk '/expect-wr-ports/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected number of write ports."; false; } - fi - if grep -q expect-wr-wide-continuation $f; then - grep -q "parameter \\\\WR_WIDE_CONTINUATION $(gawk '/expect-wr-wide-continuation/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected write wide continuation."; false; } - fi - if grep -q expect-rd-ports $f; then - grep -q "parameter \\\\RD_PORTS $(gawk '/expect-rd-ports/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected number of read ports."; false; } - fi - if grep -q expect-rd-clk $f; then - grep -q "connect \\\\RD_CLK \\$(gawk '/expect-rd-clk/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read clock."; false; } - fi - if grep -q expect-rd-en $f; then - grep -q "connect \\\\RD_EN \\$(gawk '/expect-rd-en/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read enable."; false; } - fi - if grep -q expect-rd-srst-sig $f; then - grep -q "connect \\\\RD_SRST \\$(gawk '/expect-rd-srst-sig/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read sync reset."; false; } - fi - if grep -q expect-rd-srst-val $f; then - grep -q "parameter \\\\RD_SRST_VALUE $(gawk '/expect-rd-srst-val/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read sync reset value."; false; } - fi - if grep -q expect-rd-arst-sig $f; then - grep -q "connect \\\\RD_ARST \\$(gawk '/expect-rd-arst-sig/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read async reset."; false; } - fi - if grep -q expect-rd-arst-val $f; then - grep -q "parameter \\\\RD_ARST_VALUE $(gawk '/expect-rd-arst-val/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read async reset value."; false; } - fi - if grep -q expect-rd-init-val $f; then - grep -q "parameter \\\\RD_INIT_VALUE $(gawk '/expect-rd-init-val/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read init value."; false; } - fi - if grep -q expect-rd-wide-continuation $f; then - grep -q "parameter \\\\RD_WIDE_CONTINUATION $(gawk '/expect-rd-wide-continuation/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read wide continuation."; false; } - fi - if grep -q expect-no-rd-clk $f; then - grep -q "connect \\\\RD_CLK 1'x\$" ${f%.v}.dmp || - { echo " ERROR: Expected no read clock."; false; } - fi - echo " ok." -done - diff --git a/tests/opt/generate_mk.py b/tests/opt/generate_mk.py new file mode 100644 index 000000000..4c31c5a2b --- /dev/null +++ b/tests/opt/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--tcl-scripts"]) diff --git a/tests/opt/run-test.sh b/tests/opt/run-test.sh deleted file mode 100755 index 1d1d9b7a6..000000000 --- a/tests/opt/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --tcl-scripts diff --git a/tests/opt_share/.gitignore b/tests/opt_share/.gitignore index 9c595a6fb..90ea6e92a 100644 --- a/tests/opt_share/.gitignore +++ b/tests/opt_share/.gitignore @@ -1 +1 @@ -temp +uut_*.* diff --git a/tests/opt_share/generate.py b/tests/opt_share/generate_mk.py similarity index 61% rename from tests/opt_share/generate.py rename to tests/opt_share/generate_mk.py index 2ec92f7de..0d7e494e9 100644 --- a/tests/opt_share/generate.py +++ b/tests/opt_share/generate_mk.py @@ -1,48 +1,42 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import argparse import sys import random -from contextlib import contextmanager - - -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target - +from pathlib import Path def random_plus_x(): return "%s x" % random.choice(['+', '+', '+', '-', '-', '|', '&', '^']) - def maybe_plus_x(expr): if random.randint(0, 4) == 0: return "(%s %s)" % (expr, random_plus_x()) else: return expr - -parser = argparse.ArgumentParser( - formatter_class=argparse.ArgumentDefaultsHelpFormatter) -parser.add_argument('-S', '--seed', type=int, help='seed for PRNG') -parser.add_argument('-c', - '--count', - type=int, - default=100, - help='number of test cases to generate') +parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) +parser.add_argument('-S', '--seed', type = int, help = 'seed for PRNG') +parser.add_argument('-c', '--count', type = int, default = 100, help = 'number of test cases to generate') args = parser.parse_args() -if args.seed is not None: - print("PRNG seed: %d" % args.seed) - random.seed(args.seed) +seed = args.seed +if seed is None: + seed = random.randrange(sys.maxsize) +print("opt_share PRNG seed: %d" % seed) +random.seed(seed) + +for path in Path(".").glob("uut_*.*"): + if path.is_file(): + path.unlink() for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): print('module uut_%05d(a, b, c, s, y);' % (idx)) op = random.choice([ random.choice(['+', '-', '*', '/', '%']), @@ -67,20 +61,20 @@ for idx in range(args.count): cast2, ops2[0], op, ops2[1])) print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): - print('read_verilog temp/uut_%05d.v' % idx) + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): + print('read_verilog uut_%05d.v' % idx) print('proc;;') print('copy uut_%05d gold' % idx) print('rename uut_%05d gate' % idx) - print('tee -a temp/all_share_log.txt log') - print('tee -a temp/all_share_log.txt log #job# uut_%05d' % idx) - print('tee -a temp/all_share_log.txt opt gate') - print('tee -a temp/all_share_log.txt opt_share gate') - print('tee -a temp/all_share_log.txt opt_clean gate') + print('tee -o uut_%05d.txt opt gate' % idx) + print('tee -o uut_%05d.txt opt_share gate' % idx) + print('tee -o uut_%05d.txt opt_clean gate' % idx) print( 'miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter' ) print( 'sat -set-def-inputs -verify -prove trigger 0 -show-inputs -show-outputs miter' ) + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/opt_share/run-test.sh b/tests/opt_share/run-test.sh deleted file mode 100755 index e3a6e8b7b..000000000 --- a/tests/opt_share/run-test.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=100 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -{ - echo ".PHONY: all" - echo "all:" - - for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do - idx=$( printf "%05d" $i ) - echo ".PHONY: test-$idx" - echo "all: test-$idx" - echo "test-$idx:" - printf "\t@%s\n" \ - "echo -n [$i]" \ - "../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys" - done -} > temp/makefile - -echo "running tests.." -${MAKE:-make} -f temp/makefile -echo - -failed_share=$( echo $( gawk '/^#job#/ { j=$2; db[j]=0; } /^Removing [246] cells/ { delete db[j]; } END { for (j in db) print(j); }' temp/all_share_log.txt ) ) -if [ -n "$failed_share" ]; then - echo "Resource sharing failed for the following test cases: $failed_share" - false -fi - -exit 0 diff --git a/tests/peepopt/generate_mk.py b/tests/peepopt/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/peepopt/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/peepopt/run-test.sh b/tests/peepopt/run-test.sh deleted file mode 100644 index 2e3f5235c..000000000 --- a/tests/peepopt/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done diff --git a/tests/proc/generate_mk.py b/tests/proc/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/proc/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/proc/run-test.sh b/tests/proc/run-test.sh deleted file mode 100755 index 2e3f5235c..000000000 --- a/tests/proc/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done diff --git a/tests/pyosys/test_design_run_pass.py b/tests/pyosys/test_design_run_pass.py index 6e31a7f1c..f0013577d 100644 --- a/tests/pyosys/test_design_run_pass.py +++ b/tests/pyosys/test_design_run_pass.py @@ -13,6 +13,8 @@ base.run_pass("equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5") postopt = ys.Design() postopt.run_pass("design -load postopt") postopt.run_pass(["cd", "top"]) -postopt.run_pass("select -assert-min 11 t:LUT4") -postopt.run_pass(["select", "-assert-count", "2", "t:PFUMX"]) -postopt.run_pass("select -assert-none t:LUT4 t:PFUMX %% t:* %D") +postopt.run_pass("select -assert-min 25 t:LUT4") +postopt.run_pass("select -assert-max 26 t:LUT4") +postopt.run_pass(["select", "-assert-count", "10", "t:PFUMX"]) +postopt.run_pass(["select", "-assert-count", "6", "t:L6MUX21"]) +postopt.run_pass("select -assert-none t:LUT4 t:PFUMX t:L6MUX21 %% t:* %D") diff --git a/tests/pyosys/test_ecp5_addsub.py b/tests/pyosys/test_ecp5_addsub.py index 96258e3ba..ddc50b775 100644 --- a/tests/pyosys/test_ecp5_addsub.py +++ b/tests/pyosys/test_ecp5_addsub.py @@ -13,6 +13,8 @@ ys.run_pass("equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5", base) postopt = ys.Design() ys.run_pass("design -load postopt", postopt) ys.run_pass("cd top", postopt) -ys.run_pass("select -assert-min 11 t:LUT4", postopt) -ys.run_pass("select -assert-count 2 t:PFUMX", postopt) -ys.run_pass("select -assert-none t:LUT4 t:PFUMX %% t:* %D", postopt) +ys.run_pass("select -assert-min 25 t:LUT4", postopt) +ys.run_pass("select -assert-max 26 t:LUT4", postopt) +ys.run_pass("select -assert-count 10 t:PFUMX", postopt) +ys.run_pass("select -assert-count 6 t:L6MUX21", postopt) +ys.run_pass("select -assert-none t:LUT4 t:PFUMX t:L6MUX21 %% t:* %D", postopt) diff --git a/tests/realmath/.gitignore b/tests/realmath/.gitignore index 9c595a6fb..941856205 100644 --- a/tests/realmath/.gitignore +++ b/tests/realmath/.gitignore @@ -1 +1 @@ -temp +uut_* diff --git a/tests/realmath/generate.py b/tests/realmath/generate_mk.py similarity index 77% rename from tests/realmath/generate.py rename to tests/realmath/generate_mk.py index 2bedf38e4..bee55816e 100644 --- a/tests/realmath/generate.py +++ b/tests/realmath/generate_mk.py @@ -1,17 +1,12 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") +import gen_tests_makefile import argparse import sys import random -from contextlib import contextmanager -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target def random_expression(depth = 3, maxparam = 0): def recursion(): @@ -42,13 +37,15 @@ parser.add_argument('-S', '--seed', type = int, help = 'seed for PRNG') parser.add_argument('-c', '--count', type = int, default = 100, help = 'number of test cases to generate') args = parser.parse_args() -if args.seed is not None: - print("PRNG seed: %d" % args.seed) - random.seed(args.seed) +seed = args.seed +if seed is None: + seed = random.randrange(sys.maxsize) +print("realmath PRNG seed: %d" % seed) +random.seed(seed) for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): print('module uut_%05d(output [63:0] %s);\n' % (idx, ', '.join(['y%02d' % i for i in range(100)]))) for i in range(30): if idx < 10: @@ -63,13 +60,13 @@ for idx in range(args.count): for i in range(100): print('assign y%02d = 65536 * (%s);' % (i, random_expression(maxparam = 60))) print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): print('read_verilog uut_%05d.v' % idx) print('rename uut_%05d uut_%05d_syn' % (idx, idx)) print('write_verilog uut_%05d_syn.v' % idx) - with open('temp/uut_%05d_tb.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d_tb.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): print('module uut_%05d_tb;\n' % idx) print('wire [63:0] %s;' % (', '.join(['r%02d' % i for i in range(100)]))) print('wire [63:0] %s;' % (', '.join(['s%02d' % i for i in range(100)]))) @@ -99,3 +96,20 @@ for idx in range(args.count): print('end') print('endmodule') + +def create_tests(): + for idx in range(args.count): + cmd = [ + f"$(YOSYS) -qq uut_{idx:05d}.ys", + f"iverilog -o uut_{idx:05d}_tb uut_{idx:05d}_tb.v uut_{idx:05d}.v uut_{idx:05d}_syn.v", + f"./uut_{idx:05d}_tb" +# f"./uut_{idx:05d}_tb | tee uut_{idx:05d}.err;", +# f"if test -s uut_{idx:05d}.err; then", +# " echo \"Note: Make sure that iverilog is an up-to-date git checkout of Icarus Verilog.\";", +# " exit 1;", +# "fi;", +# f"rm -f uut_{idx:05d}.err" + ] + gen_tests_makefile.generate_cmd_test(f"uut_{idx:05d}", cmd) + +gen_tests_makefile.generate_custom(create_tests) diff --git a/tests/realmath/run-test.sh b/tests/realmath/run-test.sh deleted file mode 100755 index 833e8c3f4..000000000 --- a/tests/realmath/run-test.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -set -e - -OPTIND=1 -count=100 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -cd temp -echo "running tests.." -for ((i = 0; i < $count; i++)); do - echo -n "[$i]" - idx=$( printf "%05d" $i ) - ../../../yosys -qq uut_${idx}.ys - iverilog -o uut_${idx}_tb uut_${idx}_tb.v uut_${idx}.v uut_${idx}_syn.v - ./uut_${idx}_tb | tee uut_${idx}.err - if test -s uut_${idx}.err; then - echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." - exit 1 - fi - rm -f uut_${idx}.err -done -echo - diff --git a/tests/rpc/generate_mk.py b/tests/rpc/generate_mk.py new file mode 100644 index 000000000..aca802ebe --- /dev/null +++ b/tests/rpc/generate_mk.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile +import glob + +def create_tests(): + yss = sorted(glob.glob("*.ys")) + for ys in yss: + gen_tests_makefile.generate_ys_test(ys) + + cmd = [ "python3 frontend.py unix-socket frontend.sock" ] + gen_tests_makefile.generate_cmd_test("frontend.py", cmd) + +gen_tests_makefile.generate_custom(create_tests) diff --git a/tests/rpc/run-test.sh b/tests/rpc/run-test.sh deleted file mode 100755 index 0d58b0de2..000000000 --- a/tests/rpc/run-test.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done -python3 frontend.py unix-socket frontend.sock diff --git a/tests/rtlil/generate_mk.py b/tests/rtlil/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/rtlil/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"]) diff --git a/tests/rtlil/run-test.sh b/tests/rtlil/run-test.sh deleted file mode 100755 index 83cdf8aeb..000000000 --- a/tests/rtlil/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --bash --yosys-scripts diff --git a/tests/sat/generate_mk.py b/tests/sat/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/sat/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/sat/run-test.sh b/tests/sat/run-test.sh deleted file mode 100755 index 006c731e3..000000000 --- a/tests/sat/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts diff --git a/tests/sdc/generate_mk.py b/tests/sdc/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/sdc/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"]) diff --git a/tests/sdc/run-test.sh b/tests/sdc/run-test.sh deleted file mode 100755 index 971664bdb..000000000 --- a/tests/sdc/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash \ No newline at end of file diff --git a/tests/select/generate_mk.py b/tests/select/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/select/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/select/run-test.sh b/tests/select/run-test.sh deleted file mode 100755 index 2e3f5235c..000000000 --- a/tests/select/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done diff --git a/tests/share/.gitignore b/tests/share/.gitignore index 9c595a6fb..90ea6e92a 100644 --- a/tests/share/.gitignore +++ b/tests/share/.gitignore @@ -1 +1 @@ -temp +uut_*.* diff --git a/tests/share/generate.py b/tests/share/generate_mk.py similarity index 80% rename from tests/share/generate.py rename to tests/share/generate_mk.py index 7e87bd648..6a40758e1 100644 --- a/tests/share/generate.py +++ b/tests/share/generate_mk.py @@ -1,17 +1,14 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import argparse import sys import random -from contextlib import contextmanager - -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target +from pathlib import Path def random_plus_x(): return "%s x" % random.choice(['+', '+', '+', '-', '-', '|', '&', '^']) @@ -27,13 +24,19 @@ parser.add_argument('-S', '--seed', type = int, help = 'seed for PRNG') parser.add_argument('-c', '--count', type = int, default = 100, help = 'number of test cases to generate') args = parser.parse_args() -if args.seed is not None: - print("PRNG seed: %d" % args.seed) - random.seed(args.seed) +seed = args.seed +if seed is None: + seed = random.randrange(sys.maxsize) +print("share PRNG seed: %d" % seed) +random.seed(seed) + +for path in Path(".").glob("uut_*.*"): + if path.is_file(): + path.unlink() for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): if random.choice(['bin', 'uni']) == 'bin': print('module uut_%05d(a, b, c, d, x, s, y);' % (idx)) op = random.choice([ @@ -67,16 +70,16 @@ for idx in range(args.count): random.choice(['', '$signed', '$unsigned']), op, maybe_plus_x('b'), random_plus_x() if random.randint(0, 4) == 0 else '')) print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): - print('read_verilog temp/uut_%05d.v' % idx) - print('proc;;') + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): + print('read_verilog uut_%05d.v' % idx) + print('proc -noopt;;') print('copy uut_%05d gold' % idx) print('rename uut_%05d gate' % idx) - print('tee -a temp/all_share_log.txt log') - print('tee -a temp/all_share_log.txt log #job# uut_%05d' % idx) - print('tee -a temp/all_share_log.txt wreduce') - print('tee -a temp/all_share_log.txt share -aggressive gate') + print('tee -o uut_%05d.txt wreduce' % idx) + print('tee -a uut_%05d.txt share -aggressive gate' % idx) print('miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter') print('sat -set-def-inputs -verify -prove trigger 0 -show-inputs -show-outputs miter') + print('! grep -q \'^Removing [246] cells\' uut_%05d.txt' % idx) +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/share/run-test.sh b/tests/share/run-test.sh deleted file mode 100755 index 0cef580a7..000000000 --- a/tests/share/run-test.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=100 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -echo "running tests.." -for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do - echo -n "[$i]" - idx=$( printf "%05d" $i ) - ../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys -done -echo - -failed_share=$( echo $( gawk '/^#job#/ { j=$2; db[j]=0; } /^Removing [246] cells/ { delete db[j]; } END { for (j in db) print(j); }' temp/all_share_log.txt ) ) -if [ -n "$failed_share" ]; then - echo "Resource sharing failed for the following test cases: $failed_share" - false -fi - -exit 0 diff --git a/tests/sim/generate_mk.py b/tests/sim/generate_mk.py new file mode 100644 index 000000000..57138762d --- /dev/null +++ b/tests/sim/generate_mk.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +import subprocess +from pathlib import Path + +print("Generate FST for sim models") + +for name in Path("tb").rglob("tb*.v"): + test_name = name.stem + print(f"Test {test_name}") + + verilog_name = f"{test_name[3:]}.v" + + out_file = Path("tb") / f"{test_name}.out" + + subprocess.run( + ["iverilog", "-o", str(out_file), str(name), verilog_name], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True + ) + + subprocess.run( + [str(out_file), "-fst"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True + ) + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/sim/run-test.sh b/tests/sim/run-test.sh deleted file mode 100755 index 43571e057..000000000 --- a/tests/sim/run-test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -echo "Generate FST for sim models" -find tb/* -name tb*.v | while read name; do - test_name=$(basename $name .v) - echo "Test $test_name" - verilog_name=${test_name:3}.v - iverilog -o tb/$test_name.out $name $verilog_name - ./tb/$test_name.out -fst -done -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/simple/generate_mk.py b/tests/simple/generate_mk.py new file mode 100644 index 000000000..f8e79bcaf --- /dev/null +++ b/tests/simple/generate_mk.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import shutil + +# ---------------------- +# Check if iverilog is installed +# ---------------------- +if shutil.which("iverilog") is None: + print("Error: Icarus Verilog 'iverilog' not found.", file=sys.stderr) + sys.exit(1) + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.*v", "") diff --git a/tests/simple/run-test.sh b/tests/simple/run-test.sh deleted file mode 100755 index c3711fe3e..000000000 --- a/tests/simple/run-test.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -# check for Icarus Verilog -if ! command -v iverilog > /dev/null ; then - echo "$0: Error: Icarus Verilog 'iverilog' not found." - exit 1 -fi - -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.{sv,v} diff --git a/tests/simple_abc9/generate_mk.py b/tests/simple_abc9/generate_mk.py new file mode 100644 index 000000000..44dd7e2b4 --- /dev/null +++ b/tests/simple_abc9/generate_mk.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import shutil +import os +from pathlib import Path + +# ---------------------- +# Check if iverilog is installed +# ---------------------- +if shutil.which("iverilog") is None: + print("Error: Icarus Verilog 'iverilog' not found.", file=sys.stderr) + sys.exit(1) + +src_dir = Path("../simple") +# ---------------------- +# Copy all files from ../simple to current directory +# ---------------------- +for file in src_dir.glob("*.v"): + shutil.copy(file, os.path.join(".", file.name)) + +for file in src_dir.glob("*.sv"): + shutil.copy(file, os.path.join(".", file.name)) + +# bug 2675 +bug_file = os.path.join(".", "specify.v") +if os.path.exists(bug_file): + os.remove(bug_file) + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.*v", "-f \"verilog -noblackbox -specify\" -n 300 -p '\ + read_verilog -icells -lib +/abc9_model.v; \ + hierarchy; \ + synth -run coarse; \ + opt -full; \ + techmap; \ + abc9 -lut 4; \ + clean; \ + check -assert * abc9_test037 %d; \ + select -assert-none t:?_NOT_ t:?_AND_ %%; \ + setattr -mod -unset blackbox -unset whitebox =*'") diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh deleted file mode 100755 index 0b3e5061f..000000000 --- a/tests/simple_abc9/run-test.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -# check for Icarus Verilog -if ! command -v iverilog > /dev/null ; then - echo "$0: Error: Icarus Verilog 'iverilog' not found." - exit 1 -fi - -for file in `ls *.v *.sv`; do - if [ ! -f "../simple/$file" -a "$file" != "abc9.v" ]; then - echo "Warning: $file is in simple_abc9/, but not in simple/" - backup="$file.bak" - if [ -f "$backup" ]; then - if cmp "$file" "$backup" > /dev/null; then - echo " => $backup already exists and matches; removing $file" - rm "$file" - else - echo " => $backup already exists but differs; leaving $file in place" - fi - else - echo " => moving $file to $backup" - mv -i "$file" "$backup" - fi - fi -done - -cp ../simple/*.v . -cp ../simple/*.sv . -rm specify.v # bug 2675 -DOLLAR='?' -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-f \"verilog -noblackbox -specify\" -n 300 -p '\ - read_verilog -icells -lib +/abc9_model.v; \ - hierarchy; \ - synth -run coarse; \ - opt -full; \ - techmap; \ - abc9 -lut 4; \ - clean; \ - check -assert * abc9_test037 %d; \ - select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \ - setattr -mod -unset blackbox -unset whitebox =*'" - -# NOTE: Skip 'check -assert' on abc9_test037 because it intentionally has a combinatorial loop diff --git a/tests/svinterfaces/generate_mk.py b/tests/svinterfaces/generate_mk.py new file mode 100644 index 000000000..4703e9c9e --- /dev/null +++ b/tests/svinterfaces/generate_mk.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +from pathlib import Path +import glob +import sys +sys.path.append("..") + +import gen_tests_makefile + +runone_tests = [ + "svinterface1", + #"svinterface_at_top" +] + +def run_one(): + for testname in runone_tests: + cmd_lines = [ + f'$(YOSYS) -p "read_verilog -sv {testname}.sv ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr', + f'$(YOSYS) -p "read_verilog -sv {testname}_ref.v ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_ref_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr', + f'rm -f a.out reference_result.txt dut_result.txt', + f'iverilog -g2012 {testname}_syn.v', + f'iverilog -g2012 {testname}_ref_syn.v', + f'iverilog -g2012 {testname}_tb.v {testname}_ref_syn.v', + f'./a.out', + f'mv output.txt reference_result.txt', + f'iverilog -g2012 {testname}_tb_wrapper.v {testname}_syn.v' if testname=="svinterface_at_top" else + f'iverilog -g2012 {testname}_tb.v {testname}_syn.v', + f'./a.out', + f'mv output.txt dut_result.txt', + f'diff reference_result.txt dut_result.txt > {testname}.diff', + ] + gen_tests_makefile.generate_cmd_test(testname, cmd_lines) + +def run_simple(): + for f in sorted(glob.glob("*.ys")): + gen_tests_makefile.generate_ys_test(f) + +def main(): + def callback(): + run_one() + run_simple() + + gen_tests_makefile.generate_custom(callback) + +if __name__ == "__main__": + main() diff --git a/tests/svinterfaces/run-test.sh b/tests/svinterfaces/run-test.sh deleted file mode 100755 index 28ce627d9..000000000 --- a/tests/svinterfaces/run-test.sh +++ /dev/null @@ -1,9 +0,0 @@ -#/bin/bash -e -source ../common-env.sh - -./runone.sh svinterface1 -./runone.sh svinterface_at_top - -./run_simple.sh load_and_derive -./run_simple.sh resolve_types -./run_simple.sh positional_args diff --git a/tests/svinterfaces/run_simple.sh b/tests/svinterfaces/run_simple.sh deleted file mode 100755 index 5bf044373..000000000 --- a/tests/svinterfaces/run_simple.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -# Run a simple test with a .ys file - -if [ $# != 1 ]; then - echo >&2 "Expected 1 argument" - exit 1 -fi - -echo -n "Test: $1 ->" -../../yosys $1.ys >$1.log_stdout 2>$1.log_stderr || { - echo "ERROR!" - exit 1 -} -echo "ok" diff --git a/tests/svinterfaces/runone.sh b/tests/svinterfaces/runone.sh deleted file mode 100755 index 2d6e0463d..000000000 --- a/tests/svinterfaces/runone.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - - -TESTNAME=$1 - -STDOUTFILE=${TESTNAME}.log_stdout -STDERRFILE=${TESTNAME}.log_stderr - -echo "" > $STDOUTFILE -echo "" > $STDERRFILE - -echo -n "Test: ${TESTNAME} -> " - -set -e - -$PWD/../../yosys -p "read_verilog -sv ${TESTNAME}.sv ; hierarchy -check -top TopModule ; synth ; write_verilog ${TESTNAME}_syn.v" >> $STDOUTFILE 2>> $STDERRFILE -$PWD/../../yosys -p "read_verilog -sv ${TESTNAME}_ref.v ; hierarchy -check -top TopModule ; synth ; write_verilog ${TESTNAME}_ref_syn.v" >> $STDOUTFILE 2>> $STDERRFILE - -rm -f a.out reference_result.txt dut_result.txt - -iverilog -g2012 ${TESTNAME}_syn.v -iverilog -g2012 ${TESTNAME}_ref_syn.v - -set +e -iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_ref_syn.v -./a.out -mv output.txt reference_result.txt -if [ -f ${TESTNAME}_wrapper.v ] ; then - iverilog -g2012 ${TESTNAME}_tb_wrapper.v ${TESTNAME}_syn.v -else - iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_syn.v -fi -./a.out -mv output.txt dut_result.txt - -diff reference_result.txt dut_result.txt > ${TESTNAME}.diff -RET=$? -if [ "$RET" != "0" ] ; then - echo "ERROR!" - exit -1 -fi - -echo "ok" -exit 0 diff --git a/tests/svtypes/array_assign.sv b/tests/svtypes/array_assign.sv index a5ca6363c..f23a08d27 100644 --- a/tests/svtypes/array_assign.sv +++ b/tests/svtypes/array_assign.sv @@ -84,4 +84,85 @@ module top; assert(pt_o[0] == 1'b0); assert(pt_o[1] == 1'b1); end + + // Test 9: Positional assignment pattern on a whole unpacked array + // Covers the parser and continuous assignment expansion path for `'{...}. + wire ap_table [1]; + wire ap_i = 1'b0; + wire ap_out; + assign ap_table = '{1'h1}; + assign ap_out = ap_table[ap_i > 1'h0 ? 1'h0 : ap_i]; + always_comb begin + assert(ap_out == 1'b1); + end + + // Test 10: Positional assignment pattern preserves left-to-right element order. + wire ap_order [2]; + assign ap_order = '{1'b0, 1'b1}; + always_comb begin + assert(ap_order[0] == 1'b0); + assert(ap_order[1] == 1'b1); + end + + function automatic logic ap_identity(input logic value); + ap_identity = value; + endfunction + + // Test 11: The first assignment pattern element is a runtime expression. + wire ap_runtime_in = 1'b1; + wire ap_runtime [2]; + assign ap_runtime = '{ap_identity(ap_runtime_in), 1'b0}; + always_comb begin + assert(ap_runtime[0] == 1'b1); + assert(ap_runtime[1] == 1'b0); + end + + // Test 12: Nested positional assignment pattern on a multidimensional array. + wire ap_nested [2][2]; + assign ap_nested = '{'{1'b1, 1'b0}, '{1'b0, 1'b1}}; + always_comb begin + assert(ap_nested[0][0] == 1'b1); + assert(ap_nested[0][1] == 1'b0); + assert(ap_nested[1][0] == 1'b0); + assert(ap_nested[1][1] == 1'b1); + end + + // Test 13: Multidimensional assignment pattern with row expressions. + wire ap_row0 [2]; + wire ap_row1 [2]; + wire ap_rows [2][2]; + assign ap_row0 = '{1'b1, 1'b0}; + assign ap_row1 = '{1'b0, 1'b1}; + assign ap_rows = '{ap_row0, ap_row1}; + always_comb begin + assert(ap_rows[0][0] == 1'b1); + assert(ap_rows[0][1] == 1'b0); + assert(ap_rows[1][0] == 1'b0); + assert(ap_rows[1][1] == 1'b1); + end + + // Test 14: Procedural blocking assignment pattern preserves RHS values. + logic ap_swap [2]; + always_comb begin + ap_swap[0] = 1'b0; + ap_swap[1] = 1'b1; + ap_swap = '{ap_swap[1], ap_swap[0]}; + + assert(ap_swap[0] == 1'b1); + assert(ap_swap[1] == 1'b0); + end + + // Test 15: Assignment pattern elements use the target element width context. + logic [4:0] ap_width_ctx [1]; + assign ap_width_ctx = '{4'hf + 4'h1}; + always_comb begin + assert(ap_width_ctx[0] == 5'h10); + end + + // Test 16: Nested assignment pattern elements also use the target element width context. + logic [4:0] ap_nested_width_ctx [1][1]; + assign ap_nested_width_ctx = '{'{4'hf + 4'h1}}; + always_comb begin + assert(ap_nested_width_ctx[0][0] == 5'h10); + end endmodule diff --git a/tests/svtypes/array_assign_flat_multidim_pattern.ys b/tests/svtypes/array_assign_flat_multidim_pattern.ys new file mode 100644 index 000000000..a2e57e2f5 --- /dev/null +++ b/tests/svtypes/array_assign_flat_multidim_pattern.ys @@ -0,0 +1,10 @@ +logger -expect error "Assignment pattern element count mismatch: got 4, expected 2" 1 + +read_verilog -sv <&2 if [ ! -f "$toolsdir/cmp_tbdata" -o "$toolsdir/cmp_tbdata.c" -nt "$toolsdir/cmp_tbdata" ]; then - ( set -ex; ${CXX:-g++} -Wall -o "$toolsdir/cmp_tbdata" "$toolsdir/cmp_tbdata.c"; ) || exit 1 + ( set -ex; ${CXX:-g++} -Wall ${CPPFLAGS} ${CXXFLAGS:-} -o "$toolsdir/cmp_tbdata" "$toolsdir/cmp_tbdata.c"; ) || exit 1 fi +flock -u "$lock"; exec {lock}>&- while getopts xmGl:wkjvref:s:p:n:S:I:A:-: opt; do case "$opt" in @@ -148,7 +150,7 @@ do rm -f ${bn}_ref.fir if [[ "$ext" == "v" ]]; then - egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} + grep -Ev '^\s*`timescale' ../$fn > ${bn}_ref.${ext} elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then $abcprog -c "read_aiger ../${fn}; write ${bn}_ref.${refext}" else @@ -235,6 +237,7 @@ do echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi fi + sed -e "s,^,${bn}: ," ${bn}.err $keeprunning || exit 1 fi done diff --git a/tests/unit/kernel/rtlilHelpers.h b/tests/unit/kernel/rtlilHelpers.h new file mode 100644 index 000000000..99585f23b --- /dev/null +++ b/tests/unit/kernel/rtlilHelpers.h @@ -0,0 +1,71 @@ +#ifndef RTLIL_HELPERS_H +#define RTLIL_HELPERS_H + +#include + +#include "kernel/rtlil.h" + +YOSYS_NAMESPACE_BEGIN + +class SigSpecRepTest : public ::testing::Test { +protected: + Design* d; + Module* m; + + void SetUp() override { + d = new Design; + m = d->addModule("$test"); + } + + void TearDown() override { + delete d; + } + + // Create n wires with given width + std::vector createWires(int count, int width = 4) { + std::vector wires; + for (int i = 0; i < count; i++) { + Wire* w = m->addWire(stringf("$w%d", i), width); + wires.push_back(w); + } + return wires; + } + + // Append all wires to a SigSpec + SigSpec wiresAsSigSpec(const std::vector& wires) { + SigSpec sig; + for (auto w : wires) + sig.append(w); + return sig; + } + + // Create a SigSpec of constants + SigSpec constsAsSigSpec(int count, int width = 4) { + SigSpec sig; + for (int i = 0; i < count; i++) + sig.append(Const(i, width)); + return sig; + } + + // Convert wires to pool of SigBits + pool wiresToPool(const std::vector& wires) { + pool pool; + for (auto w : wires) + for (auto &bit : SigSpec(w)) + pool.insert(bit); + return pool; + } + + // Convert wires to set of SigBits + std::set wiresToSet(const std::vector& wires) { + std::set set; + for (auto w : wires) + for (auto &bit : SigSpec(w)) + set.insert(bit); + return set; + } +}; + +YOSYS_NAMESPACE_END + +#endif /* RTLIL_HELPERS_H */ diff --git a/tests/unit/kernel/sigspecExtractTest.cc b/tests/unit/kernel/sigspecExtractTest.cc new file mode 100644 index 000000000..87bd4f6da --- /dev/null +++ b/tests/unit/kernel/sigspecExtractTest.cc @@ -0,0 +1,89 @@ +#include + +#include "kernel/rtlil.h" +#include "tests/unit/kernel/rtlilHelpers.h" + +YOSYS_NAMESPACE_BEGIN + +namespace RTLIL { + TEST_F(SigSpecRepTest, Extract) + { + { + std::vector wires; + SigSpec sig; + for (int i = 0; i < 4; i++) + wires.push_back(m->addWire(stringf("$w%d", i), 4)); + for (auto w : wires) + sig.append(w); + + SigSpec extractedFirst = sig.extract(0, 4); + SigSpec extractedSecond = sig.extract(4, 4); + SigSpec extractedLast = sig.extract(12, 4); + EXPECT_EQ(extractedFirst.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedSecond.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedLast.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedFirst.as_wire(), wires[0]); + EXPECT_EQ(extractedSecond.as_wire(), wires[1]); + EXPECT_EQ(extractedLast.as_wire(), wires[3]); + } + + { + std::vector consts; + SigSpec sig; + for (int i = 0; i < 4; i++) + consts.push_back(Const(i, 4)); + for (auto c : consts) + sig.append(c); + + SigSpec extractedFirst = sig.extract(0, 4); + SigSpec extractedSecond = sig.extract(4, 4); + SigSpec extractedLast = sig.extract(12, 4); + EXPECT_EQ(extractedFirst.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedSecond.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedLast.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedFirst, consts[0]); + EXPECT_EQ(extractedSecond, consts[1]); + EXPECT_EQ(extractedLast, consts[3]); + } + + { + SigSpec sig; + sig.append(Const(0, 4)); + Wire* w = m->addWire("$foo", 4); + sig.append(w); + sig.append(Const(15, 4)); + + SigSpec extractedFirst = sig.extract(0, 4); + SigSpec extractedSecond = sig.extract(4, 4); + SigSpec extractedLast = sig.extract(8, 4); + EXPECT_EQ(extractedFirst.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedSecond.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedLast.rep_, SigSpec::Representation::CHUNK); + + SigSpec extractedFirstTwo = sig.extract(0, 8); + EXPECT_EQ(extractedFirstTwo.rep_, SigSpec::Representation::BITS); + SigSpec extractedLastTwo = sig.extract(4, 8); + EXPECT_EQ(extractedLastTwo.rep_, SigSpec::Representation::BITS); + + EXPECT_EQ(extractedFirstTwo[0], State::S0); + EXPECT_EQ(extractedFirstTwo[1], State::S0); + EXPECT_EQ(extractedFirstTwo[2], State::S0); + EXPECT_EQ(extractedFirstTwo[3], State::S0); + EXPECT_EQ(extractedFirstTwo[4], SigBit(w, 0)); + EXPECT_EQ(extractedFirstTwo[5], SigBit(w, 1)); + EXPECT_EQ(extractedFirstTwo[6], SigBit(w, 2)); + EXPECT_EQ(extractedFirstTwo[7], SigBit(w, 3)); + + EXPECT_EQ(extractedLastTwo[0], SigBit(w, 0)); + EXPECT_EQ(extractedLastTwo[1], SigBit(w, 1)); + EXPECT_EQ(extractedLastTwo[2], SigBit(w, 2)); + EXPECT_EQ(extractedLastTwo[3], SigBit(w, 3)); + EXPECT_EQ(extractedLastTwo[4], State::S1); + EXPECT_EQ(extractedLastTwo[5], State::S1); + EXPECT_EQ(extractedLastTwo[6], State::S1); + EXPECT_EQ(extractedLastTwo[7], State::S1); + } + } +}; + +YOSYS_NAMESPACE_END diff --git a/tests/unit/kernel/sigspecRemove2Test.cc b/tests/unit/kernel/sigspecRemove2Test.cc index a6789c774..9d7bf4863 100644 --- a/tests/unit/kernel/sigspecRemove2Test.cc +++ b/tests/unit/kernel/sigspecRemove2Test.cc @@ -5,7 +5,7 @@ YOSYS_NAMESPACE_BEGIN // Test fixture with helper functions -class SigSpecRemove2Test : public ::testing::Test { +class SigSpecRepTest : public ::testing::Test { protected: Design* d; Module* m; @@ -64,7 +64,7 @@ protected: } }; -TEST_F(SigSpecRemove2Test, WithSigSpecPattern) +TEST_F(SigSpecRepTest, WithSigSpecPattern) { auto wires = createWires(4); SigSpec sig = wiresAsSigSpec(wires); @@ -84,7 +84,7 @@ TEST_F(SigSpecRemove2Test, WithSigSpecPattern) EXPECT_EQ(sig, expected); } -TEST_F(SigSpecRemove2Test, WithPoolPattern) +TEST_F(SigSpecRepTest, WithPoolPattern) { auto wires = createWires(3); SigSpec sig = wiresAsSigSpec(wires); @@ -103,7 +103,7 @@ TEST_F(SigSpecRemove2Test, WithPoolPattern) EXPECT_EQ(sig, expected); } -TEST_F(SigSpecRemove2Test, WithSetPattern) +TEST_F(SigSpecRepTest, WithSetPattern) { auto wires = createWires(3); SigSpec sig = wiresAsSigSpec(wires); @@ -122,7 +122,7 @@ TEST_F(SigSpecRemove2Test, WithSetPattern) EXPECT_EQ(sig, expected); } -TEST_F(SigSpecRemove2Test, ManyElements) +TEST_F(SigSpecRepTest, ManyElements) { const int num_wires = 100; auto wires = createWires(num_wires); @@ -146,7 +146,7 @@ TEST_F(SigSpecRemove2Test, ManyElements) } // Test remove2 with very large dataset to check scaling -TEST_F(SigSpecRemove2Test, VeryLargeScalingTest) +TEST_F(SigSpecRepTest, VeryLargeScalingTest) { const int num_wires = 50000; auto wires = createWires(num_wires); @@ -173,7 +173,7 @@ TEST_F(SigSpecRemove2Test, VeryLargeScalingTest) } // Test multiple sequential removals (simulates removeSignalFromCaseTree) -TEST_F(SigSpecRemove2Test, MultipleSequentialRemovals) +TEST_F(SigSpecRepTest, MultipleSequentialRemovals) { const int num_wires = 512; auto wires = createWires(num_wires); @@ -204,7 +204,7 @@ TEST_F(SigSpecRemove2Test, MultipleSequentialRemovals) } // Test remove2 with very large dataset to check scaling -TEST_F(SigSpecRemove2Test, PoolOverloadLargeDataset) +TEST_F(SigSpecRepTest, PoolOverloadLargeDataset) { const int num_wires = 50000; auto wires = createWires(num_wires, 1); @@ -228,7 +228,7 @@ TEST_F(SigSpecRemove2Test, PoolOverloadLargeDataset) } // Test set overload (same perf characteristics as pool) -TEST_F(SigSpecRemove2Test, SetOverloadLargeDataset) +TEST_F(SigSpecRepTest, SetOverloadLargeDataset) { const int num_wires = 50000; auto wires = createWires(num_wires, 1); @@ -252,7 +252,7 @@ TEST_F(SigSpecRemove2Test, SetOverloadLargeDataset) } // Worst case: remove almost all elements -TEST_F(SigSpecRemove2Test, RemoveAlmostAllElements) +TEST_F(SigSpecRepTest, RemoveAlmostAllElements) { const int num_wires = 10000; auto wires = createWires(num_wires, 1); @@ -269,7 +269,7 @@ TEST_F(SigSpecRemove2Test, RemoveAlmostAllElements) EXPECT_EQ(sig[0].wire, wires[num_wires - 1]); } -TEST_F(SigSpecRemove2Test, EmptyPattern) +TEST_F(SigSpecRepTest, EmptyPattern) { auto wires = createWires(1); SigSpec sig(wires[0]); @@ -285,7 +285,7 @@ TEST_F(SigSpecRemove2Test, EmptyPattern) } // Test that NULL wire bits (constants) are not removed -TEST_F(SigSpecRemove2Test, NullWireBitsStay) +TEST_F(SigSpecRepTest, NullWireBitsStay) { auto wires = createWires(1); SigSpec sig; @@ -309,7 +309,7 @@ TEST_F(SigSpecRemove2Test, NullWireBitsStay) EXPECT_EQ(sig, expected); } -TEST_F(SigSpecRemove2Test, PartialBitRemoval) +TEST_F(SigSpecRepTest, PartialBitRemoval) { Wire* w = m->addWire("$w1", 8); SigSpec sig(w); diff --git a/tests/various/.gitignore b/tests/various/.gitignore index 9296a04c0..1431c4096 100644 --- a/tests/various/.gitignore +++ b/tests/various/.gitignore @@ -9,3 +9,4 @@ /temp /smtlib2_module.smt2 /smtlib2_module-filtered.smt2 +/*.aig diff --git a/tests/various/ezcmdline_dummy_solver b/tests/various/ezcmdline_dummy_solver index db5b21b8e..d0377f9af 100755 --- a/tests/various/ezcmdline_dummy_solver +++ b/tests/various/ezcmdline_dummy_solver @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env sh # Dummy SAT solver for ezCmdlineSAT tests. # Accepts exactly two CNF shapes: # - SAT: p cnf 1 1; clause: "1 0" -> exits 10 with v 1 diff --git a/tests/various/generate_mk.py b/tests/various/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/various/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"]) diff --git a/tests/various/run-test.sh b/tests/various/run-test.sh deleted file mode 100755 index dee032827..000000000 --- a/tests/various/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/verific/generate_mk.py b/tests/verific/generate_mk.py new file mode 100644 index 000000000..c8c8c53c3 --- /dev/null +++ b/tests/verific/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"],["export ASAN_OPTIONS=halt_on_error=0"]) diff --git a/tests/verific/run-test.sh b/tests/verific/run-test.sh deleted file mode 100755 index 1666ee1f9..000000000 --- a/tests/verific/run-test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash -{ echo 'export ASAN_OPTIONS=halt_on_error=0'; cat run-test.mk; } > run-test.mk.tmp && mv run-test.mk.tmp run-test.mk diff --git a/tests/verilog/generate_mk.py b/tests/verilog/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/verilog/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"]) diff --git a/tests/verilog/run-test.sh b/tests/verilog/run-test.sh deleted file mode 100755 index dee032827..000000000 --- a/tests/verilog/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/xprop/generate.py b/tests/xprop/generate_mk.py similarity index 94% rename from tests/xprop/generate.py rename to tests/xprop/generate_mk.py index 484f1661c..c4a351247 100644 --- a/tests/xprop/generate.py +++ b/tests/xprop/generate_mk.py @@ -1,6 +1,12 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + import os import re -import sys import random import argparse @@ -16,7 +22,10 @@ if args.seed is None: print(f"xprop PRNG seed: {args.seed}") -makefile = open("run-test.mk", "w") + +makefile = open("Makefile", "w") +with gen_tests_makefile.redirect_stdout(makefile): + gen_tests_makefile.print_header() def add_test(name, src, seq=False): if not re.search(args.filter, name): @@ -26,17 +35,10 @@ def add_test(name, src, seq=False): os.makedirs(workdir, exist_ok=True) with open(f"{workdir}/uut.v", "w") as uut: print(src, file=uut) - print(f"all: {workdir}", file=makefile) - print(f".PHONY: {workdir}", file=makefile) - print(f"{workdir}:", file=makefile) seq_arg = " -s" if seq else "" - print( - f"\t@cd {workdir} && python3 -u ../test.py -S {args.seed} -c {args.count}{seq_arg} > test.log 2>&1 || echo {workdir}: failed > status\n" - f"\t@cat {workdir}/status\n" - f"\t@grep '^.*: ok' {workdir}/status\n" - , - file=makefile, - ) + with gen_tests_makefile.redirect_stdout(makefile): + gen_tests_makefile.generate_target(workdir, + f"cd {workdir} && python3 -u ../test.py -S {args.seed} -c {args.count}{seq_arg} > test.log 2>&1") def cell_test(name, cell, inputs, outputs, params, initial={}, defclock=False, seq=False): ports = [] @@ -119,10 +121,6 @@ def dff_test(width, pol, defclock): def dffe_test(width, pol, enpol, defclock): cell_test(f"dffe_{width}{'np'[pol]}{'np'[enpol]}{'xd'[defclock]}", 'dffe', {"CLK": 1, "EN": 1, "D": width}, {"Q": width}, {"WIDTH": width, "CLK_POLARITY": int(pol), "EN_POLARITY": int(enpol)}, defclock=defclock, seq=True) - -print(".PHONY: all", file=makefile) -print("all:\n\t@echo done\n", file=makefile) - for cell in ["not", "pos", "neg"]: if args.more: unary_test(cell, 1, False, 1) diff --git a/tests/xprop/run-test.sh b/tests/xprop/run-test.sh deleted file mode 100755 index 303c0bb3b..000000000 --- a/tests/xprop/run-test.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e - -python3 generate.py $@ -${MAKE:-make} -f run-test.mk