3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-06-19 23:36:30 +00:00

Merge branch 'YosysHQ:main' into master

This commit is contained in:
Eder Monteiro 2026-05-15 13:56:24 -03:00 committed by GitHub
commit 1de823666d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
447 changed files with 6184 additions and 3330 deletions

View file

@ -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/).

View file

@ -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

View file

@ -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:

View file

@ -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' }}

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -e -x
# Build-time dependencies

View file

@ -9,6 +9,6 @@ brew "python3"
brew "uv"
brew "xdot"
brew "bash"
brew "llvm@20"
brew "llvm"
brew "lld"
brew "googletest"

View file

@ -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

View file

@ -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).

146
Makefile
View file

@ -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)

2
abc

@ -1 +1 @@
Subproject commit 180a6adb68e855942e859f3646eff7762c7bc3e6
Subproject commit 5d51a5e420f5de493d07bf61109a977248c86ffb

View file

@ -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);

View file

@ -268,7 +268,7 @@ struct XAigerWriter
if (ys_debug(1)) {
static pool<std::pair<IdString,TimingInfo::NameBit>> 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<IdString, std::vector<IdString>> 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);

View file

@ -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<AigerWriter, unsigned int, 0, 1> {
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<AigerWriter, unsigned int, 0, 1> {
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<AigerWriter, unsigned int, 0, 1> {
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<AigerWriter, unsigned int, 0, 1> {
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<AigerWriter, unsigned int, 0, 1> {
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<AigerWriter, unsigned int, 0, 1> {
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<AigerWriter, unsigned int, 0, 1> {
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<std::tuple<HierCursor, Cell *, Module *>> 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;

View file

@ -150,7 +150,7 @@ struct BlifDumper
void dump_params(const char *command, dict<IdString, Const> &params)
{
for (auto &param : 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);

View file

@ -119,7 +119,7 @@ struct BtorWorker
template<typename T>
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<pair<int, Mem*>> 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);

View file

@ -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<std::string> param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t");
for (const auto &param_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.

View file

@ -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);

View file

@ -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;

View file

@ -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<std::string> 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<string> 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 &param : 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");

View file

@ -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++;
}

View file

@ -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);

View file

@ -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<std::string> 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();

View file

@ -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();
}

View file

@ -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;

View file

@ -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";

View file

@ -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);

View file

@ -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 $(<F) --interaction=nonstopmode

View file

@ -14,7 +14,7 @@ struct MyPass : public Pass {
log("Modules in current design:\n");
for (auto mod : design->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;

View file

@ -6,6 +6,7 @@ begin:
proc
flatten:
check
flatten
tribuf -logic
deminout

View file

@ -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'

View file

@ -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.

View file

@ -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

View file

@ -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"

View file

@ -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 </using_yosys/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.

View file

@ -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

View file

@ -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

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -ex
yosys -p '
read_verilog -formal demo.v

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -ex
yosys demo.ys
$TD_HOME/bin/td build.tcl

View file

@ -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

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -ex

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -ex

View file

@ -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)

View file

@ -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

View file

@ -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}

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
export REV="de2i"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
iverilog -o presynth lfsr_updown_tb.v lfsr_updown.v &&\

View file

@ -1,4 +1,4 @@
#!/bin/sh
#!/usr/bin/env sh
set -e
yosys run_yosys.ys
edif2ngd example.edif

View file

@ -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);
}

View file

@ -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",

View file

@ -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<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(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 dict<RTLIL::IdStr
RTLIL::Module *intfmodule = intf.second;
for (auto w : intfmodule->wires()){
auto wire = std::make_unique<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(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 dict<RTLIL::IdStr
bool has_interfaces = false;
for(auto &intf : interfaces) {
interf_info += log_id(intf.second->name);
interf_info += intf.second->name.unescape();
has_interfaces = true;
}
@ -1724,7 +1735,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
new_subcell->set_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);
}
}

View file

@ -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,

View file

@ -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;
}

View file

@ -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<int> array_indices_from_position(AstNode *mem, const std::vector<int> &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<AstNode>(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<AstNode> id, const std::vector<int>& 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<AstNode>(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<AstNode> id, AstNode *mem, const std::vector<int>& 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<void(AstNode*, int)> 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<int>& 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<int> 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<std::unique_ptr<AstNode>> assignments;
std::vector<std::unique_ptr<AstNode>> pattern_temp_assignments;
foreach_array_position(lhs_mem, [&](const std::vector<int>& 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<AstNode> 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<AstNode>(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<AstNode>(location, AST_WIRE,
std::make_unique<AstNode>(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<AstNode>(location, AST_IDENTIFIER);
tmp_id->str = wire_tmp->str;
pattern_temp_assignments.push_back(std::make_unique<AstNode>(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<AstNode>(location, type,
@ -3386,6 +3506,8 @@ skip_dynamic_range_lvalue_expansion:;
} else {
// Wrap in AST_BLOCK for procedural
newNode = std::make_unique<AstNode>(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<AstNode*, pool<std::string>> &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)) {

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -332,7 +332,7 @@ struct RTLILFrontendWorker {
error("No wires found for legalization");
int hash = hash_ops<RTLIL::IdString>::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;
}

View file

@ -1392,13 +1392,13 @@ void VerificImporter::merge_past_ffs_clock(pool<RTLIL::Cell*> &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);
}
}

View file

@ -546,7 +546,7 @@
%token TOK_z "'z'"
%type <ast_t> range range_or_multirange non_opt_range non_opt_multirange
%type <ast_t> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
%type <ast_t> wire_type expr basic_expr concat_list assignment_pattern_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
%type <string_t> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
%type <string_t> type_name
%type <ast_t> 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<AstNode>(@$, 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<AstNode>(@$, 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); } |

View file

@ -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.
for the new code instead of trying to mimic the style of the surrounding code.

View file

@ -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<RTLIL::IdString>());
setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool<RTLIL::IdString>());
setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool<RTLIL::IdString>());
setup_type(ID($specrule), {ID::SRC_EN, ID::DST_EN, ID::SRC, ID::DST}, pool<RTLIL::IdString>());
setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>());
setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>());
setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y});

View file

@ -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)

View file

@ -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;
}

View file

@ -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 = ", ";

View file

@ -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)

View file

@ -792,7 +792,7 @@ void FfData::flip_bits(const pool<int> &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) {

View file

@ -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)

View file

@ -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;

View file

@ -55,7 +55,7 @@ class FstData
std::string valueOf(fstHandle signal);
fstHandle getHandle(std::string name);
dict<int,fstHandle> 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<fstHandle, std::string> 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;

View file

@ -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);

View file

@ -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<typename K, typename T, typename OPS>
class dict {
class HASHLIB_ATTRIBUTE_WARN_UNUSED dict {
struct entry_t
{
std::pair<K, T> udata;
@ -877,7 +883,7 @@ public:
};
template<typename K, typename OPS>
class pool
class HASHLIB_ATTRIBUTE_WARN_UNUSED pool
{
template<typename, int, typename> friend class idict;
@ -1257,7 +1263,7 @@ public:
};
template<typename K, int offset, typename OPS>
class idict
class HASHLIB_ATTRIBUTE_WARN_UNUSED idict
{
pool<K, OPS> database;
@ -1360,7 +1366,7 @@ public:
* i-prefixed methods operate on indices in parents
*/
template<typename K, typename OPS>
class mfp
class HASHLIB_ATTRIBUTE_WARN_UNUSED mfp
{
idict<K, 0, OPS> database;
class AtomicParent {

View file

@ -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 <class T>
static auto has_name_member_imp(int)
-> decltype(static_cast<const RTLIL::IdString>(std::declval<T>().name), std::true_type{});
template <class T>
static auto has_name_member_imp(long)
-> std::false_type;
template <class T>
struct has_name_member : decltype(has_name_member_imp<T>(0)){};
template <class T>
static auto ptr_has_name_member_imp(int)
-> decltype(static_cast<const RTLIL::IdString>(std::declval<T>()->name), std::true_type{});
template <class T>
static auto ptr_has_name_member_imp(long)
-> std::false_type;
template <class T>
struct ptr_has_name_member : decltype(ptr_has_name_member_imp<T>(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<Arg, const char *> &&
!std::is_convertible_v<Arg, const std::string &> &&
!std::is_convertible_v<Arg, const std::string_view &> &&
!std::is_convertible_v<Arg, const RTLIL::IdString &>) {
!std::is_convertible_v<Arg, const RTLIL::IdString &> &&
!has_name_member<Arg>() &&
!ptr_has_name_member<Arg>()) {
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<Arg>()) {
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<Arg>()) {
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<Arg, const void *>) {
@ -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 <typename T> struct WrapType { using type = T; };

View file

@ -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) {

View file

@ -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;

View file

@ -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());
}
}
};

View file

@ -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);

View file

@ -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::Module*> 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::Module*> 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<RTLIL::SigSig> &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<SigBit> 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;
}

View file

@ -1400,6 +1400,8 @@ struct RTLIL::SigSpecConstIterator
struct RTLIL::SigSpec
{
private:
friend class SigSpecRepTest;
FRIEND_TEST(SigSpecRepTest, Extract);
enum Representation : char {
CHUNK,
BITS,

View file

@ -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);
}

View file

@ -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);

View file

@ -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<ModuleItem>::Cursor cursor ) { log("%p %s", cursor.target, log_id(cursor.scope_name)); }
static inline void log_dump_val_worker(typename IdTree<ModuleItem>::Cursor cursor ) { log("%p %s", cursor.target, cursor.scope_name.unescape()); }
template<typename T>
static inline void log_dump_val_worker(const typename std::unique_ptr<T> &cursor ) { log("unique %p", cursor.get()); }

View file

@ -45,9 +45,12 @@ int ThreadPool::pool_size(int reserved_cores, int max_worker_threads)
#ifdef YOSYS_ENABLE_THREADS
int available_threads = std::min<int>(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
}

View file

@ -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:

View file

@ -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) {

112
kernel/wallace_tree.h Normal file
View file

@ -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<SigSpec, SigSpec> 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<SigSpec, SigSpec> wallace_reduce_scheduled(Module *module, std::vector<SigSpec> &sigs, int width, int *compressor_count = nullptr)
{
struct DepthSig {
SigSpec sig;
int depth;
};
for (auto &s : sigs)
s.extend_u0(width);
std::vector<DepthSig> 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<DepthSig> 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<DepthSig> 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

View file

@ -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());
}

View file

@ -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)

View file

@ -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,</AdditionalIncludeDirectories>,</AdditionalIncludeDirectories>\n <LanguageStandard>stdcpp17</LanguageStandard>\n <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
sed -i 's,</AdditionalIncludeDirectories>,</AdditionalIncludeDirectories>\n <LanguageStandard>stdcpp20</LanguageStandard>\n <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
sed -i 's,<PreprocessorDefinitions>,<PreprocessorDefinitions>YOSYS_ENABLE_THREADS;,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
if [ -f "/usr/include/FlexLexer.h" ] ; then
sed -i 's,</AdditionalIncludeDirectories>,;..\\yosys\\libs\\flex</AdditionalIncludeDirectories>,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new

View file

@ -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<S
for (int i = 0; i < GetSize(ff.sig_q); i++) {
SigBit bit = ff.sig_q[i];
if (selected_reps.count(sigmap(bit))) {
log_debug("Abstracting state for %s.Q[%i] in module %s due to selections:\n", log_id(ff.cell), i, log_id(mod));
log_debug("Abstracting state for %s.Q[%i] in module %s due to selections:\n", ff.cell, i, mod);
explain_selections(selected_reps.at(sigmap(bit)));
offsets_to_abstract.insert(i);
}
@ -271,7 +271,7 @@ unsigned int abstract_value(Module* mod, EnableLogic enable, const std::vector<S
for (int i = 0; i < conn.second.size(); i++) {
if (selected_reps.count(sigmap(conn.second[i]))) {
log_debug("Abstracting value for %s.%s[%i] in module %s due to selections:\n",
log_id(cell), log_id(conn.first), i, log_id(mod));
cell, conn.first.unescape(), i, mod);
explain_selections(selected_reps.at(sigmap(conn.second[i])));
offsets_to_abstract.insert(i);
}
@ -289,7 +289,7 @@ unsigned int abstract_value(Module* mod, EnableLogic enable, const std::vector<S
for (auto bit : SigSpec(wire))
if (selected_reps.count(sigmap(bit))) {
log_debug("Abstracting value for module input port bit %s in module %s due to selections:\n",
log_signal(bit), log_id(mod));
log_signal(bit), mod);
explain_selections(selected_reps.at(sigmap(bit)));
offsets_to_abstract.insert(bit.offset);
}

View file

@ -48,7 +48,7 @@ int autoname_worker(Module *module, const dict<Wire*, unsigned int>& 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*, unsigned int>& 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*, unsigned int>& 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*, unsigned int>& 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;

View file

@ -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<std::pair<RTLIL::IdString, dict<RTLIL::IdString, RTLIL::Const>>, 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);
}

View file

@ -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;
}

View file

@ -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<SigBit, vector<string>> 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++;
}
}

View file

@ -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));

View file

@ -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)

View file

@ -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));
}
}
}

Some files were not shown because too many files have changed in this diff Show more