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

Merge branch 'YosysHQ:main' into master

This commit is contained in:
Eder Monteiro 2025-09-29 19:38:31 -03:00 committed by GitHub
commit 99159e76e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
329 changed files with 7804 additions and 3722 deletions

View file

@ -8,7 +8,7 @@ runs:
shell: bash
run: |
sudo apt-get update
sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev
sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev libgtest-dev
- name: Install macOS Dependencies
if: runner.os == 'macOS'

View file

@ -1,6 +1,14 @@
name: Test extra build flows
on: [push, pull_request]
on:
# always test main
push:
branches:
- main
# test PRs
pull_request:
# allow triggering tests, ignores skip check
workflow_dispatch:
jobs:
pre_job:
@ -11,11 +19,11 @@ jobs:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
# cancel previous builds if a new commit is pushed
cancel_others: 'true'
# only run on push *or* pull_request, not both
concurrent_skipping: 'same_content_newer'
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
vs-prep:
name: Prepare Visual Studio build

View file

@ -26,7 +26,7 @@ jobs:
# docs builds are needed for anything on main, any tagged versions, and any tag
# or branch starting with docs-preview
needs: check_docs_rebuild
if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' }}
if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
runs-on: [self-hosted, linux, x64, fast]
steps:
- name: Checkout Yosys
@ -48,7 +48,7 @@ jobs:
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
echo "ENABLE_HELP_SOURCE := 1" >> Makefile.conf
make -j$procs ENABLE_LTO=1
make -j$procs
- name: Prepare docs
shell: bash

View file

@ -1,6 +1,14 @@
name: Build and run tests
on: [push, pull_request]
on:
# always test main
push:
branches:
- main
# test PRs
pull_request:
# allow triggering tests, ignores skip check
workflow_dispatch:
jobs:
pre_job:
@ -11,11 +19,12 @@ jobs:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
# cancel previous builds if a new commit is pushed
cancel_others: 'true'
# only run on push *or* pull_request, not both
concurrent_skipping: 'same_content_newer'
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
pre_docs_job:
runs-on: ubuntu-latest
outputs:
@ -24,15 +33,16 @@ jobs:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on readme changes
paths_ignore: '["**/README.md"]'
# cancel previous builds if a new commit is pushed
cancel_others: 'true'
# only run on push *or* pull_request, not both
concurrent_skipping: 'same_content_newer'
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
build-yosys:
name: Reusable build
runs-on: ${{ matrix.os }}
# pre_job is a subset of pre_docs_job, so we can always build for pre_docs_job
needs: pre_docs_job
if: needs.pre_docs_job.outputs.should_skip != 'true'
env:
@ -40,7 +50,6 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
sanitizer: [undefined, address]
fail-fast: false
steps:
- name: Checkout Yosys
@ -58,8 +67,7 @@ jobs:
mkdir build
cd build
make -f ../Makefile config-$CC
echo 'SANITIZER = ${{ matrix.sanitizer }}' >> Makefile.conf
make -f ../Makefile -j$procs ENABLE_LTO=1
make -f ../Makefile -j$procs
- name: Log yosys-config output
run: |
@ -74,7 +82,7 @@ jobs:
- name: Store build artifact
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.os }}-${{ matrix.sanitizer }}
name: build-${{ matrix.os }}
path: build.tar
retention-days: 1
@ -85,12 +93,9 @@ jobs:
if: needs.pre_job.outputs.should_skip != 'true'
env:
CC: clang
ASAN_OPTIONS: halt_on_error=1
UBSAN_OPTIONS: halt_on_error=1
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
sanitizer: [undefined, address]
fail-fast: false
steps:
- name: Checkout Yosys
@ -102,11 +107,12 @@ jobs:
uses: ./.github/actions/setup-build-env
- name: Get iverilog
id: get-iverilog
shell: bash
run: |
git clone https://github.com/steveicarus/iverilog.git
cd iverilog
echo "IVERILOG_GIT=$(git rev-parse HEAD)" >> $GITHUB_ENV
echo "IVERILOG_GIT=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- name: Get vcd2fst
shell: bash
@ -123,7 +129,13 @@ jobs:
uses: actions/cache@v4
with:
path: .local/
key: ${{ matrix.os }}-${IVERILOG_GIT}
key: ${{ matrix.os }}-${{ steps.get-iverilog.outputs.IVERILOG_GIT }}
- name: iverilog macOS deps
if: steps.cache-iverilog.outputs.cache-hit != 'true' && runner.os == 'macOS'
shell: bash
run: |
brew install autoconf
- name: Build iverilog
if: steps.cache-iverilog.outputs.cache-hit != 'true'
@ -139,7 +151,7 @@ jobs:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: build-${{ matrix.os }}-${{ matrix.sanitizer }}
name: build-${{ matrix.os }}
- name: Uncompress build
shell: bash
@ -171,7 +183,6 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
sanitizer: [undefined]
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
@ -184,7 +195,7 @@ jobs:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: build-${{ matrix.os }}-${{ matrix.sanitizer }}
name: build-${{ matrix.os }}
- name: Uncompress build
shell: bash
@ -209,7 +220,6 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
sanitizer: [undefined, address]
fail-fast: false
steps:
- name: Checkout Yosys
@ -223,7 +233,7 @@ jobs:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: build-${{ matrix.os }}-${{ matrix.sanitizer }}
name: build-${{ matrix.os }}
- name: Uncompress build
shell: bash
@ -243,7 +253,7 @@ jobs:
name: Try build docs
runs-on: [self-hosted, linux, x64, fast]
needs: [pre_docs_job]
if: needs.pre_docs_job.outputs.should_skip != 'true'
if: ${{ needs.pre_docs_job.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
strategy:
matrix:
docs-target: [html, latexpdf]

View file

@ -1,6 +1,14 @@
name: Compiler testing
on: [push, pull_request]
on:
# always test main
push:
branches:
- main
# test PRs
pull_request:
# allow triggering tests, ignores skip check
workflow_dispatch:
jobs:
pre_job:
@ -11,11 +19,11 @@ jobs:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
# cancel previous builds if a new commit is pushed
cancel_others: 'true'
# only run on push *or* pull_request, not both
concurrent_skipping: 'same_content_newer'
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
test-compile:
runs-on: ${{ matrix.os }}
@ -34,7 +42,7 @@ jobs:
- 'gcc-10'
# newest, make sure to update maximum standard step to match
- 'clang-19'
- 'gcc-13'
- 'gcc-14'
include:
# macOS x86
- os: macos-13
@ -73,7 +81,7 @@ jobs:
# maximum standard, only on newest compilers
- name: Build C++20
if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-13' }}
if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-14' }}
shell: bash
run: |
make config-$CC_SHORT

120
.github/workflows/test-sanitizers.yml vendored Normal file
View file

@ -0,0 +1,120 @@
name: Check clang sanitizers
on:
# always test main
push:
branches:
- main
# ignore PRs due to time needed
# allow triggering tests, ignores skip check
workflow_dispatch:
jobs:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
run_san:
name: Build and run tests
runs-on: ${{ matrix.os }}
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
env:
CC: clang
ASAN_OPTIONS: halt_on_error=1
UBSAN_OPTIONS: halt_on_error=1
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
sanitizer: ['undefined,address']
fail-fast: false
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
with:
submodules: true
persist-credentials: false
- name: Setup environment
uses: ./.github/actions/setup-build-env
- name: Get iverilog
id: get-iverilog
shell: bash
run: |
git clone https://github.com/steveicarus/iverilog.git
cd iverilog
echo "IVERILOG_GIT=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- name: Get vcd2fst
shell: bash
run: |
git clone https://github.com/mmicko/libwave.git
mkdir -p ${{ github.workspace }}/.local/
cd libwave
cmake . -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/.local
make -j$procs
make install
- name: Cache iverilog
id: cache-iverilog
uses: actions/cache@v4
with:
path: .local/
key: ${{ matrix.os }}-${{ steps.get-iverilog.outputs.IVERILOG_GIT }}
- name: iverilog macOS deps
if: steps.cache-iverilog.outputs.cache-hit != 'true' && runner.os == 'macOS'
shell: bash
run: |
brew install autoconf
- name: Build iverilog
if: steps.cache-iverilog.outputs.cache-hit != 'true'
shell: bash
run: |
mkdir -p ${{ github.workspace }}/.local/
cd iverilog
autoconf
CC=gcc CXX=g++ ./configure --prefix=${{ github.workspace }}/.local
make -j$procs
make install
- name: Check iverilog
shell: bash
run: |
iverilog -V
- name: Build
shell: bash
run: |
make config-$CC
echo 'SANITIZER = ${{ matrix.sanitizer }}' >> Makefile.conf
make -j$procs
- name: Log yosys-config output
run: |
./yosys-config || true
- name: Run tests
shell: bash
run: |
make -j$procs test TARGETS= EXTRA_TARGETS=
- name: Report errors
if: ${{ failure() }}
shell: bash
run: |
find tests/**/*.err -print -exec cat {} \;
- name: Run unit tests
shell: bash
run: |
make -j$procs unit-test ENABLE_LIBYOSYS=1

View file

@ -1,6 +1,14 @@
name: Build and run tests with Verific (Linux)
on: [push, pull_request]
on:
# always test main
push:
branches:
- main
# test PRs
pull_request:
# allow triggering tests, ignores skip check
workflow_dispatch:
jobs:
pre-job:
@ -11,15 +19,15 @@ jobs:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
# cancel previous builds if a new commit is pushed
cancel_others: 'true'
# only run on push *or* pull_request, not both
concurrent_skipping: 'same_content_newer'
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
test-verific:
needs: pre-job
if: needs.pre-job.outputs.should_skip != 'true'
if: ${{ needs.pre-job.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
runs-on: [self-hosted, linux, x64, fast]
steps:
- name: Checkout Yosys
@ -70,3 +78,8 @@ jobs:
if: ${{ github.ref == 'refs/heads/main' }}
run: |
make -C sby run_ci
- name: Run unit tests
shell: bash
run: |
make -j$procs unit-test ENABLE_LTO=1 ENABLE_LIBYOSYS=1

View file

@ -6,6 +6,7 @@ on:
jobs:
lockfile:
if: github.repository == 'YosysHQ/Yosys'
runs-on: ubuntu-latest
steps:
- name: Checkout repository

View file

@ -7,6 +7,7 @@ on:
jobs:
bump-version:
if: github.repository == 'YosysHQ/Yosys'
runs-on: ubuntu-latest
steps:
- name: Checkout
@ -18,11 +19,8 @@ jobs:
- name: Take last commit
id: log
run: echo "message=$(git log --no-merges -1 --oneline)" >> $GITHUB_OUTPUT
- name: Take repository
id: repo
run: echo "message=$GITHUB_REPOSITORY" >> $GITHUB_OUTPUT
- name: Bump version
if: "!contains(steps.log.outputs.message, 'Bump version') && contains(steps.repo.outputs.message, 'YosysHQ/yosys')"
if: ${{ !contains(steps.log.outputs.message, 'Bump version') }}
run: |
make bumpversion
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
@ -30,7 +28,7 @@ jobs:
git add Makefile
git commit -m "Bump version"
- name: Push changes # push the output folder to your repo
if: "!contains(steps.log.outputs.message, 'Bump version') && contains(steps.repo.outputs.message, 'YosysHQ/yosys')"
if: ${{ !contains(steps.log.outputs.message, 'Bump version') }}
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -124,6 +124,7 @@ jobs:
path: ./wheelhouse/*.whl
upload_wheels:
name: Upload Wheels
if: github.repository == 'YosysHQ/Yosys'
runs-on: ubuntu-latest
# Specifying a GitHub environment is optional, but strongly encouraged
environment: pypi

9
.gitignore vendored
View file

@ -1,6 +1,9 @@
## user config
/Makefile.conf
## homebrew
/Brewfile.lock.json
## build artifacts
# compiler intermediate files
*.o
@ -11,6 +14,12 @@
*.gcno
*.so.dSYM/
## test artifacts
**/run-test.mk
*.err
*.log
*.tmp
# compiler output files
/kernel/version_*.cc
/share

View file

@ -11,3 +11,4 @@ brew "bash"
brew "boost-python3"
brew "llvm@20"
brew "lld"
brew "googletest"

View file

@ -30,8 +30,8 @@ docs/source/using_yosys/synthesis/abc.rst @KrystalDelusion @Ravenslofty
# These still override previous lines, so be careful not to
# accidentally disable any of the above rules.
frontends/verilog/ @zachjs
frontends/ast/ @zachjs
frontends/verilog/ @widlarizer
frontends/ast/ @widlarizer
techlibs/intel_alm/ @Ravenslofty
techlibs/gowin/ @pepijndevos

View file

@ -60,14 +60,11 @@ merge; please do not use these labels if you are not a maintainer.
# Asking questions
If you have a question about how to use Yosys, please ask on our [discussions
page](https://github.com/YosysHQ/yosys/discussions) or in our [community
slack](https://join.slack.com/t/yosyshq/shared_invite/zt-1aopkns2q-EiQ97BeQDt_pwvE41sGSuA).
The slack is also a great place to ask questions about developing or
If you have a question about how to use Yosys, please ask on our [Discourse forum](https://yosyshq.discourse.group/) or in our [discussions
page](https://github.com/YosysHQ/yosys/discussions).
The Discourse is also a great place to ask questions about developing or
contributing to Yosys.
We have open dev 'jour fixe' (JF) meetings where developers from YosysHQ and the
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. Please join the
community slack if you would like to join the next meeting, the link is
available in the description of the #devel-discuss channel.
place to talk to us about how to implement larger PRs.

View file

@ -44,7 +44,12 @@ LINK_ABC := 0
# Needed for environments that can't run executables (i.e. emscripten, wasm)
DISABLE_SPAWN := 0
# Needed for environments that don't have proper thread support (i.e. emscripten, wasm--for now)
ENABLE_THREADS := 1
ifeq ($(ENABLE_THREADS),1)
DISABLE_ABC_THREADS := 0
else
DISABLE_ABC_THREADS := 1
endif
# clang sanitizers
SANITIZER =
@ -159,7 +164,7 @@ ifeq ($(OS), Haiku)
CXXFLAGS += -D_DEFAULT_SOURCE
endif
YOSYS_VER := 0.57+0
YOSYS_VER := 0.57+218
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1)
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2)
@ -300,6 +305,7 @@ DISABLE_SPAWN := 1
ifeq ($(ENABLE_ABC),1)
LINK_ABC := 1
ENABLE_THREADS := 0
DISABLE_ABC_THREADS := 1
endif
@ -457,6 +463,11 @@ CXXFLAGS := -Og -DDEBUG $(filter-out $(OPT_LEVEL),$(CXXFLAGS))
STRIP :=
endif
ifeq ($(ENABLE_THREADS),1)
CXXFLAGS += -DYOSYS_ENABLE_THREADS
LIBS += -lpthread
endif
ifeq ($(ENABLE_ABC),1)
CXXFLAGS += -DYOSYS_ENABLE_ABC
ifeq ($(LINK_ABC),1)
@ -612,6 +623,7 @@ $(eval $(call add_include_file,kernel/satgen.h))
$(eval $(call add_include_file,kernel/scopeinfo.h))
$(eval $(call add_include_file,kernel/sexpr.h))
$(eval $(call add_include_file,kernel/sigtools.h))
$(eval $(call add_include_file,kernel/threading.h))
$(eval $(call add_include_file,kernel/timinginfo.h))
$(eval $(call add_include_file,kernel/utils.h))
$(eval $(call add_include_file,kernel/yosys.h))
@ -632,10 +644,14 @@ $(eval $(call add_include_file,frontends/blif/blifparse.h))
$(eval $(call add_include_file,backends/rtlil/rtlil_backend.h))
OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o kernel/io.o kernel/gzip.o
OBJS += kernel/rtlil_bufnorm.o
OBJS += kernel/log_help.o
ifeq ($(ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS),1)
OBJS += kernel/log_compat.o
endif
OBJS += kernel/binding.o kernel/tclapi.o
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o kernel/sexpr.o
OBJS += kernel/drivertools.o kernel/functional.o
OBJS += kernel/drivertools.o kernel/functional.o kernel/threading.o
ifeq ($(ENABLE_ZLIB),1)
OBJS += kernel/fstdata.o
endif
@ -874,6 +890,7 @@ 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

View file

@ -1040,7 +1040,7 @@ struct AigerBackend : public Backend {
std::ofstream mapf;
mapf.open(map_filename.c_str(), std::ofstream::trunc);
if (mapf.fail())
log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno));
log_error("Can't open file `%s' for writing: %s\n", map_filename, strerror(errno));
writer.write_map(mapf, verbose_map, no_startoffset);
}
@ -1051,7 +1051,7 @@ struct AigerBackend : public Backend {
PrettyJson json;
if (!json.write_to_file(yw_map_filename))
log_error("Can't open file `%s' for writing: %s\n", yw_map_filename.c_str(), strerror(errno));
log_error("Can't open file `%s' for writing: %s\n", yw_map_filename, strerror(errno));
writer.write_ywmap(json);
}
}

View file

@ -788,7 +788,7 @@ struct XAigerBackend : public Backend {
std::ofstream mapf;
mapf.open(map_filename.c_str(), std::ofstream::trunc);
if (mapf.fail())
log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno));
log_error("Can't open file `%s' for writing: %s\n", map_filename, strerror(errno));
writer.write_map(mapf);
}
}

View file

@ -91,7 +91,7 @@ struct Index {
int pos = index_wires(info, m);
for (auto cell : m->cells()) {
if (cell->type.in(KNOWN_OPS) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3)))
if (cell->type.in(KNOWN_OPS) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port)))
continue;
Module *submodule = m->design->module(cell->type);
@ -105,6 +105,13 @@ struct Index {
if (allow_blackboxes) {
info.found_blackboxes.insert(cell);
} else {
// Even if we don't allow blackboxes these might still be
// present outside of any traversed input cones, so we
// can't bail at this point. If they are hit by a traversal
// (which can only really happen with $tribuf not
// $connect), we can still detect this as an error later.
if (cell->type == ID($connect) || (cell->type == ID($tribuf) && cell->has_attribute(ID(aiger2_zbuf))))
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));
@ -483,7 +490,8 @@ struct Index {
{
Design *design = index.design;
auto &minfo = leaf_minfo(index);
log_assert(minfo.suboffsets.count(cell));
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));
Module *def = design->module(cell->type);
log_assert(def);
levels.push_back(Level(index.modules.at(def), cell));
@ -566,7 +574,7 @@ struct Index {
}
Lit ret;
if (!bit.wire->port_input) {
if (!bit.wire->port_input || bit.wire->port_output) {
// an output of a cell
Cell *driver = bit.wire->driverCell();
@ -618,7 +626,7 @@ struct Index {
if (!cursor) {
log_assert(bit.wire->module == top);
log_assert(bit.wire->port_input);
log_assert(bit.wire->port_input && !bit.wire->port_output);
return lits[top_minfo->windices[bit.wire] + bit.offset];
} else {
log_assert(bit.wire->module == cursor->leaf_module(*this));
@ -723,7 +731,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
for (auto id : top->ports) {
Wire *w = top->wire(id);
log_assert(w);
if (w->port_input)
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));
@ -828,7 +836,7 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
{
log_assert(cursor.is_top()); // TOOD: fix analyzer to work with hierarchy
if (bit.wire->port_input)
if (bit.wire->port_input && !bit.wire->port_output)
return false;
Cell *driver = bit.wire->driverCell();
@ -838,7 +846,7 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
int max = 1;
for (auto wire : mod->wires())
if (wire->port_input)
if (wire->port_input && !wire->port_output)
for (int i = 0; i < wire->width; i++) {
int ilevel = visit(cursor, driver->getPort(wire->name)[i]);
max = std::max(max, ilevel + 1);
@ -858,7 +866,7 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
for (auto id : top->ports) {
Wire *w = top->wire(id);
log_assert(w);
if (w->port_input)
if (w->port_input && !w->port_output)
for (int i = 0; i < w->width; i++)
pi_literal(SigBit(w, i)) = 0;
}
@ -868,7 +876,7 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
Module *def = design->module(box->type);
if (!(def && def->has_attribute(ID::abc9_box_id)))
for (auto &conn : box->connections_)
if (box->output(conn.first))
if (box->port_dir(conn.first) != RTLIL::PD_INPUT)
for (auto bit : conn.second)
pi_literal(bit, &cursor) = 0;
}
@ -883,7 +891,7 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
Module *def = design->module(box->type);
if (!(def && def->has_attribute(ID::abc9_box_id)))
for (auto &conn : box->connections_)
if (box->input(conn.first))
if (box->port_dir(conn.first) == RTLIL::PD_INPUT)
for (auto bit : conn.second)
(void) eval_po(bit);
}
@ -903,6 +911,16 @@ struct XAigerWriter : AigerWriter {
typedef std::pair<SigBit, HierCursor> HierBit;
std::vector<HierBit> pos;
std::vector<HierBit> pis;
// * The aiger output port sequence is COs (inputs to modeled boxes),
// inputs to opaque boxes, then module outputs. COs going first is
// required by abc.
// * proper_pos_counter counts ports which follow after COs
// * The mapping file `pseudopo` and `po` statements use indexing relative
// to the first port following COs.
// * If a module output is directly driven by an opaque box, the emission
// of the po statement in the mapping file is skipped. This is done to
// aid re-integration of the mapped result.
int proper_pos_counter = 0;
pool<SigBit> driven_by_opaque_box;
@ -937,15 +955,10 @@ struct XAigerWriter : AigerWriter {
lit_counter += 2;
}
void append_box_ports(Cell *box, HierCursor &cursor, bool inputs)
void append_opaque_box_ports(Cell *box, HierCursor &cursor, bool inputs)
{
for (auto &conn : box->connections_) {
bool is_input = box->input(conn.first);
bool is_output = box->output(conn.first);
if (!(is_input || is_output) || (is_input && is_output))
log_error("Ambiguous port direction on %s/%s\n",
log_id(box->type), log_id(conn.first));
bool is_input = box->port_dir(conn.first) == RTLIL::PD_INPUT;
if (is_input && inputs) {
int bitp = 0;
@ -955,13 +968,14 @@ struct XAigerWriter : AigerWriter {
continue;
}
// Inputs to opaque boxes are proper POs as far as abc is concerned
if (map_file.is_open()) {
log_assert(cursor.is_top());
map_file << "pseudopo " << proper_pos_counter++ << " " << bitp
map_file << "pseudopo " << proper_pos_counter << " " << bitp
<< " " << box->name.c_str()
<< " " << conn.first.c_str() << "\n";
}
proper_pos_counter++;
pos.push_back(std::make_pair(bit, cursor));
if (mapping_prep)
@ -969,10 +983,10 @@ struct XAigerWriter : AigerWriter {
bitp++;
}
} else if (is_output && !inputs) {
} else if (!is_input && !inputs) {
for (auto &bit : conn.second) {
if (!bit.wire || bit.wire->port_input)
log_error("Bad connection");
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));
ensure_pi(bit, cursor);
@ -1011,8 +1025,8 @@ struct XAigerWriter : AigerWriter {
auto &minfo = cursor.leaf_minfo(*this);
for (auto box : minfo.found_blackboxes) {
log_debug(" - %s.%s (type %s): ", cursor.path().c_str(),
RTLIL::unescape_id(box->name).c_str(),
log_debug(" - %s.%s (type %s): ", cursor.path(),
RTLIL::unescape_id(box->name),
log_id(box->type));
Module *box_module = design->module(box->type), *box_derived;
@ -1038,7 +1052,7 @@ struct XAigerWriter : AigerWriter {
});
for (auto [cursor, box, def] : opaque_boxes)
append_box_ports(box, cursor, false);
append_opaque_box_ports(box, cursor, false);
holes_module = design->addModule(NEW_ID);
std::vector<RTLIL::Wire *> holes_pis;
@ -1086,6 +1100,8 @@ struct XAigerWriter : AigerWriter {
bit = RTLIL::Sx;
}
// Nonopaque box inputs come first and are not part of
// the PO numbering used by the mapping file.
pos.push_back(std::make_pair(bit, cursor));
}
boxes_co_num += port->width;
@ -1106,7 +1122,7 @@ struct XAigerWriter : AigerWriter {
holes_pi_idx++;
}
holes_wb->setPort(port_id, in_conn);
} else if (port->port_output && !port->port_input) {
} else if (port->port_output) {
// primary
for (int i = 0; i < port->width; i++) {
SigBit bit;
@ -1138,7 +1154,7 @@ struct XAigerWriter : AigerWriter {
}
for (auto [cursor, box, def] : opaque_boxes)
append_box_ports(box, cursor, true);
append_opaque_box_ports(box, cursor, true);
write_be32(h_buffer, 1);
write_be32(h_buffer, pis.size());
@ -1159,7 +1175,7 @@ struct XAigerWriter : AigerWriter {
log_assert(port);
if (port->port_input && !port->port_output) {
box_co_num += port->width;
} else if (port->port_output && !port->port_input) {
} else if (port->port_output) {
box_ci_num += port->width;
} else {
log_abort();
@ -1182,7 +1198,7 @@ struct XAigerWriter : AigerWriter {
reset_counters();
for (auto w : top->wires())
if (w->port_input)
if (w->port_input && !w->port_output)
for (int i = 0; i < w->width; i++)
ensure_pi(SigBit(w, i));
@ -1195,10 +1211,14 @@ struct XAigerWriter : AigerWriter {
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
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{}));
}
@ -1446,7 +1466,7 @@ struct XAiger2Backend : Backend {
if (!map_filename.empty()) {
writer.map_file.open(map_filename);
if (!writer.map_file)
log_cmd_error("Failed to open '%s' for writing\n", map_filename.c_str());
log_cmd_error("Failed to open '%s' for writing\n", map_filename);
}
design->bufNormalize(true);

View file

@ -157,14 +157,14 @@ struct BlifDumper
f << stringf("%c", ch);
f << stringf("\"\n");
} else
f << stringf("%s\n", param.second.as_string().c_str());
f << stringf("%s\n", param.second.as_string());
}
}
void dump()
{
f << stringf("\n");
f << stringf(".model %s\n", str(module->name).c_str());
f << stringf(".model %s\n", str(module->name));
std::map<int, RTLIL::Wire*> inputs, outputs;
@ -179,7 +179,7 @@ struct BlifDumper
for (auto &it : inputs) {
RTLIL::Wire *wire = it.second;
for (int i = 0; i < wire->width; i++)
f << stringf(" %s", str(RTLIL::SigSpec(wire, i)).c_str());
f << stringf(" %s", str(RTLIL::SigSpec(wire, i)));
}
f << stringf("\n");
@ -187,7 +187,7 @@ struct BlifDumper
for (auto &it : outputs) {
RTLIL::Wire *wire = it.second;
for (int i = 0; i < wire->width; i++)
f << stringf(" %s", str(RTLIL::SigSpec(wire, i)).c_str());
f << stringf(" %s", str(RTLIL::SigSpec(wire, i)));
}
f << stringf("\n");
@ -200,7 +200,7 @@ struct BlifDumper
if (!config->impltf_mode) {
if (!config->false_type.empty()) {
if (config->false_type == "+")
f << stringf(".names %s\n", config->false_out.c_str());
f << stringf(".names %s\n", config->false_out);
else if (config->false_type != "-")
f << stringf(".%s %s %s=$false\n", subckt_or_gate(config->false_type),
config->false_type.c_str(), config->false_out.c_str());
@ -208,7 +208,7 @@ struct BlifDumper
f << stringf(".names $false\n");
if (!config->true_type.empty()) {
if (config->true_type == "+")
f << stringf(".names %s\n1\n", config->true_out.c_str());
f << stringf(".names %s\n1\n", config->true_out);
else if (config->true_type != "-")
f << stringf(".%s %s %s=$true\n", subckt_or_gate(config->true_type),
config->true_type.c_str(), config->true_out.c_str());
@ -216,7 +216,7 @@ struct BlifDumper
f << stringf(".names $true\n1\n");
if (!config->undef_type.empty()) {
if (config->undef_type == "+")
f << stringf(".names %s\n", config->undef_out.c_str());
f << stringf(".names %s\n", config->undef_out);
else if (config->undef_type != "-")
f << stringf(".%s %s %s=$undef\n", subckt_or_gate(config->undef_type),
config->undef_type.c_str(), config->undef_out.c_str());
@ -331,31 +331,31 @@ struct BlifDumper
}
if (!config->icells_mode && cell->type == ID($_FF_)) {
f << stringf(".latch %s %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
f << stringf(".latch %s %s%s\n", str(cell->getPort(ID::D)), str(cell->getPort(ID::Q)),
str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_DFF_N_)) {
f << stringf(".latch %s %s fe %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
f << stringf(".latch %s %s fe %s%s\n", str(cell->getPort(ID::D)), str(cell->getPort(ID::Q)),
str(cell->getPort(ID::C)).c_str(), str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_DFF_P_)) {
f << stringf(".latch %s %s re %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
f << stringf(".latch %s %s re %s%s\n", str(cell->getPort(ID::D)), str(cell->getPort(ID::Q)),
str(cell->getPort(ID::C)).c_str(), str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_DLATCH_N_)) {
f << stringf(".latch %s %s al %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
f << stringf(".latch %s %s al %s%s\n", str(cell->getPort(ID::D)), str(cell->getPort(ID::Q)),
str(cell->getPort(ID::E)).c_str(), str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_DLATCH_P_)) {
f << stringf(".latch %s %s ah %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
f << stringf(".latch %s %s ah %s%s\n", str(cell->getPort(ID::D)), str(cell->getPort(ID::Q)),
str(cell->getPort(ID::E)).c_str(), str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
@ -366,10 +366,10 @@ struct BlifDumper
auto width = cell->parameters.at(ID::WIDTH).as_int();
log_assert(inputs.size() == width);
for (int i = width-1; i >= 0; i--)
f << stringf(" %s", str(inputs.extract(i, 1)).c_str());
f << stringf(" %s", str(inputs.extract(i, 1)));
auto &output = cell->getPort(ID::Y);
log_assert(output.size() == 1);
f << stringf(" %s", str(output).c_str());
f << stringf(" %s", str(output));
f << stringf("\n");
RTLIL::SigSpec mask = cell->parameters.at(ID::LUT);
for (int i = 0; i < (1 << width); i++)
@ -392,10 +392,10 @@ struct BlifDumper
table.push_back(State::S0);
log_assert(inputs.size() == width);
for (int i = 0; i < width; i++)
f << stringf(" %s", str(inputs.extract(i, 1)).c_str());
f << stringf(" %s", str(inputs.extract(i, 1)));
auto &output = cell->getPort(ID::Y);
log_assert(output.size() == 1);
f << stringf(" %s", str(output).c_str());
f << stringf(" %s", str(output));
f << stringf("\n");
for (int i = 0; i < depth; i++) {
for (int j = 0; j < width; j++) {
@ -410,11 +410,11 @@ struct BlifDumper
goto internal_cell;
}
f << stringf(".%s %s", subckt_or_gate(cell->type.str()), str(cell->type).c_str());
f << stringf(".%s %s", subckt_or_gate(cell->type.str()), str(cell->type));
for (auto &conn : cell->connections())
{
if (conn.second.size() == 1) {
f << stringf(" %s=%s", str(conn.first).c_str(), str(conn.second[0]).c_str());
f << stringf(" %s=%s", str(conn.first), str(conn.second[0]));
continue;
}
@ -423,11 +423,11 @@ struct BlifDumper
if (w == nullptr) {
for (int i = 0; i < GetSize(conn.second); i++)
f << stringf(" %s[%d]=%s", str(conn.first).c_str(), i, str(conn.second[i]).c_str());
f << stringf(" %s[%d]=%s", str(conn.first), i, str(conn.second[i]));
} else {
for (int i = 0; i < std::min(GetSize(conn.second), GetSize(w)); i++) {
SigBit sig(w, i);
f << stringf(" %s[%d]=%s", str(conn.first).c_str(), sig.wire->upto ?
f << stringf(" %s[%d]=%s", str(conn.first), sig.wire->upto ?
sig.wire->start_offset+sig.wire->width-sig.offset-1 :
sig.wire->start_offset+sig.offset, str(conn.second[i]).c_str());
}
@ -436,7 +436,7 @@ struct BlifDumper
f << stringf("\n");
if (config->cname_mode)
f << stringf(".cname %s\n", str(cell->name).c_str());
f << stringf(".cname %s\n", str(cell->name));
if (config->attr_mode)
dump_params(".attr", cell->attributes);
if (config->param_mode)
@ -445,7 +445,7 @@ struct BlifDumper
if (0) {
internal_cell:
if (config->iname_mode)
f << stringf(".cname %s\n", str(cell->name).c_str());
f << stringf(".cname %s\n", str(cell->name));
if (config->iattr_mode)
dump_params(".attr", cell->attributes);
}
@ -461,12 +461,12 @@ struct BlifDumper
continue;
if (config->conn_mode)
f << stringf(".conn %s %s\n", str(rhs_bit).c_str(), str(lhs_bit).c_str());
f << stringf(".conn %s %s\n", str(rhs_bit), str(lhs_bit));
else if (!config->buf_type.empty())
f << stringf(".%s %s %s=%s %s=%s\n", subckt_or_gate(config->buf_type), config->buf_type.c_str(),
f << stringf(".%s %s %s=%s %s=%s\n", subckt_or_gate(config->buf_type), config->buf_type,
config->buf_in.c_str(), str(rhs_bit).c_str(), config->buf_out.c_str(), str(lhs_bit).c_str());
else
f << stringf(".names %s %s\n1 1\n", str(rhs_bit).c_str(), str(lhs_bit).c_str());
f << stringf(".names %s %s\n1 1\n", str(rhs_bit), str(lhs_bit));
}
f << stringf(".end\n");
@ -674,7 +674,7 @@ struct BlifBackend : public Backend {
}
if (!top_module_name.empty())
log_error("Can't find top module `%s'!\n", top_module_name.c_str());
log_error("Can't find top module `%s'!\n", top_module_name);
for (auto module : mod_list)
BlifDumper::dump(*f, module, design, config);

View file

@ -102,20 +102,16 @@ struct BtorWorker
PrettyJson ywmap_json;
void btorf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 2, 3))
template <typename... Args>
void btorf(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
va_list ap;
va_start(ap, fmt);
f << indent << vstringf(fmt, ap);
va_end(ap);
f << indent << fmt.format(args...);
}
void infof(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 2, 3))
template <typename... Args>
void infof(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
va_list ap;
va_start(ap, fmt);
info_lines.push_back(vstringf(fmt, ap));
va_end(ap);
info_lines.push_back(fmt.format(args...));
}
template<typename T>
@ -246,7 +242,7 @@ struct BtorWorker
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.c_str());
log_error("Found topological loop while processing cell %s. Active cells:%s\n", log_id(cell), cell_list);
}
cell_recursion_guard.insert(cell);
@ -322,12 +318,12 @@ struct BtorWorker
btorf("%d slt %d %d %d\n", nid_b_ltz, sid_bit, nid_b, nid_zero);
nid = next_nid++;
btorf("%d ite %d %d %d %d%s\n", nid, sid, nid_b_ltz, nid_l, nid_r, getinfo(cell).c_str());
btorf("%d ite %d %d %d %d%s\n", nid, sid, nid_b_ltz, nid_l, nid_r, getinfo(cell));
}
else
{
nid = next_nid++;
btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str());
btorf("%d %s %d %d %d%s\n", nid, btor_op, sid, nid_a, nid_b, getinfo(cell));
}
SigSpec sig = sigmap(cell->getPort(ID::Y));
@ -368,7 +364,7 @@ struct BtorWorker
int sid = get_bv_sid(width);
int nid = next_nid++;
btorf("%d %c%s %d %d %d%s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str());
btorf("%d %c%s %d %d %d%s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op, sid, nid_a, nid_b, getinfo(cell));
SigSpec sig = sigmap(cell->getPort(ID::Y));
@ -394,12 +390,12 @@ struct BtorWorker
if (cell->type == ID($_ANDNOT_)) {
btorf("%d not %d %d\n", nid1, sid, nid_b);
btorf("%d and %d %d %d%s\n", nid2, sid, nid_a, nid1, getinfo(cell).c_str());
btorf("%d and %d %d %d%s\n", nid2, sid, nid_a, nid1, getinfo(cell));
}
if (cell->type == ID($_ORNOT_)) {
btorf("%d not %d %d\n", nid1, sid, nid_b);
btorf("%d or %d %d %d%s\n", nid2, sid, nid_a, nid1, getinfo(cell).c_str());
btorf("%d or %d %d %d%s\n", nid2, sid, nid_a, nid1, getinfo(cell));
}
SigSpec sig = sigmap(cell->getPort(ID::Y));
@ -421,13 +417,13 @@ struct BtorWorker
if (cell->type == ID($_OAI3_)) {
btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b);
btorf("%d and %d %d %d\n", nid2, sid, nid1, nid_c);
btorf("%d not %d %d%s\n", nid3, sid, nid2, getinfo(cell).c_str());
btorf("%d not %d %d%s\n", nid3, sid, nid2, getinfo(cell));
}
if (cell->type == ID($_AOI3_)) {
btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b);
btorf("%d or %d %d %d\n", nid2, sid, nid1, nid_c);
btorf("%d not %d %d%s\n", nid3, sid, nid2, getinfo(cell).c_str());
btorf("%d not %d %d%s\n", nid3, sid, nid2, getinfo(cell));
}
SigSpec sig = sigmap(cell->getPort(ID::Y));
@ -452,14 +448,14 @@ struct BtorWorker
btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b);
btorf("%d or %d %d %d\n", nid2, sid, nid_c, nid_d);
btorf("%d and %d %d %d\n", nid3, sid, nid1, nid2);
btorf("%d not %d %d%s\n", nid4, sid, nid3, getinfo(cell).c_str());
btorf("%d not %d %d%s\n", nid4, sid, nid3, getinfo(cell));
}
if (cell->type == ID($_AOI4_)) {
btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b);
btorf("%d and %d %d %d\n", nid2, sid, nid_c, nid_d);
btorf("%d or %d %d %d\n", nid3, sid, nid1, nid2);
btorf("%d not %d %d%s\n", nid4, sid, nid3, getinfo(cell).c_str());
btorf("%d not %d %d%s\n", nid4, sid, nid3, getinfo(cell));
}
SigSpec sig = sigmap(cell->getPort(ID::Y));
@ -491,9 +487,9 @@ struct BtorWorker
int nid = next_nid++;
if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt))) {
btorf("%d %c%s %d %d %d%s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str());
btorf("%d %c%s %d %d %d%s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op, sid, nid_a, nid_b, getinfo(cell));
} else {
btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str());
btorf("%d %s %d %d %d%s\n", nid, btor_op, sid, nid_a, nid_b, getinfo(cell));
}
SigSpec sig = sigmap(cell->getPort(ID::Y));
@ -528,7 +524,7 @@ struct BtorWorker
log_assert(!btor_op.empty());
int sid = get_bv_sid(width);
nid = next_nid++;
btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str());
btorf("%d %s %d %d%s\n", nid, btor_op, sid, nid_a, getinfo(cell));
}
if (GetSize(sig) < width) {
@ -568,9 +564,9 @@ struct BtorWorker
int nid = next_nid++;
if (btor_op != "not")
btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str());
btorf("%d %s %d %d %d%s\n", nid, btor_op, sid, nid_a, nid_b, getinfo(cell));
else
btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str());
btorf("%d %s %d %d%s\n", nid, btor_op, sid, nid_a, getinfo(cell));
SigSpec sig = sigmap(cell->getPort(ID::Y));
@ -601,11 +597,11 @@ struct BtorWorker
if (cell->type == ID($reduce_xnor)) {
int nid2 = next_nid++;
btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str());
btorf("%d %s %d %d%s\n", nid, btor_op, sid, nid_a, getinfo(cell));
btorf("%d not %d %d\n", nid2, sid, nid);
nid = nid2;
} else {
btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str());
btorf("%d %s %d %d%s\n", nid, btor_op, sid, nid_a, getinfo(cell));
}
SigSpec sig = sigmap(cell->getPort(ID::Y));
@ -640,9 +636,9 @@ struct BtorWorker
int tmp = nid;
nid = next_nid++;
btorf("%d ite %d %d %d %d\n", tmp, sid, nid_s, nid_b, nid_a);
btorf("%d not %d %d%s\n", nid, sid, tmp, getinfo(cell).c_str());
btorf("%d not %d %d%s\n", nid, sid, tmp, getinfo(cell));
} else {
btorf("%d ite %d %d %d %d%s\n", nid, sid, nid_s, nid_b, nid_a, getinfo(cell).c_str());
btorf("%d ite %d %d %d %d%s\n", nid, sid, nid_s, nid_b, nid_a, getinfo(cell));
}
add_nid_sig(nid, sig_y);
@ -665,7 +661,7 @@ struct BtorWorker
int nid_s = get_sig_nid(sig_s.extract(i));
int nid2 = next_nid++;
if (i == GetSize(sig_s)-1)
btorf("%d ite %d %d %d %d%s\n", nid2, sid, nid_s, nid_b, nid, getinfo(cell).c_str());
btorf("%d ite %d %d %d %d%s\n", nid2, sid, nid_s, nid_b, nid, getinfo(cell));
else
btorf("%d ite %d %d %d %d\n", nid2, sid, nid_s, nid_b, nid);
nid = nid2;
@ -709,12 +705,13 @@ struct BtorWorker
}
}
Const initval;
Const::Builder initval_bits(GetSize(sig_q));
for (int i = 0; i < GetSize(sig_q); i++)
if (initbits.count(sig_q[i]))
initval.bits().push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0);
initval_bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0);
else
initval.bits().push_back(State::Sx);
initval_bits.push_back(State::Sx);
Const initval = initval_bits.build();
int nid_init_val = -1;
@ -753,7 +750,7 @@ struct BtorWorker
int sid = get_bv_sid(GetSize(sig_y));
int nid = next_nid++;
btorf("%d state %d%s\n", nid, sid, getinfo(cell).c_str());
btorf("%d state %d%s\n", nid, sid, getinfo(cell));
ywmap_state(sig_y);
@ -776,7 +773,7 @@ struct BtorWorker
int one_nid = get_sig_nid(State::S1);
int zero_nid = get_sig_nid(State::S0);
initstate_nid = next_nid++;
btorf("%d state %d%s\n", initstate_nid, sid, getinfo(cell).c_str());
btorf("%d state %d%s\n", initstate_nid, sid, getinfo(cell));
btorf("%d init %d %d %d\n", next_nid++, sid, initstate_nid, one_nid);
btorf("%d next %d %d %d\n", next_nid++, sid, initstate_nid, zero_nid);
@ -1043,15 +1040,16 @@ struct BtorWorker
{
if (bit.wire == nullptr)
{
Const c(bit.data);
while (i+GetSize(c) < GetSize(sig) && sig[i+GetSize(c)].wire == nullptr)
c.bits().push_back(sig[i+GetSize(c)].data);
Const::Builder c_bits;
c_bits.push_back(bit.data);
while (i + GetSize(c_bits) < GetSize(sig) && sig[i + GetSize(c_bits)].wire == nullptr)
c_bits.push_back(sig[i + GetSize(c_bits)].data);
Const c = c_bits.build();
if (consts.count(c) == 0) {
int sid = get_bv_sid(GetSize(c));
int nid = next_nid++;
btorf("%d const %d %s\n", nid, sid, c.as_string().c_str());
btorf("%d const %d %s\n", nid, sid, c.as_string());
consts[c] = nid;
nid_width[nid] = GetSize(c);
}
@ -1215,7 +1213,7 @@ struct BtorWorker
int sid = get_bv_sid(GetSize(sig));
int nid = next_nid++;
btorf("%d input %d%s\n", nid, sid, getinfo(wire).c_str());
btorf("%d input %d%s\n", nid, sid, getinfo(wire));
ywmap_input(wire);
add_nid_sig(nid, sig);
@ -1260,7 +1258,7 @@ struct BtorWorker
btorf_push(stringf("output %s", log_id(wire)));
int nid = get_sig_nid(wire);
btorf("%d output %d%s\n", next_nid++, nid, getinfo(wire).c_str());
btorf("%d output %d%s\n", next_nid++, nid, getinfo(wire));
btorf_pop(stringf("output %s", log_id(wire)));
}
@ -1302,10 +1300,10 @@ struct BtorWorker
bad_properties.push_back(nid_en_and_not_a);
} else {
if (cover_mode) {
infof("bad %d%s\n", nid_en_and_not_a, getinfo(cell, true).c_str());
infof("bad %d%s\n", nid_en_and_not_a, getinfo(cell, true));
} else {
int nid = next_nid++;
btorf("%d bad %d%s\n", nid, nid_en_and_not_a, getinfo(cell, true).c_str());
btorf("%d bad %d%s\n", nid, nid_en_and_not_a, getinfo(cell, true));
}
}
@ -1327,7 +1325,7 @@ struct BtorWorker
bad_properties.push_back(nid_en_and_a);
} else {
int nid = next_nid++;
btorf("%d bad %d%s\n", nid, nid_en_and_a, getinfo(cell, true).c_str());
btorf("%d bad %d%s\n", nid, nid_en_and_a, getinfo(cell, true));
}
btorf_pop(log_id(cell));
@ -1348,7 +1346,7 @@ struct BtorWorker
continue;
int this_nid = next_nid++;
btorf("%d uext %d %d %d%s\n", this_nid, sid, nid, 0, getinfo(wire).c_str());
btorf("%d uext %d %d %d%s\n", this_nid, sid, nid, 0, getinfo(wire));
if (info_clocks.count(nid))
info_clocks[this_nid] |= info_clocks[nid];
@ -1371,7 +1369,7 @@ struct BtorWorker
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).c_str());
btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell));
btorf_pop(stringf("next %s", log_id(cell)));
}
@ -1430,7 +1428,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)).c_str());
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)));
}
@ -1489,7 +1487,7 @@ struct BtorWorker
std::ofstream f;
f.open(info_filename.c_str(), std::ofstream::trunc);
if (f.fail())
log_error("Can't open file `%s' for writing: %s\n", info_filename.c_str(), strerror(errno));
log_error("Can't open file `%s' for writing: %s\n", info_filename, strerror(errno));
for (auto &it : info_lines)
f << it;
f.close();

View file

@ -1533,7 +1533,7 @@ struct CxxrtlWorker {
}
// Internal cells
} else if (is_internal_cell(cell->type)) {
log_cmd_error("Unsupported internal cell `%s'.\n", cell->type.c_str());
log_cmd_error("Unsupported internal cell `%s'.\n", cell->type);
// User cells
} else if (for_debug) {
// Outlines are called on demand when computing the value of a debug item. Nothing to do here.
@ -1668,26 +1668,29 @@ struct CxxrtlWorker {
f << signal_temp << " == ";
dump_sigspec(compare, /*is_lhs=*/false, for_debug);
} else if (compare.is_fully_const()) {
RTLIL::Const compare_mask, compare_value;
RTLIL::Const::Builder compare_mask_builder(compare.size());
RTLIL::Const::Builder compare_value_builder(compare.size());
for (auto bit : compare.as_const()) {
switch (bit) {
case RTLIL::S0:
case RTLIL::S1:
compare_mask.bits().push_back(RTLIL::S1);
compare_value.bits().push_back(bit);
compare_mask_builder.push_back(RTLIL::S1);
compare_value_builder.push_back(bit);
break;
case RTLIL::Sx:
case RTLIL::Sz:
case RTLIL::Sa:
compare_mask.bits().push_back(RTLIL::S0);
compare_value.bits().push_back(RTLIL::S0);
compare_mask_builder.push_back(RTLIL::S0);
compare_value_builder.push_back(RTLIL::S0);
break;
default:
log_assert(false);
}
}
RTLIL::Const compare_mask = compare_mask_builder.build();
RTLIL::Const compare_value = compare_value_builder.build();
f << "and_uu<" << compare.size() << ">(" << signal_temp << ", ";
dump_const(compare_mask);
f << ") == ";
@ -3042,7 +3045,7 @@ struct CxxrtlWorker {
if (init == RTLIL::Const()) {
init = RTLIL::Const(State::Sx, GetSize(bit.wire));
}
init.bits()[bit.offset] = port.init_value[i];
init.set(bit.offset, port.init_value[i]);
}
}
}
@ -3478,8 +3481,8 @@ struct CxxrtlWorker {
};
struct CxxrtlBackend : public Backend {
static const int DEFAULT_OPT_LEVEL = 6;
static const int DEFAULT_DEBUG_LEVEL = 4;
static constexpr int DEFAULT_OPT_LEVEL = 6;
static constexpr int DEFAULT_DEBUG_LEVEL = 4;
CxxrtlBackend() : Backend("cxxrtl", "convert design to C++ RTL simulation") { }
void help() override
@ -3800,7 +3803,7 @@ struct CxxrtlBackend : public Backend {
if (args[argidx] == "-print-output" && argidx+1 < args.size()) {
worker.print_output = args[++argidx];
if (!(worker.print_output == "std::cout" || worker.print_output == "std::cerr")) {
log_cmd_error("Invalid output stream \"%s\".\n", worker.print_output.c_str());
log_cmd_error("Invalid output stream \"%s\".\n", worker.print_output);
worker.print_output = "std::cout";
}
continue;

View file

@ -30,9 +30,9 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true).c_str()
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br).c_str()
#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false).c_str()
#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true)
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br)
#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false)
struct EdifNames
{
@ -48,8 +48,8 @@ struct EdifNames
if (define) {
std::string new_id = operator()(id, false);
if (port_rename)
return stringf("(rename %s \"%s%c%d:%d%c\")", new_id.c_str(), id.c_str(), delim_left, range_left, range_right, delim_right);
return new_id != id ? stringf("(rename %s \"%s\")", new_id.c_str(), id.c_str()) : id;
return stringf("(rename %s \"%s%c%d:%d%c\")", new_id, id, delim_left, range_left, range_right, delim_right);
return new_id != id ? stringf("(rename %s \"%s\")", new_id, id) : id;
}
if (name_map.count(id) > 0)
@ -334,7 +334,7 @@ struct EdifBackend : public Backend {
auto add_prop = [&](IdString name, Const val) {
if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0)
*f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str());
*f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string());
else if (val.size() <= 32 && RTLIL::SigSpec(val).is_fully_def())
*f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int());
else {
@ -348,7 +348,7 @@ struct EdifBackend : public Backend {
char digit_str[2] = { "0123456789abcdef"[digit_value], 0 };
hex_string = std::string(digit_str) + hex_string;
}
*f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val), hex_string.c_str());
*f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val), hex_string);
}
};
for (auto module : sorted_modules)
@ -513,13 +513,13 @@ struct EdifBackend : public Backend {
if (sig.wire == NULL && sig != RTLIL::State::S0 && sig != RTLIL::State::S1) {
if (sig == RTLIL::State::Sx) {
for (auto &ref : it.second)
log_warning("Exporting x-bit on %s as zero bit.\n", ref.first.c_str());
log_warning("Exporting x-bit on %s as zero bit.\n", ref.first);
sig = RTLIL::State::S0;
} else if (sig == RTLIL::State::Sz) {
continue;
} else {
for (auto &ref : it.second)
log_error("Don't know how to handle %s on %s.\n", log_signal(sig), ref.first.c_str());
log_error("Don't know how to handle %s on %s.\n", log_signal(sig), ref.first);
log_abort();
}
}
@ -536,7 +536,7 @@ struct EdifBackend : public Backend {
}
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname));
for (auto &ref : it.second)
*f << stringf(" %s\n", ref.first.c_str());
*f << stringf(" %s\n", ref.first);
if (sig.wire == NULL) {
if (nogndvcc)
log_error("Design contains constant nodes (map with \"hilomap\" first).\n");
@ -577,7 +577,7 @@ struct EdifBackend : public Backend {
auto &refs = net_join_db.at(mapped_sig);
for (auto &ref : refs)
if (ref.second)
*f << stringf(" %s\n", ref.first.c_str());
*f << stringf(" %s\n", ref.first);
*f << stringf(" )");
if (attr_properties && raw_sig.wire != NULL)

View file

@ -347,7 +347,7 @@ void emit_elaborated_extmodules(RTLIL::Design *design, std::ostream &f)
auto modInstance = design->module(cell->type);
// Ensure that we actually have a module instance
if (modInstance == nullptr) {
log_error("Unknown cell type %s\n", cell->type.c_str());
log_error("Unknown cell type %s\n", cell->type);
return;
}
@ -465,7 +465,7 @@ struct FirrtlWorker
// If there is no instance for this, just return.
if (instModule == NULL)
{
log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str());
log_warning("No instance for %s.%s\n", cell_type, cell_name);
return;
}
@ -490,7 +490,7 @@ struct FirrtlWorker
const SigSpec *sinkSig = nullptr;
switch (dir) {
case FD_INOUT:
log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second));
log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type, log_signal(it->second));
YS_FALLTHROUGH
case FD_OUT:
sourceExpr = firstName;
@ -498,21 +498,21 @@ struct FirrtlWorker
sinkSig = &secondSig;
break;
case FD_NODIRECTION:
log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second));
log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type, log_signal(it->second));
YS_FALLTHROUGH
case FD_IN:
sourceExpr = secondExpr;
sinkExpr = firstName;
break;
default:
log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir);
log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type, log_signal(it->second), dir);
break;
}
// Check for subfield assignment.
std::string bitsString = "bits(";
if (sinkExpr.compare(0, bitsString.length(), bitsString) == 0) {
if (sinkSig == nullptr)
log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str());
log_error("Unknown subfield %s.%s\n", cell_type, sinkExpr);
// Don't generate the assignment here.
// Add the source and sink to the "reverse_wire_map" and we'll output the assignment
// as part of the coalesced subfield assignments for this wire.
@ -565,12 +565,12 @@ struct FirrtlWorker
{
if (wire->port_input && wire->port_output)
log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire));
port_decls.push_back(stringf("%s%s %s: UInt<%d> %s\n", indent.c_str(), wire->port_input ? "input" : "output",
port_decls.push_back(stringf("%s%s %s: UInt<%d> %s\n", indent, wire->port_input ? "input" : "output",
wireName, wire->width, wireFileinfo.c_str()));
}
else
{
wire_decls.push_back(stringf("%swire %s: UInt<%d> %s\n", indent.c_str(), wireName, wire->width, wireFileinfo.c_str()));
wire_decls.push_back(stringf("%swire %s: UInt<%d> %s\n", indent, wireName, wire->width, wireFileinfo));
}
}
@ -885,7 +885,7 @@ struct FirrtlWorker
string a_expr = make_expr(cell->getPort(ID::A));
string b_expr = make_expr(cell->getPort(ID::B));
string s_expr = make_expr(cell->getPort(ID::S));
wire_decls.push_back(stringf("%swire %s: UInt<%d> %s\n", indent.c_str(), y_id.c_str(), width, cellFileinfo.c_str()));
wire_decls.push_back(stringf("%swire %s: UInt<%d> %s\n", indent, y_id, width, cellFileinfo));
string expr = stringf("mux(%s, %s, %s)", s_expr, b_expr, a_expr);
@ -926,7 +926,7 @@ struct FirrtlWorker
string a_expr = make_expr(cell->getPort(ID::A));
// Get the initial bit selector
string b_expr = make_expr(cell->getPort(ID::B));
wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent.c_str(), y_id.c_str(), y_width));
wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent, y_id, y_width));
if (cell->getParam(ID::B_SIGNED).as_bool()) {
// Use validif to constrain the selection (test the sign bit)
@ -936,7 +936,7 @@ struct FirrtlWorker
}
string expr = stringf("dshr(%s, %s)", a_expr, b_expr);
cell_exprs.push_back(stringf("%s%s <= %s\n", indent.c_str(), y_id.c_str(), expr.c_str()));
cell_exprs.push_back(stringf("%s%s <= %s\n", indent, y_id, expr));
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
}
@ -948,21 +948,21 @@ struct FirrtlWorker
string b_expr = make_expr(cell->getPort(ID::B));
auto b_string = b_expr.c_str();
string expr;
wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent.c_str(), y_id.c_str(), y_width));
wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent, y_id, y_width));
if (cell->getParam(ID::B_SIGNED).as_bool()) {
// We generate a left or right shift based on the sign of b.
std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_width).c_str(), y_width);
std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string);
std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr, gen_dshl(b_expr, b_width), y_width);
std::string dshr = stringf("dshr(%s, %s)", a_expr, b_string);
expr = stringf("mux(%s < 0, %s, %s)",
b_string,
dshl.c_str(),
dshr.c_str()
);
} else {
expr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string);
expr = stringf("dshr(%s, %s)", a_expr, b_string);
}
cell_exprs.push_back(stringf("%s%s <= %s\n", indent.c_str(), y_id.c_str(), expr.c_str()));
cell_exprs.push_back(stringf("%s%s <= %s\n", indent, y_id, expr));
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
}
@ -975,8 +975,8 @@ struct FirrtlWorker
if (a_width < y_width) {
a_expr = stringf("pad(%s, %d)", a_expr, y_width);
}
wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent.c_str(), y_id.c_str(), y_width));
cell_exprs.push_back(stringf("%s%s <= %s\n", indent.c_str(), y_id.c_str(), a_expr.c_str()));
wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent, y_id, y_width));
cell_exprs.push_back(stringf("%s%s <= %s\n", indent, y_id, a_expr));
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
}
@ -999,7 +999,7 @@ struct FirrtlWorker
for (int i = 0; i < GetSize(mem.rd_ports); i++)
{
auto &port = mem.rd_ports[i];
string port_name(stringf("%s.r%d", mem_id.c_str(), i));
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));
@ -1010,17 +1010,17 @@ struct FirrtlWorker
string ena_expr = make_expr(State::S1);
string clk_expr = make_expr(State::S0);
rpe << stringf("%s%s.addr <= %s\n", indent.c_str(), port_name.c_str(), addr_expr.c_str());
rpe << stringf("%s%s.en <= %s\n", indent.c_str(), port_name.c_str(), ena_expr.c_str());
rpe << stringf("%s%s.clk <= asClock(%s)\n", indent.c_str(), port_name.c_str(), clk_expr.c_str());
rpe << stringf("%s%s.addr <= %s\n", indent, port_name, addr_expr);
rpe << stringf("%s%s.en <= %s\n", indent, port_name, ena_expr);
rpe << stringf("%s%s.clk <= asClock(%s)\n", indent, port_name, clk_expr);
cell_exprs.push_back(rpe.str());
register_reverse_wire_map(stringf("%s.data", port_name.c_str()), port.data);
register_reverse_wire_map(stringf("%s.data", port_name), port.data);
}
for (int i = 0; i < GetSize(mem.wr_ports); i++)
{
auto &port = mem.wr_ports[i];
string port_name(stringf("%s.w%d", mem_id.c_str(), i));
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));
@ -1037,18 +1037,18 @@ struct FirrtlWorker
string ena_expr = make_expr(port.en[0]);
string clk_expr = make_expr(port.clk);
string mask_expr = make_expr(State::S1);
wpe << stringf("%s%s.data <= %s\n", indent.c_str(), port_name.c_str(), data_expr.c_str());
wpe << stringf("%s%s.addr <= %s\n", indent.c_str(), port_name.c_str(), addr_expr.c_str());
wpe << stringf("%s%s.en <= %s\n", indent.c_str(), port_name.c_str(), ena_expr.c_str());
wpe << stringf("%s%s.clk <= asClock(%s)\n", indent.c_str(), port_name.c_str(), clk_expr.c_str());
wpe << stringf("%s%s.mask <= %s\n", indent.c_str(), port_name.c_str(), mask_expr.c_str());
wpe << stringf("%s%s.data <= %s\n", indent, port_name, data_expr);
wpe << stringf("%s%s.addr <= %s\n", indent, port_name, addr_expr);
wpe << stringf("%s%s.en <= %s\n", indent, port_name, ena_expr);
wpe << stringf("%s%s.clk <= asClock(%s)\n", indent, port_name, clk_expr);
wpe << stringf("%s%s.mask <= %s\n", indent, port_name, mask_expr);
cell_exprs.push_back(wpe.str());
}
std::ostringstream me;
me << stringf(" mem %s:\n", mem_id.c_str());
me << stringf(" mem %s:\n", mem_id);
me << stringf(" data-type => UInt<%d>\n", mem.width);
me << stringf(" depth => %d\n", mem.size);
for (int i = 0; i < GetSize(mem.rd_ports); i++)
@ -1068,8 +1068,8 @@ struct FirrtlWorker
int y_width = GetSize(conn.first);
string expr = make_expr(conn.second);
wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent.c_str(), y_id.c_str(), y_width));
cell_exprs.push_back(stringf("%s%s <= %s\n", indent.c_str(), y_id.c_str(), expr.c_str()));
wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent, y_id, y_width));
cell_exprs.push_back(stringf("%s%s <= %s\n", indent, y_id, expr));
register_reverse_wire_map(y_id, conn.first);
}
@ -1112,7 +1112,7 @@ struct FirrtlWorker
chunk_width++;
}
new_expr = stringf("bits(%s, %d, %d)", start_map.first.c_str(),
new_expr = stringf("bits(%s, %d, %d)", start_map.first,
start_map.second + chunk_width - 1, start_map.second);
is_valid = true;
}
@ -1135,13 +1135,13 @@ struct FirrtlWorker
if (is_valid) {
if (make_unconn_id) {
wire_decls.push_back(stringf("%swire %s: UInt<1> %s\n", indent.c_str(), unconn_id.c_str(), wireFileinfo.c_str()));
wire_decls.push_back(stringf("%swire %s: UInt<1> %s\n", indent, unconn_id, wireFileinfo));
// `invalid` is a firrtl construction for simulation so we will not
// tag it with a @[fileinfo] tag as it doesn't directly correspond to
// a specific line of verilog code.
wire_decls.push_back(stringf("%s%s is invalid\n", indent.c_str(), unconn_id.c_str()));
wire_decls.push_back(stringf("%s%s is invalid\n", indent, unconn_id));
}
wire_exprs.push_back(stringf("%s%s <= %s %s\n", indent.c_str(), make_id(wire->name), expr.c_str(), wireFileinfo.c_str()));
wire_exprs.push_back(stringf("%s%s <= %s %s\n", indent, make_id(wire->name), expr, wireFileinfo));
} else {
if (make_unconn_id) {
unconn_id.clear();
@ -1149,7 +1149,7 @@ struct FirrtlWorker
// `invalid` is a firrtl construction for simulation so we will not
// tag it with a @[fileinfo] tag as it doesn't directly correspond to
// a specific line of verilog code.
wire_decls.push_back(stringf("%s%s is invalid\n", indent.c_str(), make_id(wire->name)));
wire_decls.push_back(stringf("%s%s is invalid\n", indent, make_id(wire->name)));
}
}
@ -1249,7 +1249,7 @@ struct FirrtlBackend : public Backend {
log_cmd_error("There is no top module in this design!\n");
std::string circuitFileinfo = getFileinfo(top);
*f << stringf("circuit %s: %s\n", make_id(top->name), circuitFileinfo.c_str());
*f << stringf("circuit %s: %s\n", make_id(top->name), circuitFileinfo);
emit_elaborated_extmodules(design, *f);

View file

@ -268,7 +268,7 @@ struct FunctionalCxxBackend : public Backend
extra_args(f, filename, args, argidx, design);
for (auto module : design->selected_modules()) {
log("Dumping module `%s'.\n", module->name.c_str());
log("Dumping module `%s'.\n", module->name);
printCxx(*f, filename, module);
}
}

View file

@ -285,7 +285,7 @@ struct FunctionalSmtBackend : public Backend {
extra_args(f, filename, args, argidx, design);
for (auto module : design->selected_modules()) {
log("Processing module `%s`.\n", module->name.c_str());
log("Processing module `%s`.\n", module->name);
SmtModule smt(module);
smt.write(*f);
}

View file

@ -307,7 +307,7 @@ struct FunctionalSmtrBackend : public Backend {
}
for (auto module : design->selected_modules()) {
log("Processing module `%s`.\n", module->name.c_str());
log("Processing module `%s`.\n", module->name);
SmtrModule smtr(module);
smtr.write(*f);
}

View file

@ -105,7 +105,7 @@ struct MemContentsTest {
RTLIL::Const values;
for(addr_t addr = low; addr <= high; addr++) {
RTLIL::Const word(data_dist(rnd), data_width);
values.bits().insert(values.bits().end(), word.begin(), word.end());
values.append(word);
}
insert_concatenated(low, values);
}
@ -143,7 +143,7 @@ struct FunctionalTestGeneric : public Pass
*/
for (auto module : design->selected_modules()) {
log("Dumping module `%s'.\n", module->name.c_str());
log("Dumping module `%s'.\n", module->name);
auto fir = Functional::IR::from_module(module);
for(auto node : fir)
std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n";

View file

@ -100,13 +100,13 @@ struct IntersynthBackend : public Backend {
}
extra_args(f, filename, args, argidx);
log("Output filename: %s\n", filename.c_str());
log("Output filename: %s\n", filename);
for (auto filename : libfiles) {
std::ifstream f;
f.open(filename.c_str());
if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str());
log_error("Can't open lib file `%s'.\n", filename);
RTLIL::Design *lib = new RTLIL::Design;
Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "rtlil" : "verilog"));
libs.push_back(lib);

View file

@ -125,7 +125,7 @@ struct JnyWriter
f << "{\n";
f << " \"$schema\": \"https://raw.githubusercontent.com/YosysHQ/yosys/main/misc/jny.schema.json\",\n";
f << stringf(" \"generator\": \"%s\",\n", escape_string(yosys_maybe_version()).c_str());
f << stringf(" \"generator\": \"%s\",\n", escape_string(yosys_maybe_version()));
f << " \"version\": \"0.0.1\",\n";
f << " \"invocation\": \"" << escape_string(invk) << "\",\n";
f << " \"features\": [";
@ -232,7 +232,7 @@ struct JnyWriter
const auto _indent = gen_indent(indent_level);
f << _indent << "{\n";
f << stringf(" %s\"name\": \"%s\",\n", _indent.c_str(), escape_string(RTLIL::unescape_id(mod->name)).c_str());
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(mod->name)));
f << _indent << " \"cell_sorts\": [\n";
bool first_sort{true};
@ -280,7 +280,7 @@ struct JnyWriter
f << ",\n";
f << _indent << " {\n";
f << stringf(" %s\"name\": \"%s\",\n", _indent.c_str(), escape_string(RTLIL::unescape_id(con.first)).c_str());
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(con.first)));
f << _indent << " \"direction\": \"";
if (port_cell->input(con.first))
f << "i";
@ -290,7 +290,7 @@ struct JnyWriter
if (con.second.size() == 1)
f << _indent << " \"range\": [0, 0]\n";
else
f << stringf(" %s\"range\": [%d, %d]\n", _indent.c_str(), con.second.size(), 0);
f << stringf(" %s\"range\": [%d, %d]\n", _indent, con.second.size(), 0);
f << _indent << " }";
first_port = false;
@ -304,7 +304,7 @@ struct JnyWriter
const auto _indent = gen_indent(indent_level);
f << _indent << "{\n";
f << stringf(" %s\"type\": \"%s\",\n", _indent.c_str(), sort.first.c_str());
f << stringf(" %s\"type\": \"%s\",\n", _indent, sort.first);
f << _indent << " \"ports\": [\n";
write_cell_ports(port_cell, indent_level + 2);
@ -351,10 +351,10 @@ struct JnyWriter
f << stringf(",\n");
const auto param_val = param.second;
if (!param_val.empty()) {
f << stringf(" %s\"%s\": ", _indent.c_str(), escape_string(RTLIL::unescape_id(param.first)).c_str());
f << stringf(" %s\"%s\": ", _indent, escape_string(RTLIL::unescape_id(param.first)));
write_param_val(param_val);
} else {
f << stringf(" %s\"%s\": true", _indent.c_str(), escape_string(RTLIL::unescape_id(param.first)).c_str());
f << stringf(" %s\"%s\": true", _indent, escape_string(RTLIL::unescape_id(param.first)));
}
first_param = false;
@ -366,7 +366,7 @@ struct JnyWriter
log_assert(cell != nullptr);
f << _indent << " {\n";
f << stringf(" %s\"name\": \"%s\"", _indent.c_str(), escape_string(RTLIL::unescape_id(cell->name)).c_str());
f << stringf(" %s\"name\": \"%s\"", _indent, escape_string(RTLIL::unescape_id(cell->name)));
if (_include_connections) {
f << ",\n" << _indent << " \"connections\": [\n";
@ -553,7 +553,7 @@ struct JnyPass : public Pass {
ff->open(filename.c_str(), std::ofstream::trunc);
if (ff->fail()) {
delete ff;
log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
log_error("Can't open file `%s' for writing: %s\n", filename, strerror(errno));
}
f = ff;
invk << filename;
@ -568,7 +568,7 @@ struct JnyPass : public Pass {
if (!empty) {
delete f;
} else {
log("%s", buf.str().c_str());
log("%s", buf.str());
}
}

View file

@ -135,7 +135,7 @@ struct JsonWriter
bool first = true;
for (auto &param : parameters) {
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str());
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first));
write_parameter_value(param.second);
first = false;
}
@ -155,7 +155,7 @@ struct JsonWriter
log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", log_id(module));
}
f << stringf(" %s: {\n", get_name(module->name).c_str());
f << stringf(" %s: {\n", get_name(module->name));
f << stringf(" \"attributes\": {");
write_parameters(module->attributes, /*for_module=*/true);
@ -174,7 +174,7 @@ struct JsonWriter
if (use_selection && !module->selected(w))
continue;
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s: {\n", get_name(n).c_str());
f << stringf(" %s: {\n", get_name(n));
f << stringf(" \"direction\": \"%s\",\n", w->port_input ? w->port_output ? "inout" : "input" : "output");
if (w->start_offset)
f << stringf(" \"offset\": %d,\n", w->start_offset);
@ -182,7 +182,7 @@ struct JsonWriter
f << stringf(" \"upto\": 1,\n");
if (w->is_signed)
f << stringf(" \"signed\": %d,\n", w->is_signed);
f << stringf(" \"bits\": %s\n", get_bits(w).c_str());
f << stringf(" \"bits\": %s\n", get_bits(w));
f << stringf(" }");
first = false;
}
@ -196,13 +196,13 @@ struct JsonWriter
if (!scopeinfo_mode && c->type == ID($scopeinfo))
continue;
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s: {\n", get_name(c->name).c_str());
f << stringf(" %s: {\n", get_name(c->name));
f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
f << stringf(" \"type\": %s,\n", get_name(c->type).c_str());
f << stringf(" \"type\": %s,\n", get_name(c->type));
if (aig_mode) {
Aig aig(c);
if (!aig.name.empty()) {
f << stringf(" \"model\": \"%s\",\n", aig.name.c_str());
f << stringf(" \"model\": \"%s\",\n", aig.name);
aig_models.insert(aig);
}
}
@ -220,7 +220,7 @@ struct JsonWriter
if (c->input(conn.first))
direction = c->output(conn.first) ? "inout" : "input";
f << stringf("%s\n", first2 ? "" : ",");
f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
f << stringf(" %s: \"%s\"", get_name(conn.first), direction);
first2 = false;
}
f << stringf("\n },\n");
@ -229,7 +229,7 @@ struct JsonWriter
bool first2 = true;
for (auto &conn : c->connections()) {
f << stringf("%s\n", first2 ? "" : ",");
f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
f << stringf(" %s: %s", get_name(conn.first), get_bits(conn.second));
first2 = false;
}
f << stringf("\n }\n");
@ -245,7 +245,7 @@ struct JsonWriter
if (use_selection && !module->selected(it.second))
continue;
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s: {\n", get_name(it.second->name).c_str());
f << stringf(" %s: {\n", get_name(it.second->name));
f << stringf(" \"hide_name\": %s,\n", it.second->name[0] == '$' ? "1" : "0");
f << stringf(" \"attributes\": {");
write_parameters(it.second->attributes);
@ -265,9 +265,9 @@ struct JsonWriter
if (use_selection && !module->selected(w))
continue;
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s: {\n", get_name(w->name).c_str());
f << stringf(" %s: {\n", get_name(w->name));
f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
f << stringf(" \"bits\": %s,\n", get_bits(w).c_str());
f << stringf(" \"bits\": %s,\n", get_bits(w));
if (w->start_offset)
f << stringf(" \"offset\": %d,\n", w->start_offset);
if (w->upto)
@ -291,7 +291,7 @@ struct JsonWriter
design->sort();
f << stringf("{\n");
f << stringf(" \"creator\": %s,\n", get_string(yosys_maybe_version()).c_str());
f << stringf(" \"creator\": %s,\n", get_string(yosys_maybe_version()));
f << stringf(" \"modules\": {\n");
vector<Module*> modules = use_selection ? design->selected_modules() : design->modules();
bool first_module = true;
@ -308,7 +308,7 @@ struct JsonWriter
for (auto &aig : aig_models) {
if (!first_model)
f << stringf(",\n");
f << stringf(" \"%s\": [\n", aig.name.c_str());
f << stringf(" \"%s\": [\n", aig.name);
int node_idx = 0;
for (auto &node : aig.nodes) {
if (node_idx != 0)
@ -701,7 +701,7 @@ struct JsonPass : public Pass {
ff->open(filename.c_str(), std::ofstream::trunc);
if (ff->fail()) {
delete ff;
log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
log_error("Can't open file `%s' for writing: %s\n", filename, strerror(errno));
}
f = ff;
} else {
@ -714,7 +714,7 @@ struct JsonPass : public Pass {
if (!empty) {
delete f;
} else {
log("%s", buf.str().c_str());
log("%s", buf.str());
}
}
} JsonPass;

View file

@ -24,12 +24,23 @@
#include "rtlil_backend.h"
#include "kernel/yosys.h"
#include "kernel/utils.h"
#include <errno.h>
#include <iterator>
USING_YOSYS_NAMESPACE
using namespace RTLIL_BACKEND;
YOSYS_NAMESPACE_BEGIN
void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj)
{
for (const auto& [name, value] : reversed(obj->attributes)) {
f << stringf("%s" "attribute %s ", indent, name);
dump_const(f, value);
f << stringf("\n");
}
}
void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint)
{
if (width < 0)
@ -96,11 +107,11 @@ void RTLIL_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk,
dump_const(f, chunk.data, chunk.width, chunk.offset, autoint);
} else {
if (chunk.width == chunk.wire->width && chunk.offset == 0)
f << stringf("%s", chunk.wire->name.c_str());
f << stringf("%s", chunk.wire->name);
else if (chunk.width == 1)
f << stringf("%s [%d]", chunk.wire->name.c_str(), chunk.offset);
f << stringf("%s [%d]", chunk.wire->name, chunk.offset);
else
f << stringf("%s [%d:%d]", chunk.wire->name.c_str(), chunk.offset+chunk.width-1, chunk.offset);
f << stringf("%s [%d:%d]", chunk.wire->name, chunk.offset+chunk.width-1, chunk.offset);
}
}
@ -110,8 +121,8 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
dump_sigchunk(f, sig.as_chunk(), autoint);
} else {
f << stringf("{ ");
for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) {
dump_sigchunk(f, *it, false);
for (const auto& chunk : reversed(sig.chunks())) {
dump_sigchunk(f, chunk, false);
f << stringf(" ");
}
f << stringf("}");
@ -120,16 +131,12 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire)
{
for (auto &it : wire->attributes) {
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
dump_const(f, it.second);
f << stringf("\n");
}
dump_attributes(f, indent, wire);
if (wire->driverCell_) {
f << stringf("%s" "# driver %s %s\n", indent.c_str(),
wire->driverCell()->name.c_str(), wire->driverPort().c_str());
f << stringf("%s" "# driver %s %s\n", indent,
wire->driverCell()->name, wire->driverPort());
}
f << stringf("%s" "wire ", indent.c_str());
f << stringf("%s" "wire ", indent);
if (wire->width != 1)
f << stringf("width %d ", wire->width);
if (wire->upto)
@ -144,101 +151,84 @@ void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::
f << stringf("inout %d ", wire->port_id);
if (wire->is_signed)
f << stringf("signed ");
f << stringf("%s\n", wire->name.c_str());
f << stringf("%s\n", wire->name);
}
void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory)
{
for (auto &it : memory->attributes) {
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
dump_const(f, it.second);
f << stringf("\n");
}
f << stringf("%s" "memory ", indent.c_str());
dump_attributes(f, indent, memory);
f << stringf("%s" "memory ", indent);
if (memory->width != 1)
f << stringf("width %d ", memory->width);
if (memory->size != 0)
f << stringf("size %d ", memory->size);
if (memory->start_offset != 0)
f << stringf("offset %d ", memory->start_offset);
f << stringf("%s\n", memory->name.c_str());
f << stringf("%s\n", memory->name);
}
void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
{
for (auto &it : cell->attributes) {
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
dump_const(f, it.second);
dump_attributes(f, indent, cell);
f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name);
for (const auto& [name, param] : reversed(cell->parameters)) {
f << stringf("%s parameter%s%s %s ", indent,
(param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
(param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
name);
dump_const(f, param);
f << stringf("\n");
}
f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str());
for (auto &it : cell->parameters) {
f << stringf("%s parameter%s%s %s ", indent.c_str(),
(it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
(it.second.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
it.first.c_str());
dump_const(f, it.second);
for (const auto& [port, sig] : reversed(cell->connections_)) {
f << stringf("%s connect %s ", indent, port);
dump_sigspec(f, sig);
f << stringf("\n");
}
for (auto &it : cell->connections()) {
f << stringf("%s connect %s ", indent.c_str(), it.first.c_str());
dump_sigspec(f, it.second);
f << stringf("\n");
}
f << stringf("%s" "end\n", indent.c_str());
f << stringf("%s" "end\n", indent);
}
void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs)
{
for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it)
{
f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, it->first);
for (const auto& [lhs, rhs] : cs->actions) {
f << stringf("%s" "assign ", indent);
dump_sigspec(f, lhs);
f << stringf(" ");
dump_sigspec(f, it->second);
dump_sigspec(f, rhs);
f << stringf("\n");
}
for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it)
dump_proc_switch(f, indent, *it);
for (const auto& sw : cs->switches)
dump_proc_switch(f, indent, sw);
}
void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw)
{
for (auto it = sw->attributes.begin(); it != sw->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
dump_const(f, it->second);
f << stringf("\n");
}
dump_attributes(f, indent, sw);
f << stringf("%s" "switch ", indent.c_str());
f << stringf("%s" "switch ", indent);
dump_sigspec(f, sw->signal);
f << stringf("\n");
for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it)
for (const auto case_ : sw->cases)
{
for (auto ait = (*it)->attributes.begin(); ait != (*it)->attributes.end(); ++ait) {
f << stringf("%s attribute %s ", indent.c_str(), ait->first.c_str());
dump_const(f, ait->second);
f << stringf("\n");
}
f << stringf("%s case ", indent.c_str());
for (size_t i = 0; i < (*it)->compare.size(); i++) {
dump_attributes(f, indent, case_);
f << stringf("%s case ", indent);
for (size_t i = 0; i < case_->compare.size(); i++) {
if (i > 0)
f << stringf(" , ");
dump_sigspec(f, (*it)->compare[i]);
dump_sigspec(f, case_->compare[i]);
}
f << stringf("\n");
dump_proc_case_body(f, indent + " ", *it);
dump_proc_case_body(f, indent + " ", case_);
}
f << stringf("%s" "end\n", indent.c_str());
f << stringf("%s" "end\n", indent);
}
void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy)
{
f << stringf("%s" "sync ", indent.c_str());
f << stringf("%s" "sync ", indent);
switch (sy->type) {
case RTLIL::ST0: f << stringf("low ");
if (0) case RTLIL::ST1: f << stringf("high ");
@ -253,21 +243,17 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
case RTLIL::STi: f << stringf("init\n"); break;
}
for (auto &it: sy->actions) {
f << stringf("%s update ", indent.c_str());
dump_sigspec(f, it.first);
for (const auto& [lhs, rhs] : sy->actions) {
f << stringf("%s update ", indent);
dump_sigspec(f, lhs);
f << stringf(" ");
dump_sigspec(f, it.second);
dump_sigspec(f, rhs);
f << stringf("\n");
}
for (auto &it: sy->mem_write_actions) {
for (auto it2 = it.attributes.begin(); it2 != it.attributes.end(); ++it2) {
f << stringf("%s attribute %s ", indent.c_str(), it2->first.c_str());
dump_const(f, it2->second);
f << stringf("\n");
}
f << stringf("%s memwr %s ", indent.c_str(), it.memid.c_str());
dump_attributes(f, indent, &it);
f << stringf("%s memwr %s ", indent, it.memid);
dump_sigspec(f, it.address);
f << stringf(" ");
dump_sigspec(f, it.data);
@ -281,21 +267,17 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
void RTLIL_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc)
{
for (auto it = proc->attributes.begin(); it != proc->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
dump_const(f, it->second);
f << stringf("\n");
}
f << stringf("%s" "process %s\n", indent.c_str(), proc->name.c_str());
dump_attributes(f, indent, proc);
f << stringf("%s" "process %s\n", indent, proc->name);
dump_proc_case_body(f, indent + " ", &proc->root_case);
for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it)
dump_proc_sync(f, indent + " ", *it);
f << stringf("%s" "end\n", indent.c_str());
for (auto* sync : proc->syncs)
dump_proc_sync(f, indent + " ", sync);
f << stringf("%s" "end\n", indent);
}
void RTLIL_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
{
f << stringf("%s" "connect ", indent.c_str());
f << stringf("%s" "connect ", indent);
dump_sigspec(f, left);
f << stringf(" ");
dump_sigspec(f, right);
@ -309,13 +291,9 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
if (print_header)
{
for (auto it = module->attributes.begin(); it != module->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
dump_const(f, it->second);
f << stringf("\n");
}
dump_attributes(f, indent, module);
f << stringf("%s" "module %s\n", indent.c_str(), module->name.c_str());
f << stringf("%s" "module %s\n", indent, module->name);
if (!module->avail_parameters.empty()) {
if (only_selected)
@ -323,9 +301,9 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
for (const auto &p : module->avail_parameters) {
const auto &it = module->parameter_default_values.find(p);
if (it == module->parameter_default_values.end()) {
f << stringf("%s" " parameter %s\n", indent.c_str(), p.c_str());
f << stringf("%s" " parameter %s\n", indent, p);
} else {
f << stringf("%s" " parameter %s ", indent.c_str(), p.c_str());
f << stringf("%s" " parameter %s ", indent, p);
dump_const(f, it->second);
f << stringf("\n");
}
@ -335,40 +313,40 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
if (print_body)
{
for (auto it : module->wires())
if (!only_selected || design->selected(module, it)) {
for (const auto& [_, wire] : reversed(module->wires_))
if (!only_selected || design->selected(module, wire)) {
if (only_selected)
f << stringf("\n");
dump_wire(f, indent + " ", it);
dump_wire(f, indent + " ", wire);
}
for (auto it : module->memories)
if (!only_selected || design->selected(module, it.second)) {
for (const auto& [_, mem] : reversed(module->memories))
if (!only_selected || design->selected(module, mem)) {
if (only_selected)
f << stringf("\n");
dump_memory(f, indent + " ", it.second);
dump_memory(f, indent + " ", mem);
}
for (auto it : module->cells())
if (!only_selected || design->selected(module, it)) {
for (const auto& [_, cell] : reversed(module->cells_))
if (!only_selected || design->selected(module, cell)) {
if (only_selected)
f << stringf("\n");
dump_cell(f, indent + " ", it);
dump_cell(f, indent + " ", cell);
}
for (auto it : module->processes)
if (!only_selected || design->selected(module, it.second)) {
for (const auto& [_, process] : reversed(module->processes))
if (!only_selected || design->selected(module, process)) {
if (only_selected)
f << stringf("\n");
dump_proc(f, indent + " ", it.second);
dump_proc(f, indent + " ", process);
}
bool first_conn_line = true;
for (auto it = module->connections().begin(); it != module->connections().end(); ++it) {
for (const auto& [lhs, rhs] : module->connections()) {
bool show_conn = !only_selected || design->selected_whole_module(module->name);
if (!show_conn) {
RTLIL::SigSpec sigs = it->first;
sigs.append(it->second);
RTLIL::SigSpec sigs = lhs;
sigs.append(rhs);
for (auto &c : sigs.chunks()) {
if (c.wire == NULL || !design->selected(module, c.wire))
continue;
@ -378,14 +356,14 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
if (show_conn) {
if (only_selected && first_conn_line)
f << stringf("\n");
dump_conn(f, indent + " ", it->first, it->second);
dump_conn(f, indent + " ", lhs, rhs);
first_conn_line = false;
}
}
}
if (print_header)
f << stringf("%s" "end\n", indent.c_str());
f << stringf("%s" "end\n", indent);
}
void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
@ -394,7 +372,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
if (!flag_m) {
int count_selected_mods = 0;
for (auto module : design->modules()) {
for (auto* module : design->modules()) {
if (design->selected_whole_module(module->name))
flag_m = true;
if (design->selected(module))
@ -410,7 +388,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
f << stringf("autoidx %d\n", autoidx);
}
for (auto module : design->modules()) {
for (const auto& [_, module] : reversed(design->modules_)) {
if (!only_selected || design->selected(module)) {
if (only_selected)
f << stringf("\n");
@ -438,10 +416,14 @@ struct RTLILBackend : public Backend {
log(" -selected\n");
log(" only write selected parts of the design.\n");
log("\n");
log(" -sort\n");
log(" sort design in-place (used to be default).\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
bool selected = false;
bool do_sort = false;
log_header(design, "Executing RTLIL backend.\n");
@ -452,13 +434,18 @@ struct RTLILBackend : public Backend {
selected = true;
continue;
}
if (arg == "-sort") {
do_sort = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
design->sort();
log("Output filename: %s\n", filename);
log("Output filename: %s\n", filename.c_str());
if (do_sort)
design->sort();
*f << stringf("# Generated by %s\n", yosys_maybe_version());
RTLIL_BACKEND::dump_design(*f, design, selected, true, false);
@ -528,10 +515,10 @@ struct DumpPass : public Pass {
if (!empty) {
rewrite_filename(filename);
std::ofstream *ff = new std::ofstream;
ff->open(filename.c_str(), append ? std::ofstream::app : std::ofstream::trunc);
ff->open(filename, append ? std::ofstream::app : std::ofstream::trunc);
if (ff->fail()) {
delete ff;
log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
log_error("Can't open file `%s' for writing: %s\n", filename, strerror(errno));
}
f = ff;
} else {
@ -543,7 +530,7 @@ struct DumpPass : public Pass {
if (!empty) {
delete f;
} else {
log("%s", buf.str().c_str());
log("%s", buf.str());
}
}
} DumpPass;

View file

@ -31,6 +31,7 @@
YOSYS_NAMESPACE_BEGIN
namespace RTLIL_BACKEND {
void dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj);
void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true);
void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true);
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true);

View file

@ -504,7 +504,7 @@ struct SimplecWorker
while (work->dirty)
{
if (verbose && (!work->dirty_bits.empty() || !work->dirty_cells.empty()))
log(" In %s:\n", work->log_prefix.c_str());
log(" In %s:\n", work->log_prefix);
while (!work->dirty_bits.empty() || !work->dirty_cells.empty())
{
@ -517,7 +517,7 @@ struct SimplecWorker
if (chunk.wire == nullptr)
continue;
if (verbose)
log(" Propagating %s.%s[%d:%d].\n", work->log_prefix.c_str(), log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset);
log(" Propagating %s.%s[%d:%d].\n", work->log_prefix, log_id(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,7 +539,7 @@ struct SimplecWorker
work->parent->set_dirty(parent_bit);
if (verbose)
log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset,
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);
}
@ -556,11 +556,11 @@ struct SimplecWorker
child->set_dirty(child_bit);
if (verbose)
log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset,
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);
} else {
if (verbose)
log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix.c_str(), log_id(std::get<0>(port)),
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);
work->set_dirty(std::get<0>(port));
}
@ -579,7 +579,7 @@ struct SimplecWorker
string hiername = work->log_prefix + "." + log_id(cell);
if (verbose)
log(" Evaluating %s (%s, best of %d).\n", hiername.c_str(), log_id(cell->type), GetSize(work->dirty_cells));
log(" Evaluating %s (%s, best of %d).\n", hiername, log_id(cell->type), GetSize(work->dirty_cells));
if (activated_cells.count(hiername))
reactivated_cells.insert(hiername);
@ -630,7 +630,7 @@ struct SimplecWorker
void make_func(HierDirtyFlags *work, const string &func_name, const vector<string> &preamble)
{
log("Generating function %s():\n", func_name.c_str());
log("Generating function %s():\n", func_name);
activated_cells.clear();
reactivated_cells.clear();
@ -657,7 +657,7 @@ struct SimplecWorker
{
SigSpec sig = sigmaps.at(module)(w);
Const val = w->attributes.at(ID::init);
val.bits().resize(GetSize(sig), State::Sx);
val.resize(GetSize(sig), State::Sx);
for (int i = 0; i < GetSize(sig); i++)
if (val[i] == State::S0 || val[i] == State::S1) {

View file

@ -82,27 +82,27 @@ struct Smt2Worker
if (statebv)
{
if (width == 0) {
decl_str = stringf("(define-fun |%s| ((state |%s_s|)) Bool (= ((_ extract %d %d) state) #b1))", name.c_str(), get_id(module), statebv_width, statebv_width);
decl_str = stringf("(define-fun |%s| ((state |%s_s|)) Bool (= ((_ extract %d %d) state) #b1))", name, get_id(module), statebv_width, statebv_width);
statebv_width += 1;
} else {
decl_str = stringf("(define-fun |%s| ((state |%s_s|)) (_ BitVec %d) ((_ extract %d %d) state))", name.c_str(), get_id(module), width, statebv_width+width-1, statebv_width);
decl_str = stringf("(define-fun |%s| ((state |%s_s|)) (_ BitVec %d) ((_ extract %d %d) state))", name, get_id(module), width, statebv_width+width-1, statebv_width);
statebv_width += width;
}
}
else if (statedt)
{
if (width == 0) {
decl_str = stringf(" (|%s| Bool)", name.c_str());
decl_str = stringf(" (|%s| Bool)", name);
} else {
decl_str = stringf(" (|%s| (_ BitVec %d))", name.c_str(), width);
decl_str = stringf(" (|%s| (_ BitVec %d))", name, width);
}
}
else
{
if (width == 0) {
decl_str = stringf("(declare-fun |%s| (|%s_s|) Bool)", name.c_str(), get_id(module));
decl_str = stringf("(declare-fun |%s| (|%s_s|) Bool)", name, get_id(module));
} else {
decl_str = stringf("(declare-fun |%s| (|%s_s|) (_ BitVec %d))", name.c_str(), get_id(module), width);
decl_str = stringf("(declare-fun |%s| (|%s_s|) (_ BitVec %d))", name, get_id(module), width);
}
}
@ -130,7 +130,7 @@ struct Smt2Worker
for (auto &mem : memories)
{
if (is_smtlib2_module)
log_error("Memory %s.%s not allowed in module with smtlib2_module attribute", get_id(module), mem.memid.c_str());
log_error("Memory %s.%s not allowed in module with smtlib2_module attribute", get_id(module), mem.memid);
mem.narrow();
mem_dict[mem.memid] = &mem;
@ -383,7 +383,7 @@ struct Smt2Worker
}
if (fcache.count(sig[i]) && fcache.at(sig[i]).second == -1) {
subexpr.push_back(stringf("(ite %s #b1 #b0)", get_bool(sig[i], state_name).c_str()));
subexpr.push_back(stringf("(ite %s #b1 #b0)", get_bool(sig[i], state_name)));
continue;
}
@ -495,7 +495,7 @@ struct Smt2Worker
}
if (width != GetSize(sig_y) && type != 'b')
processed_expr = stringf("((_ extract %d 0) %s)", GetSize(sig_y)-1, processed_expr.c_str());
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));
@ -617,14 +617,14 @@ struct Smt2Worker
string infostr = cell->attributes.count(ID::src) ? cell->attributes.at(ID::src).decode_string().c_str() : get_id(cell);
if (cell->attributes.count(ID::reg))
infostr += " " + cell->attributes.at(ID::reg).decode_string();
decls.push_back(stringf("; yosys-smt2-%s %s#%d %d %s\n", cell->type.c_str() + 1, get_id(module), idcounter, GetSize(cell->getPort(QY)), infostr.c_str()));
decls.push_back(stringf("; yosys-smt2-%s %s#%d %d %s\n", cell->type.c_str() + 1, get_id(module), idcounter, GetSize(cell->getPort(QY)), infostr));
if (cell->getPort(QY).is_wire() && cell->getPort(QY).as_wire()->get_bool_attribute(ID::maximize)){
decls.push_back(stringf("; yosys-smt2-maximize %s#%d\n", get_id(module), idcounter));
log("Wire %s is maximized\n", cell->getPort(QY).as_wire()->name.str().c_str());
log("Wire %s is maximized\n", cell->getPort(QY).as_wire()->name.str());
}
else if (cell->getPort(QY).is_wire() && cell->getPort(QY).as_wire()->get_bool_attribute(ID::minimize)){
decls.push_back(stringf("; yosys-smt2-minimize %s#%d\n", get_id(module), idcounter));
log("Wire %s is minimized\n", cell->getPort(QY).as_wire()->name.str().c_str());
log("Wire %s is minimized\n", cell->getPort(QY).as_wire()->name.str());
}
bool init_only = cell->type.in(ID($anyconst), ID($anyinit), ID($allconst));
@ -722,7 +722,7 @@ struct Smt2Worker
2*GetSize(cell->getPort(ID::A).chunks()) < GetSize(cell->getPort(ID::A))) {
bool is_and = cell->type == ID($reduce_and);
string bits(GetSize(cell->getPort(ID::A)), is_and ? '1' : '0');
return export_bvop(cell, stringf("(%s A #b%s)", is_and ? "=" : "distinct", bits.c_str()), 'b');
return export_bvop(cell, stringf("(%s A #b%s)", is_and ? "=" : "distinct", bits), 'b');
}
if (cell->type == ID($reduce_and)) return export_reduce(cell, "(and A)", true);
@ -746,7 +746,7 @@ struct Smt2Worker
get_bv(sig_s);
for (int i = 0; i < GetSize(sig_s); i++)
processed_expr = stringf("(ite %s %s %s)", get_bool(sig_s[i]).c_str(),
processed_expr = stringf("(ite %s %s %s)", get_bool(sig_s[i]),
get_bv(sig_b.extract(i*width, width)).c_str(), processed_expr.c_str());
if (verbose)
@ -1079,24 +1079,24 @@ struct Smt2Worker
RTLIL::SigSpec sig = sigmap(wire);
Const val = wire->attributes.at(ID::init);
val.bits().resize(GetSize(sig), State::Sx);
val.resize(GetSize(sig), State::Sx);
if (bvmode && GetSize(sig) > 1) {
Const mask(State::S1, GetSize(sig));
bool use_mask = false;
for (int i = 0; i < GetSize(sig); i++)
if (val[i] != State::S0 && val[i] != State::S1) {
val.bits()[i] = State::S0;
mask.bits()[i] = State::S0;
val.set(i, State::S0);
mask.set(i, State::S0);
use_mask = true;
}
if (use_mask)
init_list.push_back(stringf("(= (bvand %s #b%s) #b%s) ; %s", get_bv(sig).c_str(), mask.as_string().c_str(), val.as_string().c_str(), get_id(wire)));
init_list.push_back(stringf("(= (bvand %s #b%s) #b%s) ; %s", get_bv(sig), mask.as_string(), val.as_string(), get_id(wire)));
else
init_list.push_back(stringf("(= %s #b%s) ; %s", get_bv(sig).c_str(), val.as_string().c_str(), get_id(wire)));
init_list.push_back(stringf("(= %s #b%s) ; %s", get_bv(sig), val.as_string(), get_id(wire)));
} else {
for (int i = 0; i < GetSize(sig); i++)
if (val[i] == State::S0 || val[i] == State::S1)
init_list.push_back(stringf("(= %s %s) ; %s", get_bool(sig[i]).c_str(), val[i] == State::S1 ? "true" : "false", get_id(wire)));
init_list.push_back(stringf("(= %s %s) ; %s", get_bool(sig[i]), val[i] == State::S1 ? "true" : "false", get_id(wire)));
}
}
@ -1131,7 +1131,7 @@ struct Smt2Worker
}
if (private_name && cell->attributes.count(ID::src))
decls.push_back(stringf("; yosys-smt2-%s %d %s %s\n", cell->type.c_str() + 1, id, get_id(cell), cell->attributes.at(ID::src).decode_string().c_str()));
decls.push_back(stringf("; yosys-smt2-%s %d %s %s\n", cell->type.c_str() + 1, id, get_id(cell), cell->attributes.at(ID::src).decode_string()));
else
decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, get_id(cell)));
@ -1180,11 +1180,11 @@ struct Smt2Worker
SigSpec sig = sigmap(conn.second);
if (bvmode || GetSize(w) == 1) {
hier.push_back(stringf(" (= %s (|%s_n %s| %s)) ; %s.%s\n", (GetSize(w) > 1 ? get_bv(sig) : get_bool(sig)).c_str(),
hier.push_back(stringf(" (= %s (|%s_n %s| %s)) ; %s.%s\n", (GetSize(w) > 1 ? get_bv(sig) : get_bool(sig)),
get_id(cell->type), get_id(w), cell_state.c_str(), get_id(cell->type), get_id(w)));
} else {
for (int i = 0; i < GetSize(w); i++)
hier.push_back(stringf(" (= %s (|%s_n %s %d| %s)) ; %s.%s[%d]\n", get_bool(sig[i]).c_str(),
hier.push_back(stringf(" (= %s (|%s_n %s %d| %s)) ; %s.%s[%d]\n", get_bool(sig[i]),
get_id(cell->type), get_id(w), i, cell_state.c_str(), get_id(cell->type), get_id(w), i));
}
}
@ -1204,25 +1204,25 @@ struct Smt2Worker
{
std::string expr_d = get_bool(cell->getPort(ID::D));
std::string expr_q = get_bool(cell->getPort(ID::Q), "next_state");
trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort(ID::Q))));
ex_state_eq.push_back(stringf("(= %s %s)", get_bool(cell->getPort(ID::Q)).c_str(), get_bool(cell->getPort(ID::Q), "other_state").c_str()));
trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d, expr_q, get_id(cell), log_signal(cell->getPort(ID::Q))));
ex_state_eq.push_back(stringf("(= %s %s)", get_bool(cell->getPort(ID::Q)), get_bool(cell->getPort(ID::Q), "other_state")));
}
if (cell->type.in(ID($ff), ID($dff), ID($anyinit)))
{
std::string expr_d = get_bv(cell->getPort(ID::D));
std::string expr_q = get_bv(cell->getPort(ID::Q), "next_state");
trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort(ID::Q))));
ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort(ID::Q)).c_str(), get_bv(cell->getPort(ID::Q), "other_state").c_str()));
trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d, expr_q, get_id(cell), log_signal(cell->getPort(ID::Q))));
ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort(ID::Q)), get_bv(cell->getPort(ID::Q), "other_state")));
}
if (cell->type.in(ID($anyconst), ID($allconst)))
{
std::string expr_d = get_bv(cell->getPort(ID::Y));
std::string expr_q = get_bv(cell->getPort(ID::Y), "next_state");
trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort(ID::Y))));
trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d, expr_q, get_id(cell), log_signal(cell->getPort(ID::Y))));
if (cell->type == ID($anyconst))
ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort(ID::Y)).c_str(), get_bv(cell->getPort(ID::Y), "other_state").c_str()));
ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort(ID::Y)), get_bv(cell->getPort(ID::Y), "other_state")));
}
}
@ -1341,11 +1341,11 @@ struct Smt2Worker
std::string expr_d = stringf("(|%s#%d#%d| state)", get_id(module), arrayid, GetSize(mem->wr_ports));
std::string expr_q = stringf("(|%s#%d#0| next_state)", get_id(module), arrayid);
trans.push_back(stringf(" (= %s %s) ; %s\n", expr_d.c_str(), expr_q.c_str(), get_id(mem->memid)));
trans.push_back(stringf(" (= %s %s) ; %s\n", expr_d, expr_q, get_id(mem->memid)));
ex_state_eq.push_back(stringf("(= (|%s#%d#0| state) (|%s#%d#0| other_state))", get_id(module), arrayid, get_id(module), arrayid));
if (has_async_wr)
hier.push_back(stringf(" (= %s (|%s| state)) ; %s\n", expr_d.c_str(), final_memstate.c_str(), get_id(mem->memid)));
hier.push_back(stringf(" (= %s (|%s| state)) ; %s\n", expr_d, final_memstate, get_id(mem->memid)));
Const init_data = mem->get_init_data();
@ -1361,10 +1361,10 @@ struct Smt2Worker
for (int k = 0; k < GetSize(initword); k++) {
if (initword[k] == State::S0 || initword[k] == State::S1) {
gen_init_constr = true;
initmask.bits()[k] = State::S1;
initmask.set(k, State::S1);
} else {
initmask.bits()[k] = State::S0;
initword.bits()[k] = State::S0;
initmask.set(k, State::S0);
initword.set(k, State::S0);
}
}
@ -1402,7 +1402,7 @@ struct Smt2Worker
expr = "\n " + ex_state_eq.front() + "\n";
} else {
for (auto &str : ex_state_eq)
expr += stringf("\n %s", str.c_str());
expr += stringf("\n %s", str);
expr += "\n)";
}
}
@ -1415,7 +1415,7 @@ struct Smt2Worker
expr = "\n " + ex_input_eq.front() + "\n";
} else {
for (auto &str : ex_input_eq)
expr += stringf("\n %s", str.c_str());
expr += stringf("\n %s", str);
expr += "\n)";
}
}
@ -1429,7 +1429,7 @@ struct Smt2Worker
assert_expr = "\n " + assert_list.front() + "\n";
} else {
for (auto &str : assert_list)
assert_expr += stringf("\n %s", str.c_str());
assert_expr += stringf("\n %s", str);
assert_expr += "\n)";
}
}
@ -1442,7 +1442,7 @@ struct Smt2Worker
assume_expr = "\n " + assume_list.front() + "\n";
} else {
for (auto &str : assume_list)
assume_expr += stringf("\n %s", str.c_str());
assume_expr += stringf("\n %s", str);
assume_expr += "\n)";
}
}
@ -1455,7 +1455,7 @@ struct Smt2Worker
init_expr = "\n " + init_list.front() + "\n";
} else {
for (auto &str : init_list)
init_expr += stringf("\n %s", str.c_str());
init_expr += stringf("\n %s", str);
init_expr += "\n)";
}
}
@ -1776,7 +1776,7 @@ struct Smt2Backend : public Backend {
if (args[argidx] == "-tpl" && argidx+1 < args.size()) {
template_f.open(args[++argidx]);
if (template_f.fail())
log_error("Can't open template file `%s'.\n", args[argidx].c_str());
log_error("Can't open template file `%s'.\n", args[argidx]);
continue;
}
if (args[argidx] == "-bv" || args[argidx] == "-mem") {
@ -1846,7 +1846,7 @@ struct Smt2Backend : public Backend {
*f << stringf("; yosys-smt2-stdt\n");
for (auto &it : solver_options)
*f << stringf("; yosys-smt2-solver-option %s %s\n", it.first.c_str(), it.second.c_str());
*f << stringf("; yosys-smt2-solver-option %s %s\n", it.first, it.second);
std::vector<RTLIL::Module*> sorted_modules;
@ -1913,7 +1913,7 @@ struct Smt2Backend : public Backend {
}
if (topmod)
*f << stringf("; yosys-smt2-topmod %s\n", topmod_id.c_str());
*f << stringf("; yosys-smt2-topmod %s\n", topmod_id);
*f << stringf("; end of yosys output\n");

View file

@ -59,7 +59,7 @@ struct SmvWorker
{
if (!idcache.count(id))
{
string name = stringf("_%s", id.c_str());
string name = stringf("_%s", id);
if (name.compare(0, 2, "_\\") == 0)
name = "_" + name.substr(2);
@ -163,15 +163,15 @@ struct SmvWorker
if (width >= 0) {
if (is_signed) {
if (GetSize(sig) > width)
s = stringf("signed(resize(%s, %d))", s.c_str(), width);
s = stringf("signed(resize(%s, %d))", s, width);
else
s = stringf("resize(signed(%s), %d)", s.c_str(), width);
s = stringf("resize(signed(%s), %d)", s, width);
} else
s = stringf("resize(%s, %d)", s.c_str(), width);
s = stringf("resize(%s, %d)", s, width);
} else if (is_signed)
s = stringf("signed(%s)", s.c_str());
s = stringf("signed(%s)", s);
else if (count_chunks > 1)
s = stringf("(%s)", s.c_str());
s = stringf("(%s)", s);
strbuf.push_back(s);
return strbuf.back().c_str();
@ -262,7 +262,7 @@ struct SmvWorker
if (cell->type == ID($sshr) && signed_a)
{
expr_a = rvalue_s(sig_a, width);
expr = stringf("resize(unsigned(%s %s %s), %d)", expr_a.c_str(), op.c_str(), rvalue(sig_b.extract(0, shift_b_width)), width_y);
expr = stringf("resize(unsigned(%s %s %s), %d)", expr_a, op, rvalue(sig_b.extract(0, shift_b_width)), width_y);
if (shift_b_width < GetSize(sig_b))
expr = stringf("%s != 0ud%d_0 ? (bool(%s) ? !0ud%d_0 : 0ud%d_0) : %s",
rvalue(sig_b.extract(shift_b_width, GetSize(sig_b) - shift_b_width)), GetSize(sig_b) - shift_b_width,
@ -278,8 +278,8 @@ struct SmvWorker
// f << stringf(" %s : unsigned word[%d]; -- neg(%s)\n", b_shl, GetSize(sig_b), log_signal(sig_b));
definitions.push_back(stringf("%s := unsigned(-%s);", b_shl, rvalue_s(sig_b)));
string expr_shl = stringf("resize(%s << %s[%d:0], %d)", expr_a.c_str(), b_shl, shift_b_width-1, width_y);
string expr_shr = stringf("resize(%s >> %s[%d:0], %d)", expr_a.c_str(), b_shr, shift_b_width-1, width_y);
string expr_shl = stringf("resize(%s << %s[%d:0], %d)", expr_a, b_shl, shift_b_width-1, width_y);
string expr_shr = stringf("resize(%s >> %s[%d:0], %d)", expr_a, b_shr, shift_b_width-1, width_y);
if (shift_b_width < GetSize(sig_b)) {
expr_shl = stringf("%s[%d:%d] != 0ud%d_0 ? 0ud%d_0 : %s", b_shl, GetSize(sig_b)-1, shift_b_width,
@ -288,7 +288,7 @@ struct SmvWorker
GetSize(sig_b)-shift_b_width, width_y, expr_shr.c_str());
}
expr = stringf("bool(%s) ? %s : %s", rvalue(sig_b[GetSize(sig_b)-1]), expr_shl.c_str(), expr_shr.c_str());
expr = stringf("bool(%s) ? %s : %s", rvalue(sig_b[GetSize(sig_b)-1]), expr_shl, expr_shr);
}
else
{
@ -297,13 +297,13 @@ struct SmvWorker
else
expr_a = stringf("resize(unsigned(%s), %d)", rvalue_s(sig_a, width_ay), width);
expr = stringf("resize(%s %s %s[%d:0], %d)", expr_a.c_str(), op.c_str(), rvalue_u(sig_b), shift_b_width-1, width_y);
expr = stringf("resize(%s %s %s[%d:0], %d)", expr_a, op, rvalue_u(sig_b), shift_b_width-1, width_y);
if (shift_b_width < GetSize(sig_b))
expr = stringf("%s[%d:%d] != 0ud%d_0 ? 0ud%d_0 : %s", rvalue_u(sig_b), GetSize(sig_b)-1, shift_b_width,
GetSize(sig_b)-shift_b_width, width_y, expr.c_str());
}
definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort(ID::Y)), expr.c_str()));
definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort(ID::Y)), expr));
continue;
}
@ -426,7 +426,7 @@ struct SmvWorker
if (cell->type == ID($reduce_or)) expr = stringf("%s != 0ub%d_0", expr_a, width_a);
if (cell->type == ID($reduce_bool)) expr = stringf("%s != 0ub%d_0", expr_a, width_a);
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y));
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr, width_y));
continue;
}
@ -445,7 +445,7 @@ struct SmvWorker
if (cell->type == ID($reduce_xnor))
expr = "!(" + expr + ")";
definitions.push_back(stringf("%s := resize(%s, %d);", expr_y, expr.c_str(), width_y));
definitions.push_back(stringf("%s := resize(%s, %d);", expr_y, expr, width_y));
continue;
}
@ -463,7 +463,7 @@ struct SmvWorker
if (cell->type == ID($logic_and)) expr = expr_a + " & " + expr_b;
if (cell->type == ID($logic_or)) expr = expr_a + " | " + expr_b;
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y));
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr, width_y));
continue;
}
@ -475,7 +475,7 @@ struct SmvWorker
string expr_a = stringf("(%s = 0ub%d_0)", rvalue(cell->getPort(ID::A)), width_a);
const char *expr_y = lvalue(cell->getPort(ID::Y));
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a.c_str(), width_y));
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a, width_y));
continue;
}
@ -491,7 +491,7 @@ struct SmvWorker
expr += stringf("bool(%s) ? %s : ", rvalue(sig_s[i]), rvalue(sig_b.extract(i*width, width)));
expr += rvalue(sig_a);
definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort(ID::Y)), expr.c_str()));
definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort(ID::Y)), expr));
continue;
}
@ -505,7 +505,7 @@ struct SmvWorker
if (cell->type.in(ID($_BUF_), ID($_NOT_)))
{
string op = cell->type == ID($_NOT_) ? "!" : "";
definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort(ID::Y)), op.c_str(), rvalue(cell->getPort(ID::A))));
definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort(ID::Y)), op, rvalue(cell->getPort(ID::A))));
continue;
}
@ -650,7 +650,7 @@ struct SmvWorker
for (int k = GetSize(sig)-1; k >= 0; k--)
bits += sig[k] == State::S1 ? '1' : '0';
expr = stringf("0ub%d_%s", GetSize(bits), bits.c_str()) + expr;
expr = stringf("0ub%d_%s", GetSize(bits), bits) + expr;
}
else if (sigmap(SigBit(wire, i)) == SigBit(wire, i))
{
@ -683,36 +683,36 @@ struct SmvWorker
}
}
definitions.push_back(stringf("%s := %s;", cid(wire->name), expr.c_str()));
definitions.push_back(stringf("%s := %s;", cid(wire->name), expr));
}
if (!inputvars.empty()) {
f << stringf(" IVAR\n");
for (const string &line : inputvars)
f << stringf(" %s\n", line.c_str());
f << stringf(" %s\n", line);
}
if (!vars.empty()) {
f << stringf(" VAR\n");
for (const string &line : vars)
f << stringf(" %s\n", line.c_str());
f << stringf(" %s\n", line);
}
if (!definitions.empty()) {
f << stringf(" DEFINE\n");
for (const string &line : definitions)
f << stringf(" %s\n", line.c_str());
f << stringf(" %s\n", line);
}
if (!assignments.empty()) {
f << stringf(" ASSIGN\n");
for (const string &line : assignments)
f << stringf(" %s\n", line.c_str());
f << stringf(" %s\n", line);
}
if (!invarspecs.empty()) {
for (const string &line : invarspecs)
f << stringf(" INVARSPEC %s\n", line.c_str());
f << stringf(" INVARSPEC %s\n", line);
}
}
};
@ -756,7 +756,7 @@ struct SmvBackend : public Backend {
if (args[argidx] == "-tpl" && argidx+1 < args.size()) {
template_f.open(args[++argidx]);
if (template_f.fail())
log_error("Can't open template file `%s'.\n", args[argidx].c_str());
log_error("Can't open template file `%s'.\n", args[argidx]);
continue;
}
if (args[argidx] == "-verbose") {
@ -795,7 +795,7 @@ struct SmvBackend : public Backend {
modules.erase(module);
if (module == nullptr)
log_error("Module '%s' not found.\n", stmt[1].c_str());
log_error("Module '%s' not found.\n", stmt[1]);
*f << stringf("-- SMV description generated by %s\n", yosys_maybe_version());

View file

@ -258,7 +258,7 @@ struct SpiceBackend : public Backend {
if (!top_module_name.empty()) {
if (top_module == NULL)
log_error("Can't find top module `%s'!\n", top_module_name.c_str());
log_error("Can't find top module `%s'!\n", top_module_name);
print_spice_module(*f, top_module, design, neg, pos, buf, ncpf, big_endian, use_inames);
*f << stringf("\n");
}

File diff suppressed because it is too large Load diff

View file

@ -67,7 +67,7 @@ The ``formatted_help()`` method
Dumping command help to json
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- `help -dump-cells-json cmds.json`
- `help -dump-cmds-json cmds.json`
+ generates a ``ContentListing`` for each command registered in Yosys
+ tries to parse unformatted ``Pass::help()`` output if

View file

@ -10,7 +10,7 @@ struct MyPass : public Pass {
{
log("Arguments to my_cmd:\n");
for (auto &arg : args)
log(" %s\n", arg.c_str());
log(" %s\n", arg);
log("Modules in current design:\n");
for (auto mod : design->modules())

View file

@ -16,7 +16,7 @@ struct FunctionalDummyBackend : public Backend {
for (auto module : design->selected_modules())
{
log("Processing module `%s`.\n", module->name.c_str());
log("Processing module `%s`.\n", module->name);
// convert module to FunctionalIR
auto ir = Functional::IR::from_module(module);

View file

@ -45,9 +45,9 @@ creates a bijective map from ``K`` to the integers. For example:
log("%d\n", si("world")); // will print 43
log("%d\n", si.at("world")); // will print 43
log("%d\n", si.at("dummy")); // will throw exception
log("%s\n", si[42].c_str())); // will print hello
log("%s\n", si[43].c_str())); // will print world
log("%s\n", si[44].c_str())); // will throw exception
log("%s\n", si[42])); // will print hello
log("%s\n", si[43])); // will print world
log("%s\n", si[44])); // will throw exception
It is not possible to remove elements from an idict.

View file

@ -77,9 +77,9 @@ struct ScopeinfoExamplePass : public Pass {
continue;
}
log("%s %s\n", wire_scope.first.path_str().c_str(), log_id(wire_scope.second));
log("%s %s\n", wire_scope.first.path_str(), log_id(wire_scope.second));
for (auto src : index.sources(wire))
log(" - %s\n", src.c_str());
log(" - %s\n", src);
}
}
}

View file

@ -284,7 +284,7 @@ end_of_header:
if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size()))
log_error("Line %u has invalid symbol position!\n", line_count);
RTLIL::IdString escaped_s = stringf("\\%s", s.c_str());
RTLIL::IdString escaped_s = stringf("\\%s", s);
RTLIL::Wire* wire;
if (c == 'i') wire = inputs[l1];
else if (c == 'l') wire = latches[l1];
@ -448,7 +448,7 @@ void AigerReader::parse_xaiger()
bool success = ce.eval(o);
log_assert(success);
log_assert(o.wire == nullptr);
lut_mask.bits()[gray] = o.data;
lut_mask.set(gray, o.data);
}
RTLIL::Cell *output_cell = module->cell(stringf("$and$aiger%d$%d", aiger_autoidx, rootNodeID));
log_assert(output_cell);
@ -476,7 +476,7 @@ void AigerReader::parse_xaiger()
else if (c == 'n') {
parse_xaiger_literal(f);
f >> s;
log_debug("n: '%s'\n", s.c_str());
log_debug("n: '%s'\n", s);
}
else if (c == 'h') {
f.ignore(sizeof(uint32_t));
@ -830,7 +830,7 @@ void AigerReader::post_process()
log_debug(" -> %s\n", log_id(escaped_s));
}
else {
RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index);
existing = module->wire(indexed_name);
if (!existing)
module->rename(wire, indexed_name);
@ -877,7 +877,7 @@ void AigerReader::post_process()
log_debug(" -> %s\n", log_id(escaped_s));
}
else {
RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index);
existing = module->wire(indexed_name);
if (!existing)
module->rename(wire, indexed_name);
@ -909,7 +909,7 @@ void AigerReader::post_process()
module->rename(cell, escaped_s);
}
else
log_error("Symbol type '%s' not recognised.\n", type.c_str());
log_error("Symbol type '%s' not recognised.\n", type);
}
}
@ -922,7 +922,7 @@ void AigerReader::post_process()
RTLIL::Wire *wire = module->wire(name);
if (wire)
module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0)));
module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name, 0)));
// Do not make ports with a mix of input/output into
// wide ports
@ -942,7 +942,7 @@ void AigerReader::post_process()
wire->port_output = port_output;
for (int i = min; i <= max; i++) {
RTLIL::IdString other_name = stringf("%s[%d]", name.c_str(), i);
RTLIL::IdString other_name = stringf("%s[%d]", name, i);
RTLIL::Wire *other_wire = module->wire(other_name);
if (other_wire) {
other_wire->port_input = false;
@ -971,9 +971,9 @@ void AigerReader::post_process()
if (cell->type != ID($lut)) continue;
auto y_port = cell->getPort(ID::Y).as_bit();
if (y_port.wire->width == 1)
module->rename(cell, stringf("$lut%s", y_port.wire->name.c_str()));
module->rename(cell, stringf("$lut%s", y_port.wire->name));
else
module->rename(cell, stringf("$lut%s[%d]", y_port.wire->name.c_str(), y_port.offset));
module->rename(cell, stringf("$lut%s[%d]", y_port.wire->name, y_port.offset));
}
}

View file

@ -91,7 +91,7 @@ struct Xaiger2Frontend : public Frontend {
std::ifstream map_file;
map_file.open(map_filename);
if (!map_file)
log_error("Failed to open map file '%s'\n", map_filename.c_str());
log_error("Failed to open map file '%s'\n", map_filename);
unsigned int M, I, L, O, A;
std::string header;
@ -388,7 +388,7 @@ struct Xaiger2Frontend : public Frontend {
if (f->eof())
break;
log_assert(!f->fail());
log("input file: %s\n", scratch.c_str());
log("input file: %s\n", scratch);
}
log_debug("co_counter=%d\n", co_counter);

View file

@ -193,7 +193,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
auto& attr = attributes.at(id);
if (attr->type != AST_CONSTANT)
attr->input_error("Attribute `%s' with non-constant value!\n", id.c_str());
attr->input_error("Attribute `%s' with non-constant value!\n", id);
return attr->integer != 0;
}
@ -922,7 +922,7 @@ std::unique_ptr<AstNode> AstNode::mktemp_logic(AstSrcLocType loc, const std::str
{
auto wire_owned = std::make_unique<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(loc, AST_RANGE, mkconst_int(loc, range_left, true), mkconst_int(loc, range_right, true)));
auto* wire = wire_owned.get();
wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line, autoidx++);
wire->str = stringf("%s%s:%d$%d", name, RTLIL::encode_filename(*location.begin.filename), location.begin.line, autoidx++);
if (nosync)
wire->set_attribute(ID::nosync, AstNode::mkconst_int(loc, 1, false));
wire->is_signed = is_signed;
@ -1076,8 +1076,10 @@ RTLIL::Const AstNode::realAsConst(int width)
bool is_negative = v < 0;
if (is_negative)
v *= -1;
RTLIL::Const::Builder b(width);
for (int i = 0; i < width; i++, v /= 2)
result.bits().push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0);
b.push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0);
result = b.build();
if (is_negative)
result = const_neg(result, result, false, false, result.size());
}
@ -1108,9 +1110,9 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
if (defer)
log("Storing AST representation for module `%s'.\n", ast->str.c_str());
log("Storing AST representation for module `%s'.\n", ast->str);
else if (!quiet) {
log("Generating RTLIL representation for module `%s'.\n", ast->str.c_str());
log("Generating RTLIL representation for module `%s'.\n", ast->str);
}
AstModule *module = new AstModule;
@ -1143,7 +1145,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
{
for (auto& node : ast->children)
if (node->type == AST_PARAMETER && param_has_no_default(node.get()))
node->input_error("Parameter `%s' has no default value and has not been overridden!\n", node->str.c_str());
node->input_error("Parameter `%s' has no default value and has not been overridden!\n", node->str);
bool blackbox_module = flag_lib;
@ -1256,7 +1258,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
for (auto &attr : ast->attributes) {
log_assert((bool)attr.second.get());
if (attr.second->type != AST_CONSTANT)
ast->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
ast->input_error("Attribute `%s' with non-constant value!\n", attr.first);
module->attributes[attr.first] = attr.second->asAttrConst();
}
for (size_t i = 0; i < ast->children.size(); i++) {
@ -1411,7 +1413,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
for (auto& n : design->verilog_packages) {
for (auto &o : n->children) {
auto cloned_node = o->clone();
// log("cloned node %s\n", type2str(cloned_node->type).c_str());
// log("cloned node %s\n", type2str(cloned_node->type));
if (cloned_node->type == AST_ENUM) {
for (auto &e : cloned_node->children) {
log_assert(e->type == AST_ENUM_ITEM);
@ -1432,7 +1434,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
for (const auto& node : child->children)
if (node->type == AST_PARAMETER && param_has_no_default(node.get()))
{
log("Deferring `%s' because it contains parameter(s) without defaults.\n", child->str.c_str());
log("Deferring `%s' because it contains parameter(s) without defaults.\n", child->str);
defer_local = true;
break;
}
@ -1444,7 +1446,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
if (design->has(child->str)) {
RTLIL::Module *existing_mod = design->module(child->str);
if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
log_file_error(*child->location.begin.filename, child->location.begin.line, "Re-definition of module `%s'!\n", child->str.c_str());
log_file_error(*child->location.begin.filename, child->location.begin.line, "Re-definition of module `%s'!\n", child->str);
} else if (nooverwrite) {
log("Ignoring re-definition of module `%s' at %s.\n",
child->str.c_str(), child->loc_string().c_str());
@ -1507,7 +1509,7 @@ std::pair<std::string,std::string> AST::split_modport_from_type(std::string name
interface_modport = seglist[1];
}
else { // Erroneous port type
log_error("More than two '.' in signal port type (%s)\n", name_type.c_str());
log_error("More than two '.' in signal port type (%s)\n", name_type);
}
}
return std::pair<std::string,std::string>(interface_type, interface_modport);
@ -1720,7 +1722,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.c_str());
log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname);
}
}
@ -1731,7 +1733,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
} else {
modname = new_modname;
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
log("Found cached RTLIL representation for module `%s'.\n", modname);
}
return modname;
@ -1750,7 +1752,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
process_module(design, new_ast.get(), false, NULL, quiet);
design->module(modname)->check();
} else if (!quiet) {
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
log("Found cached RTLIL representation for module `%s'.\n", modname);
}
return modname;
@ -1773,7 +1775,7 @@ static std::string serialize_param_value(const RTLIL::Const &val) {
std::string AST::derived_module_name(std::string stripped_name, const std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> &parameters) {
std::string para_info;
for (const auto &elem : parameters)
para_info += stringf("%s=%s", elem.first.c_str(), serialize_param_value(elem.second).c_str());
para_info += stringf("%s=%s", elem.first, serialize_param_value(elem.second));
if (para_info.size() > 60)
return "$paramod$" + sha1(para_info) + stripped_name;
@ -1799,14 +1801,14 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
auto it = parameters.find(child->str);
if (it != parameters.end()) {
if (!quiet)
log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second));
log("Parameter %s = %s\n", child->str, log_signal(it->second));
named_parameters.emplace_back(child->str, it->second);
continue;
}
it = parameters.find(stringf("$%d", para_counter));
if (it != parameters.end()) {
if (!quiet)
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second));
log("Parameter %d (%s) = %s\n", para_counter, child->str, log_signal(it->second));
named_parameters.emplace_back(child->str, it->second);
continue;
}
@ -1820,7 +1822,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
return modname;
if (!quiet)
log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name);
loadconfig();
pool<IdString> rewritten;
@ -1839,13 +1841,13 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
auto it = parameters.find(child->str);
if (it != parameters.end()) {
if (!quiet)
log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second));
log("Parameter %s = %s\n", child->str, log_signal(it->second));
goto rewrite_parameter;
}
it = parameters.find(stringf("$%d", para_counter));
if (it != parameters.end()) {
if (!quiet)
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second));
log("Parameter %d (%s) = %s\n", para_counter, child->str, log_signal(it->second));
goto rewrite_parameter;
}
continue;
@ -1922,11 +1924,9 @@ void AstModule::loadconfig() const
flag_autowire = autowire;
}
void AstNode::input_error(const char *format, ...) const
void AstNode::formatted_input_error(std::string str) const
{
va_list ap;
va_start(ap, format);
logv_file_error(*location.begin.filename, location.begin.line, format, ap);
log_formatted_file_error(*location.begin.filename, location.begin.line, std::move(str));
}
YOSYS_NAMESPACE_END

View file

@ -378,7 +378,12 @@ namespace AST
AstNode *get_struct_member() const;
// helper to print errors from simplify/genrtlil code
[[noreturn]] void input_error(const char *format, ...) const YS_ATTRIBUTE(format(printf, 2, 3));
[[noreturn]] void formatted_input_error(std::string str) const;
template <typename... Args>
[[noreturn]] void input_error(FmtString<TypeIdentity<Args>...> fmt, const Args &... args) const
{
formatted_input_error(fmt.format(args...));
}
};
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code

View file

@ -40,7 +40,7 @@ static ffi_fptr resolve_fn (std::string symbol_name)
plugin_name = loaded_plugin_aliases.at(plugin_name);
if (loaded_plugins.count(plugin_name) == 0)
log_error("unable to resolve '%s': can't find plugin `%s'\n", symbol_name.c_str(), plugin_name.c_str());
log_error("unable to resolve '%s': can't find plugin `%s'\n", symbol_name, plugin_name);
void *symbol = dlsym(loaded_plugins.at(plugin_name), real_symbol_name.c_str());
@ -61,7 +61,7 @@ static ffi_fptr resolve_fn (std::string symbol_name)
if (symbol != nullptr)
return (ffi_fptr) symbol;
log_error("unable to resolve '%s'.\n", symbol_name.c_str());
log_error("unable to resolve '%s'.\n", symbol_name);
}
std::unique_ptr<AST::AstNode> AST::dpi_call(AstSrcLocType loc, const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<std::unique_ptr<AST::AstNode>> &args)
@ -74,32 +74,32 @@ std::unique_ptr<AST::AstNode> AST::dpi_call(AstSrcLocType loc, const std::string
ffi_cif cif;
int status;
log("Calling DPI function `%s' and returning `%s':\n", fname.c_str(), rtype.c_str());
log("Calling DPI function `%s' and returning `%s':\n", fname, rtype);
log_assert(GetSize(args) == GetSize(argtypes));
for (int i = 0; i < GetSize(args); i++) {
if (argtypes[i] == "real") {
log(" arg %d (%s): %f\n", i, argtypes[i].c_str(), args[i]->asReal(args[i]->is_signed));
log(" arg %d (%s): %f\n", i, argtypes[i], args[i]->asReal(args[i]->is_signed));
value_store[i].f64 = args[i]->asReal(args[i]->is_signed);
values[i] = &value_store[i].f64;
types[i] = &ffi_type_double;
} else if (argtypes[i] == "shortreal") {
log(" arg %d (%s): %f\n", i, argtypes[i].c_str(), args[i]->asReal(args[i]->is_signed));
log(" arg %d (%s): %f\n", i, argtypes[i], args[i]->asReal(args[i]->is_signed));
value_store[i].f32 = args[i]->asReal(args[i]->is_signed);
values[i] = &value_store[i].f32;
types[i] = &ffi_type_double;
} else if (argtypes[i] == "integer") {
log(" arg %d (%s): %lld\n", i, argtypes[i].c_str(), (long long)args[i]->asInt(args[i]->is_signed));
log(" arg %d (%s): %lld\n", i, argtypes[i], (long long)args[i]->asInt(args[i]->is_signed));
value_store[i].i32 = args[i]->asInt(args[i]->is_signed);
values[i] = &value_store[i].i32;
types[i] = &ffi_type_sint32;
} else if (argtypes[i] == "chandle") {
log(" arg %d (%s): %llx\n", i, argtypes[i].c_str(), (unsigned long long)args[i]->asInt(false));
log(" arg %d (%s): %llx\n", i, argtypes[i], (unsigned long long)args[i]->asInt(false));
value_store[i].ptr = (void *)args[i]->asInt(args[i]->is_signed);
values[i] = &value_store[i].ptr;
types[i] = &ffi_type_pointer;
} else {
log_error("invalid argtype '%s' for argument %d.\n", argtypes[i].c_str(), i);
log_error("invalid argtype '%s' for argument %d.\n", argtypes[i], i);
}
}
@ -116,7 +116,7 @@ std::unique_ptr<AST::AstNode> AST::dpi_call(AstSrcLocType loc, const std::string
types[args.size()] = &ffi_type_pointer;
values[args.size()] = &value_store[args.size()].ptr;
} else {
log_error("invalid rtype '%s'.\n", rtype.c_str());
log_error("invalid rtype '%s'.\n", rtype);
}
if ((status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, args.size(), types[args.size()], types.data())) != FFI_OK)
@ -155,7 +155,7 @@ YOSYS_NAMESPACE_BEGIN
std::unique_ptr<AST::AstNode> AST::dpi_call(AstSrcLocType, const std::string&, const std::string &fname, const std::vector<std::string>&, const std::vector<std::unique_ptr<AST::AstNode>>&)
{
log_error("Can't call DPI function `%s': this version of yosys is built without plugin support\n", fname.c_str());
log_error("Can't call DPI function `%s': this version of yosys is built without plugin support\n", fname);
}
YOSYS_NAMESPACE_END

View file

@ -45,7 +45,7 @@ using namespace AST_INTERNAL;
// helper function for creating RTLIL code for unary operations
static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true)
{
IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(*that->location.begin.filename).c_str(), that->location.begin.line, autoidx++);
IdString name = stringf("%s$%s:%d$%d", type, RTLIL::encode_filename(*that->location.begin.filename), that->location.begin.line, autoidx++);
RTLIL::Cell *cell = current_module->addCell(name, type);
set_src_attr(cell, that);
@ -56,7 +56,7 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width
if (gen_attributes)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
that->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
that->input_error("Attribute `%s' with non-constant value!\n", attr.first);
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@ -77,7 +77,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
return;
}
IdString name = stringf("$extend$%s:%d$%d", RTLIL::encode_filename(*that->location.begin.filename).c_str(), that->location.begin.line, autoidx++);
IdString name = stringf("$extend$%s:%d$%d", RTLIL::encode_filename(*that->location.begin.filename), that->location.begin.line, autoidx++);
RTLIL::Cell *cell = current_module->addCell(name, ID($pos));
set_src_attr(cell, that);
@ -88,7 +88,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
if (that != nullptr)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
that->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
that->input_error("Attribute `%s' with non-constant value!\n", attr.first);
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@ -104,7 +104,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
// helper function for creating RTLIL code for binary operations
static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
{
IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(*that->location.begin.filename).c_str(), that->location.begin.line, autoidx++);
IdString name = stringf("%s$%s:%d$%d", type, RTLIL::encode_filename(*that->location.begin.filename), that->location.begin.line, autoidx++);
RTLIL::Cell *cell = current_module->addCell(name, type);
set_src_attr(cell, that);
@ -114,7 +114,7 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
that->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
that->input_error("Attribute `%s' with non-constant value!\n", attr.first);
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@ -149,7 +149,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
that->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
that->input_error("Attribute `%s' with non-constant value!\n", attr.first);
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@ -199,7 +199,7 @@ struct AST_INTERNAL::LookaheadRewriter
for (auto& c : node->id2ast->children)
wire->children.push_back(c->clone());
wire->fixup_hierarchy_flags();
wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++);
wire->str = stringf("$lookahead%s$%d", node->str, autoidx++);
wire->set_attribute(ID::nosync, AstNode::mkconst_int(node->location, 1, false));
wire->is_logic = true;
while (wire->simplify(true, 1, -1, false)) { }
@ -348,11 +348,11 @@ struct AST_INTERNAL::ProcessGenerator
LookaheadRewriter la_rewriter(always.get());
// generate process and simple root case
proc = current_module->addProcess(stringf("$proc$%s:%d$%d", RTLIL::encode_filename(*always->location.begin.filename).c_str(), always->location.begin.line, autoidx++));
proc = current_module->addProcess(stringf("$proc$%s:%d$%d", RTLIL::encode_filename(*always->location.begin.filename), always->location.begin.line, autoidx++));
set_src_attr(proc, always.get());
for (auto &attr : always->attributes) {
if (attr.second->type != AST_CONSTANT)
always->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
always->input_error("Attribute `%s' with non-constant value!\n", attr.first);
proc->attributes[attr.first] = attr.second->asAttrConst();
}
current_case = &proc->root_case;
@ -382,7 +382,7 @@ struct AST_INTERNAL::ProcessGenerator
if (found_anyedge_syncs) {
if (found_global_syncs)
always->input_error("Found non-synthesizable event list!\n");
log("Note: Assuming pure combinatorial block at %s in\n", always->loc_string().c_str());
log("Note: Assuming pure combinatorial block at %s in\n", always->loc_string());
log("compliance with IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002. Recommending\n");
log("use of @* instead of @(...) for better match of synthesis and simulation.\n");
}
@ -630,7 +630,7 @@ struct AST_INTERNAL::ProcessGenerator
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
ast->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
ast->input_error("Attribute `%s' with non-constant value!\n", attr.first);
sw->attributes[attr.first] = attr.second->asAttrConst();
}
@ -732,16 +732,17 @@ struct AST_INTERNAL::ProcessGenerator
current_case->actions.push_back(SigSig(en, true));
RTLIL::SigSpec triggers;
RTLIL::Const polarity;
RTLIL::Const::Builder polarity_builder;
for (auto sync : proc->syncs) {
if (sync->type == RTLIL::STp) {
triggers.append(sync->signal);
polarity.bits().push_back(RTLIL::S1);
polarity_builder.push_back(RTLIL::S1);
} else if (sync->type == RTLIL::STn) {
triggers.append(sync->signal);
polarity.bits().push_back(RTLIL::S0);
polarity_builder.push_back(RTLIL::S0);
}
}
RTLIL::Const polarity = polarity_builder.build();
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($print));
set_src_attr(cell, ast);
@ -794,7 +795,7 @@ struct AST_INTERNAL::ProcessGenerator
fmt.append_literal("\n");
fmt.emit_rtlil(cell);
} else if (!ast->str.empty()) {
log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Found unsupported invocation of system task `%s'!\n", ast->str.c_str());
log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Found unsupported invocation of system task `%s'!\n", ast->str);
}
break;
@ -814,7 +815,7 @@ struct AST_INTERNAL::ProcessGenerator
IdString cellname;
if (ast->str.empty())
cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(*ast->location.begin.filename).c_str(), ast->location.begin.line, autoidx++);
cellname = stringf("$%s$%s:%d$%d", flavor, RTLIL::encode_filename(*ast->location.begin.filename), ast->location.begin.line, autoidx++);
else
cellname = ast->str;
check_unique_id(current_module, cellname, ast, "procedural assertion");
@ -829,22 +830,23 @@ struct AST_INTERNAL::ProcessGenerator
current_case->actions.push_back(SigSig(en, true));
RTLIL::SigSpec triggers;
RTLIL::Const polarity;
RTLIL::Const::Builder polarity_builder;
for (auto sync : proc->syncs) {
if (sync->type == RTLIL::STp) {
triggers.append(sync->signal);
polarity.bits().push_back(RTLIL::S1);
polarity_builder.push_back(RTLIL::S1);
} else if (sync->type == RTLIL::STn) {
triggers.append(sync->signal);
polarity.bits().push_back(RTLIL::S0);
polarity_builder.push_back(RTLIL::S0);
}
}
RTLIL::Const polarity = polarity_builder.build();
RTLIL::Cell *cell = current_module->addCell(cellname, ID($check));
set_src_attr(cell, ast);
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Attribute `%s' with non-constant value!\n", attr.first);
cell->attributes[attr.first] = attr.second->asAttrConst();
}
cell->setParam(ID::FLAVOR, flavor);
@ -893,7 +895,7 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::Const priority_mask = RTLIL::Const(0, cur_idx);
for (int i = 0; i < portid; i++) {
int new_bit = port_map[std::make_pair(memid, i)];
priority_mask.bits()[new_bit] = orig_priority_mask[i];
priority_mask.set(new_bit, orig_priority_mask[i]);
}
action.priority_mask = priority_mask;
sync->mem_write_actions.push_back(action);
@ -1007,7 +1009,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
}
}
if (!id_ast)
input_error("Failed to resolve identifier %s for width detection!\n", str.c_str());
input_error("Failed to resolve identifier %s for width detection!\n", str);
if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM || id_ast->type == AST_ENUM_ITEM) {
if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) {
this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
@ -1017,7 +1019,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (id_ast->children[0]->type == AST_CONSTANT)
this_width = id_ast->children[0]->bits.size();
else
input_error("Failed to detect width for parameter %s!\n", str.c_str());
input_error("Failed to detect width for parameter %s!\n", str);
}
if (children.size() != 0)
range = children[0].get();
@ -1030,7 +1032,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
// log("---\n");
// id_ast->dumpAst(nullptr, "decl> ");
// dumpAst(nullptr, "ref> ");
input_error("Failed to detect width of signal access `%s'!\n", str.c_str());
input_error("Failed to detect width of signal access `%s'!\n", str);
}
} else {
this_width = id_ast->range_left - id_ast->range_right + 1;
@ -1041,7 +1043,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
this_width = 32;
} else if (id_ast->type == AST_MEMORY) {
if (!id_ast->children[0]->range_valid)
input_error("Failed to detect width of memory access `%s'!\n", str.c_str());
input_error("Failed to detect width of memory access `%s'!\n", str);
this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
if (children.size() > 1)
range = children[1].get();
@ -1049,7 +1051,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
auto tmp_range = make_index_range(id_ast);
this_width = tmp_range->range_left - tmp_range->range_right + 1;
} else
input_error("Failed to detect width for identifier %s!\n", str.c_str());
input_error("Failed to detect width for identifier %s!\n", str);
if (range) {
if (range->children.size() == 1)
this_width = 1;
@ -1059,7 +1061,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
while (left_at_zero_ast->simplify(true, 1, -1, false)) { }
while (right_at_zero_ast->simplify(true, 1, -1, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str);
this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
} else
this_width = range->range_left - range->range_right + 1;
@ -1193,7 +1195,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (!id2ast->is_signed)
sign_hint = false;
if (!id2ast->children[0]->range_valid)
input_error("Failed to detect width of memory access `%s'!\n", str.c_str());
input_error("Failed to detect width of memory access `%s'!\n", str);
this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1;
width_hint = max(width_hint, this_width);
break;
@ -1239,7 +1241,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
while (children[0]->simplify(true, 1, -1, false) == true) { }
if (children[0]->type != AST_CONSTANT)
input_error("System function %s called with non-const argument!\n",
RTLIL::unescape_id(str).c_str());
RTLIL::unescape_id(str));
width_hint = max(width_hint, int(children[0]->asInt(true)));
}
break;
@ -1266,7 +1268,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
// item expressions.
const AstNode *func = current_scope.at(str);
if (func->type != AST_FUNCTION)
input_error("Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str).c_str());
input_error("Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str));
const AstNode *wire = nullptr;
for (const auto& child : func->children)
if (child->str == func->str) {
@ -1289,7 +1291,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
while (right->simplify(true, 1, -1, false)) { }
if (left->type != AST_CONSTANT || right->type != AST_CONSTANT)
input_error("Function %s has non-constant width!",
RTLIL::unescape_id(str).c_str());
RTLIL::unescape_id(str));
result_width = abs(int(left->asInt(true) - right->asInt(true)));
}
width_hint = max(width_hint, result_width);
@ -1302,7 +1304,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
AstNode *current_scope_ast = current_ast_mod == nullptr ? current_ast : current_ast_mod;
for (auto f : log_files)
current_scope_ast->dumpAst(f, "verilog-ast> ");
input_error("Don't know how to detect sign and width for %s node!\n", type2str(type).c_str());
input_error("Don't know how to detect sign and width for %s node!\n", type2str(type));
}
@ -1406,7 +1408,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (flag_pwires)
{
if (GetSize(children) < 1 || children[0]->type != AST_CONSTANT)
input_error("Parameter `%s' with non-constant value!\n", str.c_str());
input_error("Parameter `%s' with non-constant value!\n", str);
RTLIL::Const val = children[0]->bitsAsConst();
RTLIL::IdString id = str;
@ -1420,7 +1422,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
input_error("Attribute `%s' with non-constant value!\n", attr.first);
wire->attributes[attr.first] = attr.second->asAttrConst();
}
}
@ -1429,10 +1431,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Wire for an AST_WIRE node
case AST_WIRE: {
if (!range_valid)
input_error("Signal `%s' with non-constant width!\n", str.c_str());
input_error("Signal `%s' with non-constant width!\n", str);
if (!(range_left + 1 >= range_right))
input_error("Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1);
input_error("Signal `%s' with invalid width range %d!\n", str, range_left - range_right + 1);
RTLIL::IdString id = str;
check_unique_id(current_module, id, this, "signal");
@ -1448,7 +1450,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
input_error("Attribute `%s' with non-constant value!\n", attr.first);
wire->attributes[attr.first] = attr.second->asAttrConst();
}
@ -1464,7 +1466,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_assert(children[1]->type == AST_RANGE);
if (!children[0]->range_valid || !children[1]->range_valid)
input_error("Memory `%s' with non-constant width or size!\n", str.c_str());
input_error("Memory `%s' with non-constant width or size!\n", str);
RTLIL::Memory *memory = new RTLIL::Memory;
set_src_attr(memory, this);
@ -1482,7 +1484,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
input_error("Attribute `%s' with non-constant value!\n", attr.first);
memory->attributes[attr.first] = attr.second->asAttrConst();
}
}
@ -1537,13 +1539,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (dynamic_cast<RTLIL::Binding*>(current_module)) {
/* nothing to do here */
} else if (flag_autowire)
log_file_warning(*location.begin.filename, location.begin.line, "Identifier `%s' is implicitly declared.\n", str.c_str());
log_file_warning(*location.begin.filename, location.begin.line, "Identifier `%s' is implicitly declared.\n", str);
else
input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str);
}
else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM || id2ast->type == AST_ENUM_ITEM) {
if (id2ast->children[0]->type != AST_CONSTANT)
input_error("Parameter %s does not evaluate to constant value!\n", str.c_str());
input_error("Parameter %s does not evaluate to constant value!\n", str);
chunk = RTLIL::Const(id2ast->children[0]->bits);
goto use_const_chunk;
}
@ -1558,17 +1560,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
is_interface = true;
}
else {
input_error("Identifier `%s' doesn't map to any signal!\n", str.c_str());
input_error("Identifier `%s' doesn't map to any signal!\n", str);
}
if (id2ast->type == AST_MEMORY)
input_error("Identifier `%s' does map to an unexpanded memory!\n", str.c_str());
input_error("Identifier `%s' does map to an unexpanded memory!\n", str);
// If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface'
// This makes it possible for the hierarchy pass to see what are interface connections and then replace them
// with the individual signals:
if (is_interface) {
IdString dummy_wire_name = stringf("$dummywireforinterface%s", str.c_str());
IdString dummy_wire_name = stringf("$dummywireforinterface%s", str);
RTLIL::Wire *dummy_wire = current_module->wire(dummy_wire_name);
if (!dummy_wire) {
dummy_wire = current_module->addWire(dummy_wire_name);
@ -1610,7 +1612,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
while (left_at_zero_ast->simplify(true, 1, -1, false)) { }
while (right_at_zero_ast->simplify(true, 1, -1, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str);
int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
auto fake_ast = std::make_unique<AstNode>(children[0]->location, AST_NONE, clone(), children[0]->children.size() >= 2 ?
children[0]->children[1]->clone() : children[0]->children[0]->clone());
@ -2019,7 +2021,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
IdString cellname;
if (str.empty())
cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line, autoidx++);
cellname = stringf("$%s$%s:%d$%d", flavor, RTLIL::encode_filename(*location.begin.filename), location.begin.line, autoidx++);
else
cellname = str;
check_unique_id(current_module, cellname, this, "procedural assertion");
@ -2032,7 +2034,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
set_src_attr(cell, this);
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
input_error("Attribute `%s' with non-constant value!\n", attr.first);
cell->attributes[attr.first] = attr.second->asAttrConst();
}
cell->setParam(ID(FLAVOR), flavor);
@ -2148,7 +2150,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
input_error("Attribute `%s' with non-constant value.\n", attr.first.c_str());
input_error("Attribute `%s' with non-constant value.\n", attr.first);
cell->attributes[attr.first] = attr.second->asAttrConst();
}
if (cell->type == ID($specify2)) {
@ -2193,17 +2195,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
int sz = children.size();
if (str == "$info") {
if (sz > 0)
log_file_info(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str.c_str());
log_file_info(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str);
else
log_file_info(*location.begin.filename, location.begin.line, "\n");
} else if (str == "$warning") {
if (sz > 0)
log_file_warning(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str.c_str());
log_file_warning(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str);
else
log_file_warning(*location.begin.filename, location.begin.line, "\n");
} else if (str == "$error") {
if (sz > 0)
input_error("%s.\n", children[0]->str.c_str());
input_error("%s.\n", children[0]->str);
else
input_error("\n");
} else if (str == "$fatal") {
@ -2212,11 +2214,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// dollar_finish(sz ? children[0] : 1);
// perhaps create & use log_file_fatal()
if (sz > 0)
input_error("FATAL: %s.\n", children[0]->str.c_str());
input_error("FATAL: %s.\n", children[0]->str);
else
input_error("FATAL.\n");
} else {
input_error("Unknown elaboration system task '%s'.\n", str.c_str());
input_error("Unknown elaboration system task '%s'.\n", str);
}
} break;
@ -2235,17 +2237,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (GetSize(children) > 1)
input_error("System function %s got %d arguments, expected 1 or 0.\n",
RTLIL::unescape_id(str).c_str(), GetSize(children));
RTLIL::unescape_id(str), GetSize(children));
if (GetSize(children) == 1) {
if (children[0]->type != AST_CONSTANT)
input_error("System function %s called with non-const argument!\n",
RTLIL::unescape_id(str).c_str());
RTLIL::unescape_id(str));
width = children[0]->asInt(true);
}
if (width <= 0)
input_error("Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str());
input_error("Failed to detect width of %s!\n", RTLIL::unescape_id(str));
Cell *cell = current_module->addCell(myid, str.substr(1));
set_src_attr(cell, this);
@ -2272,7 +2274,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
default:
for (auto f : log_files)
current_ast_mod->dumpAst(f, "verilog-ast> ");
input_error("Don't know how to generate RTLIL code for %s node!\n", type2str(type).c_str());
input_error("Don't know how to generate RTLIL code for %s node!\n", type2str(type));
}
return RTLIL::SigSpec();

View file

@ -161,10 +161,10 @@ Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_
arg.sig = node_arg->bitsAsConst();
arg.signed_ = node_arg->is_signed;
} else if (may_fail) {
log_file_info(*location.begin.filename, location.begin.line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1);
log_file_info(*location.begin.filename, location.begin.line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str, index + 1);
return Fmt();
} else {
log_file_error(*location.begin.filename, location.begin.line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1);
log_file_error(*location.begin.filename, location.begin.line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str, index + 1);
}
args.push_back(arg);
}
@ -180,10 +180,10 @@ void AstNode::annotateTypedEnums(AstNode *template_node)
if (template_node->attributes.count(ID::enum_type)) {
//get reference to enum node:
std::string enum_type = template_node->attributes[ID::enum_type]->str.c_str();
// log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));
// log("enum_type=%s (count=%lu)\n", enum_type, current_scope.count(enum_type));
// log("current scope:\n");
// for (auto &it : current_scope)
// log(" %s\n", it.first.c_str());
// log(" %s\n", it.first);
log_assert(current_scope.count(enum_type) == 1);
AstNode *enum_node = current_scope.at(enum_type);
log_assert(enum_node->type == AST_ENUM);
@ -250,7 +250,7 @@ static int range_width(AstNode *node, AstNode *rnode)
{
log_assert(rnode->type==AST_RANGE);
if (!rnode->range_valid) {
node->input_error("Non-constant range in declaration of %s\n", node->str.c_str());
node->input_error("Non-constant range in declaration of %s\n", node->str);
}
// note: range swapping has already been checked for
return rnode->range_left - rnode->range_right + 1;
@ -265,7 +265,7 @@ static int add_dimension(AstNode *node, AstNode *rnode)
[[noreturn]] static void struct_array_packing_error(AstNode *node)
{
node->input_error("Unpacked array in packed struct/union member %s\n", node->str.c_str());
node->input_error("Unpacked array in packed struct/union member %s\n", node->str);
}
static int size_packed_struct(AstNode *snode, int base_offset)
@ -358,7 +358,7 @@ static int size_packed_struct(AstNode *snode, int base_offset)
}
else {
if (packed_width != width)
node->input_error("member %s of a packed union has %d bits, expecting %d\n", node->str.c_str(), width, packed_width);
node->input_error("member %s of a packed union has %d bits, expecting %d\n", node->str, width, packed_width);
}
}
else {
@ -481,7 +481,7 @@ std::unique_ptr<AstNode> AstNode::make_index_range(AstNode *decl_node, bool unpa
dim--; // Step back to the final index / slice
}
else {
input_error("Unsupported range operation for %s\n", str.c_str());
input_error("Unsupported range operation for %s\n", str);
}
std::unique_ptr<AstNode> index_range = std::make_unique<AstNode>(rnode->location, AST_RANGE);
@ -911,7 +911,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
#if 0
log("-------------\n");
log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, location.begin.filename->c_str(), location.begin.line, type2str(type).c_str(), this);
log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, location.begin.filename, location.begin.line, type2str(type), this);
log("const_fold=%d, stage=%d, width_hint=%d, sign_hint=%d\n",
int(const_fold), int(stage), int(width_hint), int(sign_hint));
// dumpAst(nullptr, "> ");
@ -963,22 +963,22 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
if ((memflags & AstNode::MEM2REG_FL_CONST_LHS) && !(memflags & AstNode::MEM2REG_FL_VAR_LHS))
goto verbose_activate;
// log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
// log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str, long(memflags));
continue;
verbose_activate:
if (mem2reg_set.count(mem) == 0) {
std::string message = stringf("Replacing memory %s with list of registers.", mem->str.c_str());
std::string message = stringf("Replacing memory %s with list of registers.", mem->str);
bool first_element = true;
for (auto &place : mem2reg_places[it.first]) {
message += stringf("%s%s", first_element ? " See " : ", ", place.c_str());
message += stringf("%s%s", first_element ? " See " : ", ", place);
first_element = false;
}
log_warning("%s\n", message.c_str());
log_warning("%s\n", message);
}
silent_activate:
// log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
// log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str, long(memflags));
mem2reg_set.insert(mem);
}
@ -997,7 +997,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
for (int i = 0; i < mem_size; i++) {
auto reg = std::make_unique<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(loc, AST_RANGE,
mkconst_int(loc, data_range_left, true), mkconst_int(loc, data_range_right, true)));
reg->str = stringf("%s[%d]", node->str.c_str(), i);
reg->str = stringf("%s[%d]", node->str, i);
reg->is_reg = true;
reg->is_signed = node->is_signed;
for (auto &it : node->attributes)
@ -1032,7 +1032,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
// note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" ||
str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) {
log_file_warning(*location.begin.filename, location.begin.line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str());
log_file_warning(*location.begin.filename, location.begin.line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str);
delete_children();
str = std::string();
}
@ -1042,7 +1042,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
str == "$write" || str == "$writeb" || str == "$writeh" || str == "$writeo"))
{
if (!current_always) {
log_file_warning(*location.begin.filename, location.begin.line, "System task `%s' outside initial or always block is unsupported.\n", str.c_str());
log_file_warning(*location.begin.filename, location.begin.line, "System task `%s' outside initial or always block is unsupported.\n", str);
delete_children();
str = std::string();
} else {
@ -1063,7 +1063,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
Fmt fmt = processFormat(stage, /*sformat_like=*/false, default_base, /*first_arg_at=*/0, /*may_fail=*/true);
if (str.substr(0, 8) == "$display")
fmt.append_literal("\n");
log("%s", fmt.render().c_str());
log("%s", fmt.render());
}
return false;
@ -1135,7 +1135,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
if (current_scope.count(enode->str) == 0)
current_scope[enode->str] = enode.get();
else
input_error("enum item %s already exists in current scope\n", enode->str.c_str());
input_error("enum item %s already exists in current scope\n", enode->str);
}
}
}
@ -1144,7 +1144,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
i--; // Adjust index since we removed an element
} else {
// If we can't find the package, just remove the import node to avoid errors later
log_warning("Package `%s' not found for import, removing import statement\n", child->str.c_str());
log_warning("Package `%s' not found for import, removing import statement\n", child->str);
children.erase(children.begin() + i);
i--; // Adjust index since we removed an element
}
@ -1209,7 +1209,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
continue;
wires_are_incompatible:
if (stage > 1)
input_error("Incompatible re-declaration of wire %s.\n", node->str.c_str());
input_error("Incompatible re-declaration of wire %s.\n", node->str);
continue;
}
this_wire_scope[node->str] = node;
@ -1228,7 +1228,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
if (current_scope.count(enode->str) == 0)
current_scope[enode->str] = enode.get();
else
input_error("enum item %s already exists\n", enode->str.c_str());
input_error("enum item %s already exists\n", enode->str);
}
}
}
@ -1268,7 +1268,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
if (current_scope.count(enode->str) == 0)
current_scope[enode->str] = enode.get();
else
input_error("enum item %s already exists in package\n", enode->str.c_str());
input_error("enum item %s already exists in package\n", enode->str);
}
}
}
@ -1438,7 +1438,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic)
children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment
if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg)
log_warning("wire '%s' is assigned in a block at %s.\n", children[0]->str.c_str(), loc_string().c_str());
log_warning("wire '%s' is assigned in a block at %s.\n", children[0]->str, loc_string());
if (type == AST_ASSIGN && children[0]->id2ast->is_reg) {
bool is_rand_reg = false;
if (children[1]->type == AST_FCALL) {
@ -1452,7 +1452,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
is_rand_reg = true;
}
if (!is_rand_reg)
log_warning("reg '%s' is assigned in a continuous assignment at %s.\n", children[0]->str.c_str(), loc_string().c_str());
log_warning("reg '%s' is assigned in a continuous assignment at %s.\n", children[0]->str, loc_string());
}
children[0]->was_checked = true;
}
@ -1499,7 +1499,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
break;
case AST_ENUM:
//log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep);
//log("\nENUM %s: %d child %d\n", str, basic_prep, children[0]->basic_prep);
if (!basic_prep) {
for (auto& item_node : children) {
while (!item_node->basic_prep && item_node->simplify(false, stage, -1, false))
@ -1561,10 +1561,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
const std::string &type_name = child->children[0]->str;
if (!current_scope.count(type_name))
input_error("Unknown identifier `%s' used as type name\n", type_name.c_str());
input_error("Unknown identifier `%s' used as type name\n", type_name);
AstNode *resolved_type_node = current_scope.at(type_name);
if (resolved_type_node->type != AST_TYPEDEF)
input_error("`%s' does not name a type\n", type_name.c_str());
input_error("`%s' does not name a type\n", type_name);
log_assert(resolved_type_node->children.size() == 1);
auto* template_node = resolved_type_node->children[0].get();
@ -1590,7 +1590,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
}
default:
log_error("Don't know how to translate static cast of type %s\n", type2str(template_node->type).c_str());
log_error("Don't know how to translate static cast of type %s\n", type2str(template_node->type));
}
}
@ -1909,13 +1909,13 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
}
if (pos == std::string::npos)
input_error("Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname).c_str());
input_error("Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname));
paramname = "\\" + paramname.substr(pos+1);
if (current_scope.at(modname)->type != AST_CELL)
input_error("Defparam argument `%s . %s` does not match a cell!\n",
RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
RTLIL::unescape_id(modname), RTLIL::unescape_id(paramname));
auto paraset = std::make_unique<AstNode>(location, AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : nullptr);
paraset->str = paramname;
@ -1943,11 +1943,11 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
log_assert(children[0]->type == AST_WIRETYPE);
auto type_name = children[0]->str;
if (!current_scope.count(type_name)) {
input_error("Unknown identifier `%s' used as type name\n", type_name.c_str());
input_error("Unknown identifier `%s' used as type name\n", type_name);
}
AstNode *resolved_type_node = current_scope.at(type_name);
if (resolved_type_node->type != AST_TYPEDEF)
input_error("`%s' does not name a type\n", type_name.c_str());
input_error("`%s' does not name a type\n", type_name);
log_assert(resolved_type_node->children.size() == 1);
auto& template_node = resolved_type_node->children[0];
@ -1985,7 +1985,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
// Cannot add packed dimensions if unpacked dimensions are already specified.
if (add_packed_dimensions && newNode->type == AST_MEMORY)
input_error("Cannot extend unpacked type `%s' with packed dimensions\n", type_name.c_str());
input_error("Cannot extend unpacked type `%s' with packed dimensions\n", type_name);
// Add packed dimensions.
if (add_packed_dimensions) {
@ -2030,7 +2030,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
children.insert(children.begin(), std::move(expr));
if (children[1]->type == AST_MEMORY)
input_error("unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
input_error("unpacked array type `%s' cannot be used for a parameter\n", children[1]->str);
fixup_hierarchy_flags();
did_something = true;
}
@ -2050,7 +2050,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
const char *second_part = children[1]->str.c_str();
if (second_part[0] == '\\')
second_part++;
newNode->str = stringf("%s[%d].%s", str.c_str(), children[0]->integer, second_part);
newNode->str = stringf("%s[%d].%s", str, children[0]->integer, second_part);
goto apply_newNode;
}
@ -2297,7 +2297,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod;
str = try_pop_module_prefix();
for (auto& node : current_scope_ast->children) {
//log("looking at mod scope child %s\n", type2str(node->type).c_str());
//log("looking at mod scope child %s\n", type2str(node->type));
switch (node->type) {
case AST_PARAMETER:
case AST_LOCALPARAM:
@ -2308,9 +2308,9 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
case AST_FUNCTION:
case AST_TASK:
case AST_DPI_FUNCTION:
//log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
//log("found child %s, %s\n", type2str(node->type), node->str);
if (str == node->str) {
//log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
//log("add %s, type %s to scope\n", str, type2str(node->type));
current_scope[node->str] = node.get();
}
break;
@ -2319,7 +2319,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
for (auto& enum_node : node->children) {
log_assert(enum_node->type==AST_ENUM_ITEM);
if (str == enum_node->str) {
//log("\nadding enum item %s to scope\n", str.c_str());
//log("\nadding enum item %s to scope\n", str);
current_scope[str] = enum_node.get();
}
}
@ -2331,7 +2331,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
}
if (current_scope.count(str) == 0) {
if (current_ast_mod == nullptr) {
input_error("Identifier `%s' is implicitly declared outside of a module.\n", str.c_str());
input_error("Identifier `%s' is implicitly declared outside of a module.\n", str);
} else if (flag_autowire || str == "\\$global_clock") {
auto auto_wire = std::make_unique<AstNode>(location, AST_AUTOWIRE);
auto_wire->str = str;
@ -2339,7 +2339,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
current_ast_mod->children.push_back(std::move(auto_wire));
did_something = true;
} else {
input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str);
}
}
if (id2ast != current_scope[str]) {
@ -2562,7 +2562,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
}
if (buf->type != AST_CONSTANT)
input_error("Right hand side of 3rd expression of %s for-loop is not constant (%s)!\n", loop_type_str, type2str(buf->type).c_str());
input_error("Right hand side of 3rd expression of %s for-loop is not constant (%s)!\n", loop_type_str, type2str(buf->type));
varbuf->children[0] = std::move(buf);
}
@ -2756,19 +2756,24 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
newNode = std::make_unique<AstNode>(location, AST_GENBLOCK);
int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1;
if (this->children.at(1)->type == AST_PRIMITIVE) {
// Move the range to the AST_PRIMITIVE node and replace this with the AST_PRIMITIVE node handled below
newNode = std::move(this->children.at(1));
newNode->range_left = this->children.at(0)->range_left;
newNode->range_right = this->children.at(0)->range_right;
newNode->range_valid = true;
goto apply_newNode;
}
for (int i = 0; i < num; i++) {
int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
auto new_cell_owned = children.at(1)->clone();
auto* new_cell = new_cell_owned.get();
newNode->children.push_back(std::move(new_cell_owned));
new_cell->str += stringf("[%d]", idx);
if (new_cell->type == AST_PRIMITIVE) {
input_error("Cell arrays of primitives are currently not supported.\n");
} else {
this->dumpAst(NULL, " ");
log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str());
}
log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str);
}
goto apply_newNode;
@ -2778,7 +2783,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
if (type == AST_PRIMITIVE)
{
if (children.size() < 2)
input_error("Insufficient number of arguments for primitive `%s'!\n", str.c_str());
input_error("Insufficient number of arguments for primitive `%s'!\n", str);
std::vector<std::unique_ptr<AstNode>> children_list;
for (auto& child : children) {
@ -2789,10 +2794,15 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
}
children.clear();
// TODO handle bit-widths of primitives and support cell arrays for more primitives
if (range_valid && str != "tran")
input_error("Cell arrays of primitives are currently not supported.\n");
if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
{
if (children_list.size() != 3)
input_error("Invalid number of arguments for primitive `%s'!\n", str.c_str());
input_error("Invalid number of arguments for primitive `%s'!\n", str);
std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
@ -2817,7 +2827,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
fixup_hierarchy_flags();
did_something = true;
}
else if (str == "buf" || str == "not")
else if (str == "buf" || str == "not" || str == "tran")
{
auto& input = children_list.back();
if (str == "not")
@ -2894,7 +2904,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
auto& range = children[0]->children[0];
if (!try_determine_range_width(range.get(), result_width))
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str);
if (range->children.size() >= 2)
shift_expr = range->children[1]->clone();
@ -3119,7 +3129,7 @@ skip_dynamic_range_lvalue_expansion:;
auto wire_tmp_owned = std::make_unique<AstNode>(location, AST_WIRE, std::make_unique<AstNode>(location, AST_RANGE, mkconst_int(location, width_hint-1, true), mkconst_int(location, 0, true)));
auto wire_tmp = wire_tmp_owned.get();
wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line, autoidx++);
wire_tmp->str = stringf("$splitcmplxassign$%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));
@ -3285,7 +3295,7 @@ skip_dynamic_range_lvalue_expansion:;
int width;
if (!try_determine_range_width(the_range.get(), width))
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str);
if (the_range->children.size() >= 2)
offset_ast = the_range->children[1]->clone();
@ -3394,18 +3404,18 @@ skip_dynamic_range_lvalue_expansion:;
if (GetSize(children) != 1 && GetSize(children) != 2)
input_error("System function %s got %d arguments, expected 1 or 2.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
if (!current_always_clocked)
input_error("System function %s is only allowed in clocked blocks.\n",
RTLIL::unescape_id(str).c_str());
RTLIL::unescape_id(str));
if (GetSize(children) == 2)
{
auto buf = children[1]->clone();
while (buf->simplify(true, stage, -1, false)) { }
if (buf->type != AST_CONSTANT)
input_error("Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
input_error("Failed to evaluate system function `%s' with non-constant value.\n", str);
num_steps = buf->asInt(true);
}
@ -3433,7 +3443,7 @@ skip_dynamic_range_lvalue_expansion:;
auto* reg = reg_owned.get();
current_ast_mod->children.push_back(std::move(reg_owned));
reg->str = stringf("$past$%s:%d$%d$%d", RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line, myidx, i);
reg->str = stringf("$past$%s:%d$%d$%d", RTLIL::encode_filename(*location.begin.filename), location.begin.line, myidx, i);
reg->is_reg = true;
reg->is_signed = sign_hint;
@ -3469,11 +3479,11 @@ skip_dynamic_range_lvalue_expansion:;
{
if (GetSize(children) != 1)
input_error("System function %s got %d arguments, expected 1.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
if (!current_always_clocked)
input_error("System function %s is only allowed in clocked blocks.\n",
RTLIL::unescape_id(str).c_str());
RTLIL::unescape_id(str));
auto present = children.at(0)->clone();
auto past = clone();
@ -3511,12 +3521,12 @@ skip_dynamic_range_lvalue_expansion:;
{
if (children.size() != 1)
input_error("System function %s got %d arguments, expected 1.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
auto buf = children[0]->clone();
while (buf->simplify(true, stage, width_hint, sign_hint)) { }
if (buf->type != AST_CONSTANT)
input_error("Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
input_error("Failed to evaluate system function `%s' with non-constant value.\n", str);
RTLIL::Const arg_value = buf->bitsAsConst();
if (arg_value.as_bool())
@ -3538,11 +3548,11 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$dimensions" || str == "\\$unpacked_dimensions" || str == "\\$bits") {
if (children.size() != 1)
input_error("System function %s got %d arguments, expected 1.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
} else {
if (children.size() != 1 && children.size() != 2)
input_error("System function %s got %d arguments, expected 1 or 2.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
if (children.size() == 2) {
auto buf = children[1]->clone();
// Evaluate constant expression
@ -3563,7 +3573,7 @@ skip_dynamic_range_lvalue_expansion:;
if (id_ast == nullptr && current_scope.count(buf->str))
id_ast = current_scope.at(buf->str);
if (!id_ast)
input_error("Failed to resolve identifier %s for width detection!\n", buf->str.c_str());
input_error("Failed to resolve identifier %s for width detection!\n", buf->str);
if (id_ast->type == AST_WIRE || id_ast->type == AST_MEMORY) {
// Check for item in packed struct / union
@ -3578,7 +3588,7 @@ skip_dynamic_range_lvalue_expansion:;
// TODO: IEEE Std 1800-2017 20.7: "If the first argument to an array query function would cause $dimensions to return 0
// or if the second argument is out of range, then 'x shall be returned."
if (dim < 1 || dim > dims)
input_error("Dimension %d out of range in `%s', as it only has %d dimensions!\n", dim, id_ast->str.c_str(), dims);
input_error("Dimension %d out of range in `%s', as it only has %d dimensions!\n", dim, id_ast->str, dims);
expr_dimensions = dims - dim + 1;
expr_unpacked_dimensions = std::max(id_ast->unpacked_dimensions - dim + 1, 0);
@ -3634,18 +3644,18 @@ skip_dynamic_range_lvalue_expansion:;
if (func_with_two_arguments) {
if (children.size() != 2)
input_error("System function %s got %d arguments, expected 2.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
} else {
if (children.size() != 1)
input_error("System function %s got %d arguments, expected 1.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
}
if (children.size() >= 1) {
while (children[0]->simplify(true, stage, width_hint, sign_hint)) { }
if (!children[0]->isConst())
input_error("Failed to evaluate system function `%s' with non-constant argument.\n",
RTLIL::unescape_id(str).c_str());
RTLIL::unescape_id(str));
int child_width_hint = width_hint;
bool child_sign_hint = sign_hint;
children[0]->detectSignWidth(child_width_hint, child_sign_hint);
@ -3656,7 +3666,7 @@ skip_dynamic_range_lvalue_expansion:;
while (children[1]->simplify(true, stage, width_hint, sign_hint)) { }
if (!children[1]->isConst())
input_error("Failed to evaluate system function `%s' with non-constant argument.\n",
RTLIL::unescape_id(str).c_str());
RTLIL::unescape_id(str));
int child_width_hint = width_hint;
bool child_sign_hint = sign_hint;
children[1]->detectSignWidth(child_width_hint, child_sign_hint);
@ -3703,7 +3713,7 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$countbits") {
if (children.size() < 2)
input_error("System function %s got %d arguments, expected at least 2.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
std::vector<RTLIL::State> control_bits;
@ -3712,9 +3722,9 @@ skip_dynamic_range_lvalue_expansion:;
auto& node = children[i];
while (node->simplify(true, stage, -1, false)) { }
if (node->type != AST_CONSTANT)
input_error("Failed to evaluate system function `%s' with non-constant control bit argument.\n", str.c_str());
input_error("Failed to evaluate system function `%s' with non-constant control bit argument.\n", str);
if (node->bits.size() != 1)
input_error("Failed to evaluate system function `%s' with control bit width != 1.\n", str.c_str());
input_error("Failed to evaluate system function `%s' with control bit width != 1.\n", str);
control_bits.push_back(node->bits[0]);
}
@ -3760,7 +3770,7 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$countones" || str == "\\$isunknown" || str == "\\$onehot" || str == "\\$onehot0") {
if (children.size() != 1)
input_error("System function %s got %d arguments, expected 1.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
auto countbits = clone();
countbits->str = "\\$countbits";
@ -3817,7 +3827,7 @@ skip_dynamic_range_lvalue_expansion:;
if (current_scope.count(str) == 0)
str = try_pop_module_prefix();
if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION)
input_error("Can't resolve function name `%s'.\n", str.c_str());
input_error("Can't resolve function name `%s'.\n", str);
}
if (type == AST_TCALL)
@ -3825,26 +3835,26 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "$finish" || str == "$stop")
{
if (!current_always || current_always->type != AST_INITIAL)
input_error("System task `%s' outside initial block is unsupported.\n", str.c_str());
input_error("System task `%s' outside initial block is unsupported.\n", str);
input_error("System task `%s' executed.\n", str.c_str());
input_error("System task `%s' executed.\n", str);
}
if (str == "\\$readmemh" || str == "\\$readmemb")
{
if (GetSize(children) < 2 || GetSize(children) > 4)
input_error("System function %s got %d arguments, expected 2-4.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
RTLIL::unescape_id(str), int(children.size()));
auto node_filename = children[0]->clone();
while (node_filename->simplify(true, stage, width_hint, sign_hint)) { }
if (node_filename->type != AST_CONSTANT)
input_error("Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str());
input_error("Failed to evaluate system function `%s' with non-constant 1st argument.\n", str);
auto node_memory = children[1]->clone();
while (node_memory->simplify(true, stage, width_hint, sign_hint)) { }
if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY)
input_error("Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str());
input_error("Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str);
int start_addr = -1, finish_addr = -1;
@ -3852,7 +3862,7 @@ skip_dynamic_range_lvalue_expansion:;
auto node_addr = children[2]->clone();
while (node_addr->simplify(true, stage, width_hint, sign_hint)) { }
if (node_addr->type != AST_CONSTANT)
input_error("Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str());
input_error("Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str);
start_addr = int(node_addr->asInt(false));
}
@ -3860,7 +3870,7 @@ skip_dynamic_range_lvalue_expansion:;
auto node_addr = children[3]->clone();
while (node_addr->simplify(true, stage, width_hint, sign_hint)) { }
if (node_addr->type != AST_CONSTANT)
input_error("Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str());
input_error("Failed to evaluate system function `%s' with non-constant 4th argument.\n", str);
finish_addr = int(node_addr->asInt(false));
}
@ -3888,7 +3898,7 @@ skip_dynamic_range_lvalue_expansion:;
if (current_scope.count(str) == 0)
str = try_pop_module_prefix();
if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK)
input_error("Can't resolve task name `%s'.\n", str.c_str());
input_error("Can't resolve task name `%s'.\n", str);
}
@ -3928,7 +3938,7 @@ skip_dynamic_range_lvalue_expansion:;
if (in_param)
input_error("Non-constant function call in constant expression.\n");
if (require_const_eval)
input_error("Function %s can only be called with constant arguments.\n", str.c_str());
input_error("Function %s can only be called with constant arguments.\n", str);
}
size_t arg_count = 0;
@ -4050,7 +4060,7 @@ skip_dynamic_range_lvalue_expansion:;
goto tcall_incompatible_wires;
} else {
tcall_incompatible_wires:
input_error("Incompatible re-declaration of wire %s.\n", child->str.c_str());
input_error("Incompatible re-declaration of wire %s.\n", child->str);
}
}
}
@ -4366,7 +4376,7 @@ replace_fcall_later:;
log_assert(a.size() == b.size());
for (auto i = 0; i < a.size(); i++)
if (a[i] != b[i])
a.bits()[i] = RTLIL::State::Sx;
a.set(i, RTLIL::State::Sx);
newNode = mkconst_bits(location, a.to_bits(), sign_hint);
} else if (children[1]->isConst() && children[2]->isConst()) {
newNode = std::make_unique<AstNode>(location, AST_REALVALUE);
@ -4476,7 +4486,7 @@ std::unique_ptr<AstNode> AstNode::readmem(bool is_readmemh, std::string mem_file
yosys_input_files.insert(mem_filename);
}
if (f.fail() || GetSize(mem_filename) == 0)
input_error("Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str());
input_error("Can not open file `%s` for %s.\n", mem_filename, str);
log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid);
int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right;
@ -4522,7 +4532,7 @@ std::unique_ptr<AstNode> AstNode::readmem(bool is_readmemh, std::string mem_file
char *endptr;
cursor = strtol(nptr, &endptr, 16);
if (!*nptr || *endptr)
input_error("Can not parse address `%s` for %s.\n", nptr, str.c_str());
input_error("Can not parse address `%s` for %s.\n", nptr, str);
continue;
}
@ -4754,7 +4764,7 @@ static void mark_memories_assign_lhs_complex(dict<AstNode*, pool<std::string>> &
if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) {
AstNode *mem = that->id2ast;
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_CMPLX_LHS))
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*that->location.begin.filename).c_str(), that->location.begin.line));
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*that->location.begin.filename), that->location.begin.line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CMPLX_LHS;
}
}
@ -4782,14 +4792,14 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
// activate mem2reg if this is assigned in an async proc
if (flags & AstNode::MEM2REG_FL_ASYNC) {
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC))
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line));
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename), location.begin.line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC;
}
// remember if this is assigned blocking (=)
if (type == AST_ASSIGN_EQ) {
if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1))
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line));
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename), location.begin.line));
proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
}
@ -4806,11 +4816,11 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
// remember where this is
if (flags & MEM2REG_FL_INIT) {
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line));
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename), location.begin.line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT;
} else {
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE))
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line));
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename), location.begin.line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE;
}
}
@ -4827,7 +4837,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
// flag if used after blocking assignment (in same proc)
if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) {
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line));
mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(*location.begin.filename), location.begin.line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2;
}
}
@ -5070,7 +5080,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
auto assign_reg = std::make_unique<AstNode>(location, type, std::make_unique<AstNode>(location, AST_IDENTIFIER), std::make_unique<AstNode>(location, AST_IDENTIFIER));
if (children[0]->children.size() == 2)
assign_reg->children[0]->children.push_back(children[0]->children[1]->clone());
assign_reg->children[0]->str = stringf("%s[%d]", children[0]->str.c_str(), i);
assign_reg->children[0]->str = stringf("%s[%d]", children[0]->str, i);
assign_reg->children[1]->str = id_data;
cond_node->children[1]->children.push_back(std::move(assign_reg));
case_node->children.push_back(std::move(cond_node));
@ -5108,7 +5118,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
(right <= id && id <= left);
if (valid_const_access)
{
str = stringf("%s[%d]", str.c_str(), id);
str = stringf("%s[%d]", str, id);
delete_children();
range_valid = false;
id2ast = nullptr;
@ -5185,7 +5195,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
auto assign_reg = std::make_unique<AstNode>(location, AST_ASSIGN_EQ, std::make_unique<AstNode>(location, AST_IDENTIFIER), std::make_unique<AstNode>(location, AST_IDENTIFIER));
assign_reg->children[0]->str = id_data;
assign_reg->children[0]->was_checked = true;
assign_reg->children[1]->str = stringf("%s[%d]", str.c_str(), i);
assign_reg->children[1]->str = stringf("%s[%d]", str, i);
cond_node->children[1]->children.push_back(std::move(assign_reg));
case_node->children.push_back(std::move(cond_node));
}
@ -5368,8 +5378,11 @@ bool AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia
offset -= variables.at(str).offset;
if (variables.at(str).range_swapped)
offset = -offset;
std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits();
std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width);
const RTLIL::Const &val = variables.at(str).val;
std::vector<RTLIL::State> new_bits;
new_bits.reserve(width);
for (int i = 0; i < width; i++)
new_bits.push_back(val[offset+i]);
auto newNode = mkconst_bits(location, new_bits, variables.at(str).is_signed);
newNode->cloneInto(*this);
return true;
@ -5404,7 +5417,7 @@ std::unique_ptr<AstNode> AstNode::eval_const_function(AstNode *fcall, bool must_
#if 0
log("-----------------------------------\n");
for (auto &it : variables)
log("%20s %40s\n", it.first.c_str(), log_signal(it.second.val));
log("%20s %40s\n", it.first, log_signal(it.second.val));
stmt->dumpAst(nullptr, "stmt> ");
#endif
if (stmt->type == AST_WIRE)
@ -5421,7 +5434,7 @@ std::unique_ptr<AstNode> AstNode::eval_const_function(AstNode *fcall, bool must_
// if this variable has already been declared as an input, check the
// sizes match if it already had an explicit size
if (variable.arg && variable.explicitly_sized && variable.val.size() != width) {
input_error("Incompatible re-declaration of constant function wire %s.\n", stmt->str.c_str());
input_error("Incompatible re-declaration of constant function wire %s.\n", stmt->str);
}
variable.val = RTLIL::Const(RTLIL::State::Sx, width);
variable.offset = stmt->range_swapped ? stmt->range_left : stmt->range_right;
@ -5503,7 +5516,7 @@ std::unique_ptr<AstNode> AstNode::eval_const_function(AstNode *fcall, bool must_
if (!range->range_valid) {
if (!must_succeed)
goto finished;
range->input_error("Non-constant range\n%s: ... called from here.\n", fcall->loc_string().c_str());
range->input_error("Non-constant range\n%s: ... called from here.\n", fcall->loc_string());
}
int offset = min(range->range_left, range->range_right);
int width = std::abs(range->range_left - range->range_right) + 1;
@ -5513,7 +5526,7 @@ std::unique_ptr<AstNode> AstNode::eval_const_function(AstNode *fcall, bool must_
int index = i + offset - v.offset;
if (v.range_swapped)
index = -index;
v.val.bits().at(index) = r.at(i);
v.val.set(index, r.at(i));
}
}

View file

@ -149,7 +149,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (buffer[0] == '.')
{
if (lutptr) {
for (auto &bit : lutptr->bits())
for (auto bit : *lutptr)
if (bit == RTLIL::State::Sx)
bit = lut_default_state;
lutptr = NULL;
@ -321,9 +321,10 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
const_v = Const(str);
} else {
int n = strlen(v);
const_v.bits().resize(n);
Const::Builder const_v_builder(n);
for (int i = 0; i < n; i++)
const_v.bits()[i] = v[n-i-1] != '0' ? State::S1 : State::S0;
const_v_builder.push_back(v[n-i-1] != '0' ? State::S1 : State::S0);
const_v = const_v_builder.build();
}
if (!strcmp(cmd, ".attr")) {
if (obj_attributes == nullptr) {
@ -362,17 +363,17 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
goto no_latch_clock;
if (!strcmp(edge, "re"))
cell = module->addDff(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q));
cell = module->addDffGate(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q));
else if (!strcmp(edge, "fe"))
cell = module->addDff(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q), false);
cell = module->addDffGate(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q), false);
else if (!strcmp(edge, "ah"))
cell = module->addDlatch(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q));
cell = module->addDlatchGate(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q));
else if (!strcmp(edge, "al"))
cell = module->addDlatch(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q), false);
cell = module->addDlatchGate(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q), false);
else {
no_latch_clock:
if (dff_name.empty()) {
cell = module->addFf(NEW_ID, blif_wire(d), blif_wire(q));
cell = module->addFfGate(NEW_ID, blif_wire(d), blif_wire(q));
} else {
cell = module->addCell(NEW_ID, dff_name);
cell->setPort(ID::D, blif_wire(d));
@ -563,21 +564,23 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
log_assert(sopcell->parameters[ID::WIDTH].as_int() == input_len);
sopcell->parameters[ID::DEPTH] = sopcell->parameters[ID::DEPTH].as_int() + 1;
Const::Builder table_bits_builder(input_len * 2);
for (int i = 0; i < input_len; i++)
switch (input[i]) {
case '0':
sopcell->parameters[ID::TABLE].bits().push_back(State::S1);
sopcell->parameters[ID::TABLE].bits().push_back(State::S0);
table_bits_builder.push_back(State::S1);
table_bits_builder.push_back(State::S0);
break;
case '1':
sopcell->parameters[ID::TABLE].bits().push_back(State::S0);
sopcell->parameters[ID::TABLE].bits().push_back(State::S1);
table_bits_builder.push_back(State::S0);
table_bits_builder.push_back(State::S1);
break;
default:
sopcell->parameters[ID::TABLE].bits().push_back(State::S0);
sopcell->parameters[ID::TABLE].bits().push_back(State::S0);
table_bits_builder.push_back(State::S0);
table_bits_builder.push_back(State::S0);
break;
}
sopcell->parameters[ID::TABLE].append(table_bits_builder.build());
if (sopmode == -1) {
sopmode = (*output == '1');
@ -605,7 +608,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
goto try_next_value;
}
}
lutptr->bits().at(i) = !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1;
lutptr->set(i, !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1);
try_next_value:;
}
@ -618,7 +621,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
error:
log_error("Syntax error in line %d!\n", line_count);
error_with_reason:
log_error("Syntax error in line %d: %s\n", line_count, err_reason.c_str());
log_error("Syntax error in line %d: %s\n", line_count, err_reason);
}
struct BlifFrontend : public Frontend {

View file

@ -258,7 +258,7 @@ Const json_parse_attr_param_value(JsonNode *node)
}
} else
if (node->type == 'N') {
value = Const(node->data_number, 32);
value = Const(node->data_number);
if (node->data_number < 0)
value.flags |= RTLIL::CONST_FLAG_SIGNED;
} else
@ -289,7 +289,7 @@ void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
void json_import(Design *design, string &modname, JsonNode *node)
{
log("Importing module %s from JSON tree.\n", modname.c_str());
log("Importing module %s from JSON tree.\n", modname);
Module *module = new RTLIL::Module;
module->name = RTLIL::escape_id(modname.c_str());
@ -367,7 +367,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.c_str());
log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", log_id(port_name), port_direction_node->data_string);
port_wire->port_id = port_id;

View file

@ -47,7 +47,7 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
std::string id = RTLIL::escape_id(std::string(expr, id_len));
if (!module->wires_.count(id))
log_error("Can't resolve wire name %s.\n", RTLIL::unescape_id(id).c_str());
log_error("Can't resolve wire name %s.\n", RTLIL::unescape_id(id));
expr += id_len;
return module->wires_.at(id);
@ -537,7 +537,7 @@ struct LibertyFrontend : public Frontend {
if (flag_wb && flag_lib)
log_error("-wb and -lib cannot be specified together!\n");
log_header(design, "Executing Liberty frontend: %s\n", filename.c_str());
log_header(design, "Executing Liberty frontend: %s\n", filename);
LibertyParser parser(*f, filename);
int cell_count = 0;
@ -550,7 +550,7 @@ struct LibertyFrontend : public Frontend {
if (cell->id != "cell" || cell->args.size() != 1)
continue;
// log("Processing cell type %s.\n", RTLIL::unescape_id(cell_name).c_str());
// log("Processing cell type %s.\n", RTLIL::unescape_id(cell_name));
std::map<std::string, std::tuple<int, int, bool>> type_map = global_type_map;
parse_type_map(type_map, cell);
@ -582,9 +582,9 @@ struct LibertyFrontend : public Frontend {
{
if (!flag_ignore_miss_dir)
{
log_error("Missing or invalid direction for pin %s on cell %s.\n", node->args.at(0).c_str(), log_id(module->name));
log_error("Missing or invalid direction for pin %s on cell %s.\n", node->args.at(0), log_id(module->name));
} else {
log("Ignoring cell %s with missing or invalid direction for pin %s.\n", log_id(module->name), node->args.at(0).c_str());
log("Ignoring cell %s with missing or invalid direction for pin %s.\n", log_id(module->name), node->args.at(0));
delete module;
goto skip_cell;
}
@ -596,7 +596,7 @@ struct LibertyFrontend : public Frontend {
if (node->id == "bus" && node->args.size() == 1)
{
if (flag_ignore_buses) {
log("Ignoring cell %s with a bus interface %s.\n", log_id(module->name), node->args.at(0).c_str());
log("Ignoring cell %s with a bus interface %s.\n", log_id(module->name), node->args.at(0));
delete module;
goto skip_cell;
}
@ -613,7 +613,7 @@ struct LibertyFrontend : public Frontend {
}
if (!dir || (dir->value != "input" && dir->value != "output" && dir->value != "inout" && dir->value != "internal"))
log_error("Missing or invalid direction for bus %s on cell %s.\n", node->args.at(0).c_str(), log_id(module->name));
log_error("Missing or invalid direction for bus %s on cell %s.\n", node->args.at(0), log_id(module->name));
simple_comb_cell = false;

View file

@ -83,17 +83,17 @@ struct RpcServer {
std::string request;
json_request.dump(request);
request += '\n';
log_debug("RPC frontend request: %s", request.c_str());
log_debug("RPC frontend request: %s", request);
write(request);
std::string response = read();
log_debug("RPC frontend response: %s", response.c_str());
log_debug("RPC frontend response: %s", response);
std::string error;
Json json_response = Json::parse(response, error);
if (json_response.is_null())
log_cmd_error("parsing JSON failed: %s\n", error.c_str());
log_cmd_error("parsing JSON failed: %s\n", error);
if (json_response["error"].is_string())
log_cmd_error("RPC frontend returned an error: %s\n", json_response["error"].string_value().c_str());
log_cmd_error("RPC frontend returned an error: %s\n", json_response["error"].string_value());
return json_response;
}
@ -111,7 +111,7 @@ struct RpcServer {
}
} else is_valid = false;
if (!is_valid)
log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump().c_str());
log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump());
return modules;
}
@ -149,7 +149,7 @@ struct RpcServer {
source = response["source"].string_value();
else is_valid = false;
if (!is_valid)
log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump().c_str());
log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump());
return std::make_pair(frontend, source);
}
};
@ -163,12 +163,12 @@ struct RpcModule : RTLIL::Module {
stripped_name = stripped_name.substr(9);
log_assert(stripped_name[0] == '\\');
log_header(design, "Executing RPC frontend `%s' for module `%s'.\n", server->name.c_str(), stripped_name.c_str());
log_header(design, "Executing RPC frontend `%s' for module `%s'.\n", server->name, stripped_name);
std::string parameter_info;
for (auto &param : parameters) {
log("Parameter %s = %s\n", param.first.c_str(), log_signal(RTLIL::SigSpec(param.second)));
parameter_info += stringf("%s=%s", param.first.c_str(), log_signal(RTLIL::SigSpec(param.second)));
log("Parameter %s = %s\n", param.first, log_signal(RTLIL::SigSpec(param.second)));
parameter_info += stringf("%s=%s", param.first, log_signal(RTLIL::SigSpec(param.second)));
}
std::string derived_name;
@ -180,7 +180,7 @@ struct RpcModule : RTLIL::Module {
derived_name = "$paramod" + stripped_name + parameter_info;
if (design->has(derived_name)) {
log("Found cached RTLIL representation for module `%s'.\n", derived_name.c_str());
log("Found cached RTLIL representation for module `%s'.\n", derived_name);
} else {
std::string command, input;
std::tie(command, input) = server->derive_module(stripped_name.substr(1), parameters);
@ -202,7 +202,7 @@ struct RpcModule : RTLIL::Module {
}
}
if (!found_derived_top)
log_cmd_error("RPC frontend did not return requested module `%s`!\n", stripped_name.c_str());
log_cmd_error("RPC frontend did not return requested module `%s`!\n", stripped_name);
for (auto module : derived_design->modules())
for (auto cell : module->cells())
@ -256,7 +256,7 @@ struct HandleRpcServer : RpcServer {
do {
DWORD data_written;
if (!WriteFile(hsend, &data[offset], data.length() - offset, &data_written, /*lpOverlapped=*/NULL))
log_cmd_error("WriteFile failed: %s\n", get_last_error_str().c_str());
log_cmd_error("WriteFile failed: %s\n", get_last_error_str());
offset += data_written;
} while(offset < (ssize_t)data.length());
}
@ -268,7 +268,7 @@ struct HandleRpcServer : RpcServer {
data.resize(data.length() + 1024);
DWORD data_read;
if (!ReadFile(hrecv, &data[offset], data.length() - offset, &data_read, /*lpOverlapped=*/NULL))
log_cmd_error("ReadFile failed: %s\n", get_last_error_str().c_str());
log_cmd_error("ReadFile failed: %s\n", get_last_error_str());
offset += data_read;
data.resize(offset);
size_t term_pos = data.find('\n', offset);
@ -437,7 +437,7 @@ struct RpcFrontend : public Pass {
command_path_len_w = SearchPathW(/*lpPath=*/NULL, /*lpFileName=*/command_w.c_str(), /*lpExtension=*/L".exe", /*nBufferLength=*/0, /*lpBuffer=*/NULL, /*lpFilePart=*/NULL);
if (command_path_len_w == 0) {
log_error("SearchPathW failed: %s\n", get_last_error_str().c_str());
log_error("SearchPathW failed: %s\n", get_last_error_str());
goto cleanup_exec;
}
command_path_w.resize(command_path_len_w - 1);
@ -448,19 +448,19 @@ struct RpcFrontend : public Pass {
pipe_attr.bInheritHandle = TRUE;
pipe_attr.lpSecurityDescriptor = NULL;
if (!CreatePipe(&send_r, &send_w, &pipe_attr, /*nSize=*/0)) {
log_error("CreatePipe failed: %s\n", get_last_error_str().c_str());
log_error("CreatePipe failed: %s\n", get_last_error_str());
goto cleanup_exec;
}
if (!SetHandleInformation(send_w, HANDLE_FLAG_INHERIT, 0)) {
log_error("SetHandleInformation failed: %s\n", get_last_error_str().c_str());
log_error("SetHandleInformation failed: %s\n", get_last_error_str());
goto cleanup_exec;
}
if (!CreatePipe(&recv_r, &recv_w, &pipe_attr, /*nSize=*/0)) {
log_error("CreatePipe failed: %s\n", get_last_error_str().c_str());
log_error("CreatePipe failed: %s\n", get_last_error_str());
goto cleanup_exec;
}
if (!SetHandleInformation(recv_r, HANDLE_FLAG_INHERIT, 0)) {
log_error("SetHandleInformation failed: %s\n", get_last_error_str().c_str());
log_error("SetHandleInformation failed: %s\n", get_last_error_str());
goto cleanup_exec;
}
@ -470,7 +470,7 @@ struct RpcFrontend : public Pass {
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
startup_info.dwFlags |= STARTF_USESTDHANDLES;
if (!CreateProcessW(/*lpApplicationName=*/command_path_w.c_str(), /*lpCommandLine=*/&command_line_w[0], /*lpProcessAttributes=*/NULL, /*lpThreadAttributes=*/NULL, /*bInheritHandles=*/TRUE, /*dwCreationFlags=*/0, /*lpEnvironment=*/NULL, /*lpCurrentDirectory=*/NULL, &startup_info, &proc_info)) {
log_error("CreateProcessW failed: %s\n", get_last_error_str().c_str());
log_error("CreateProcessW failed: %s\n", get_last_error_str());
goto cleanup_exec;
}
CloseHandle(proc_info.hProcess);
@ -550,7 +550,7 @@ cleanup_exec:
h = CreateFileW(path_w.c_str(), GENERIC_READ|GENERIC_WRITE, /*dwShareMode=*/0, /*lpSecurityAttributes=*/NULL, /*dwCreationDisposition=*/OPEN_EXISTING, /*dwFlagsAndAttributes=*/0, /*hTemplateFile=*/NULL);
if (h == INVALID_HANDLE_VALUE) {
log_error("CreateFileW failed: %s\n", get_last_error_str().c_str());
log_error("CreateFileW failed: %s\n", get_last_error_str());
goto cleanup_path;
}
@ -586,7 +586,7 @@ cleanup_path:
log_cmd_error("Failed to connect to RPC frontend.\n");
for (auto &module_name : server->get_module_names()) {
log("Linking module `%s'.\n", module_name.c_str());
log("Linking module `%s'.\n", module_name);
RpcModule *module = new RpcModule;
module->name = "$abstract\\" + module_name;
module->server = server;

View file

@ -90,7 +90,7 @@ struct RTLILFrontend : public Frontend {
}
extra_args(f, filename, args, argidx);
log("Input filename: %s\n", filename.c_str());
log("Input filename: %s\n", filename);
RTLIL_FRONTEND::lexin = f;
RTLIL_FRONTEND::current_design = design;

View file

@ -455,16 +455,17 @@ constant:
}
while ((int)bits.size() > width)
bits.pop_back();
$$ = new RTLIL::Const;
for (auto it = bits.begin(); it != bits.end(); it++)
$$->bits().push_back(*it);
RTLIL::Const::Builder builder(bits.size());
for (RTLIL::State bit : bits)
builder.push_back(bit);
$$ = new RTLIL::Const(builder.build());
if (is_signed) {
$$->flags |= RTLIL::CONST_FLAG_SIGNED;
}
free($1);
} |
TOK_INT {
$$ = new RTLIL::Const($1, 32);
$$ = new RTLIL::Const($1);
} |
TOK_STRING {
$$ = new RTLIL::Const($1);

View file

@ -129,7 +129,7 @@ void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefil
message += vstringf(msg, args);
if (log_verific_callback) {
string full_message = stringf("%s%s\n", message_prefix.c_str(), message.c_str());
string full_message = stringf("%s%s\n", message_prefix, message);
#ifdef VERIFIC_LINEFILE_INCLUDES_COLUMNS
log_verific_callback(int(msg_type), message_id, LineFile::GetFileName(linefile),
linefile ? linefile->GetLeftLine() : 0, linefile ? linefile->GetLeftCol() : 0,
@ -141,9 +141,9 @@ void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefil
#endif
} else {
if (msg_type == VERIFIC_ERROR || msg_type == VERIFIC_WARNING || msg_type == VERIFIC_PROGRAM_ERROR)
log_warning_noprefix("%s%s\n", message_prefix.c_str(), message.c_str());
log_warning_noprefix("%s%s\n", message_prefix, message);
else
log("%s%s\n", message_prefix.c_str(), message.c_str());
log("%s%s\n", message_prefix, message);
}
if (verific_error_msg.empty() && (msg_type == VERIFIC_ERROR || msg_type == VERIFIC_PROGRAM_ERROR))
verific_error_msg = message;
@ -200,8 +200,8 @@ YosysStreamCallBackHandler verific_read_cb;
// ==================================================================
VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit) :
mode_gates(mode_gates), mode_keep(mode_keep), mode_nosva(mode_nosva),
VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_sva_continue, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit) :
mode_gates(mode_gates), mode_keep(mode_keep), mode_nosva(mode_nosva), mode_sva_continue(mode_sva_continue),
mode_names(mode_names), mode_verific(mode_verific), mode_autocover(mode_autocover),
mode_fullinit(mode_fullinit)
{
@ -232,7 +232,7 @@ RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj)
{
std::string s = stringf("$verific$%s", obj->Name());
if (obj->Linefile())
s += stringf("$%s:%d", RTLIL::encode_filename(Verific::LineFile::GetFileName(obj->Linefile())).c_str(), Verific::LineFile::GetLineNo(obj->Linefile()));
s += stringf("$%s:%d", RTLIL::encode_filename(Verific::LineFile::GetFileName(obj->Linefile())), Verific::LineFile::GetLineNo(obj->Linefile()));
s += stringf("$%d", autoidx++);
return s;
}
@ -250,7 +250,7 @@ static const RTLIL::Const extract_vhdl_bit(std::string &val, std::string &typ)
{
if (val.size()==3 && val[0]=='\'' && val.back()=='\'')
return RTLIL::Const::from_string(val.substr(1,val.size()-2));
log_error("Error parsing VHDL %s.\n", typ.c_str());
log_error("Error parsing VHDL %s.\n", typ);
}
static const RTLIL::Const extract_vhdl_bit_vector(std::string &val, std::string &typ)
@ -261,19 +261,19 @@ static const RTLIL::Const extract_vhdl_bit_vector(std::string &val, std::string
c.flags |= RTLIL::CONST_FLAG_SIGNED;
return c;
}
log_error("Error parsing VHDL %s.\n", typ.c_str());
log_error("Error parsing VHDL %s.\n", typ);
}
static const RTLIL::Const extract_vhdl_integer(std::string &val)
{
char *end;
return RTLIL::Const((int)std::strtol(val.c_str(), &end, 10), 32);
return RTLIL::Const((int)std::strtol(val.c_str(), &end, 10));
}
static const RTLIL::Const extract_vhdl_char(std::string &val)
{
if (val.size()==3 && val[0]=='\"' && val.back()=='\"')
return RTLIL::Const((int)val[1], 32);
return RTLIL::Const((int)val[1]);
log_error("Error parsing VHDL character.\n");
}
@ -311,7 +311,7 @@ static const RTLIL::Const extract_vhdl_const(const char *value, bool output_sig
} else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) &&
((decimal = std::strtol(value, &end, 10)), !end[0])) {
is_signed = output_signed;
c = RTLIL::Const((int)decimal, 32);
c = RTLIL::Const((int)decimal);
} else if (val == "false") {
c = RTLIL::Const::from_string("0");
} else if (val == "true") {
@ -344,7 +344,7 @@ static const RTLIL::Const extract_verilog_const(const char *value, bool allow_s
} else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) &&
((decimal = std::strtol(value, &end, 10)), !end[0])) {
is_signed = output_signed;
c = RTLIL::Const((int)decimal, 32);
c = RTLIL::Const((int)decimal);
} else if (allow_string) {
c = RTLIL::Const(val);
} else {
@ -472,7 +472,7 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
if (nl->IsFromVerilog()) {
auto const value = verific_const(type_name, v, nl, false);
attributes.emplace(stringf("\\enum_value_%s", value.as_string().c_str()), RTLIL::escape_id(k));
attributes.emplace(stringf("\\enum_value_%s", value.as_string()), RTLIL::escape_id(k));
}
#ifdef VERIFIC_VHDL_SUPPORT
else if (nl->IsFromVhdl()) {
@ -1469,7 +1469,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
if (design->has(module_name)) {
if (!nl->IsOperator() && !is_blackbox(nl))
log_cmd_error("Re-definition of module `%s'.\n", netlist_name.c_str());
log_cmd_error("Re-definition of module `%s'.\n", netlist_name);
return;
}
@ -1926,7 +1926,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
RTLIL::SigSpec data = operatorOutput(inst).extract(i * memory->width, memory->width);
RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name :
RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), ID($memrd));
RTLIL::IdString(stringf("%s_%d", inst_name, i)), ID($memrd));
cell->parameters[ID::MEMID] = memory->name.str();
cell->parameters[ID::CLK_ENABLE] = false;
cell->parameters[ID::CLK_POLARITY] = true;
@ -1956,7 +1956,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
RTLIL::SigSpec data = operatorInput2(inst).extract(i * memory->width, memory->width);
RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name :
RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), ID($memwr));
RTLIL::IdString(stringf("%s_%d", inst_name, i)), ID($memwr));
cell->parameters[ID::MEMID] = memory->name.str();
cell->parameters[ID::CLK_ENABLE] = false;
cell->parameters[ID::CLK_POLARITY] = true;
@ -2316,6 +2316,12 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
wire->attributes.erase(ID::init);
}
}
if (num_sva_continue) {
log_warning("Encountered %d items containing unsupported SVA!\n", num_sva_continue);
log_warning("Unsupported SVA imported as 'x and marked using the `unsupported_sva' attribute due to -sva-continue-on-err.\n");
}
num_sva_continue = 0;
}
// ==================================================================
@ -2655,7 +2661,7 @@ struct VerificExtNets
cursor = ((Instance*)cursor->GetReferences()->GetLast())->Owner();
}
log_error("No common ancestor found between %s and %s.\n", get_full_netlist_name(A).c_str(), get_full_netlist_name(B).c_str());
log_error("No common ancestor found between %s and %s.\n", get_full_netlist_name(A), get_full_netlist_name(B));
}
void run(Netlist *nl)
@ -2679,17 +2685,17 @@ struct VerificExtNets
continue;
if (verific_verbose)
log("Fixing external net reference on port %s.%s.%s:\n", get_full_netlist_name(nl).c_str(), inst->Name(), port->Name());
log("Fixing external net reference on port %s.%s.%s:\n", get_full_netlist_name(nl), inst->Name(), port->Name());
Netlist *ext_nl = net->Owner();
if (verific_verbose)
log(" external net owner: %s\n", get_full_netlist_name(ext_nl).c_str());
log(" external net owner: %s\n", get_full_netlist_name(ext_nl));
Netlist *ca_nl = find_common_ancestor(nl, ext_nl);
if (verific_verbose)
log(" common ancestor: %s\n", get_full_netlist_name(ca_nl).c_str());
log(" common ancestor: %s\n", get_full_netlist_name(ca_nl));
Net *ca_net = route_up(net, !port->IsOutput(), ca_nl);
Net *new_net = ca_net;
@ -3038,7 +3044,7 @@ std::string verific_import(Design *design, const std::map<std::string,std::strin
}
if (!verific_error_msg.empty())
log_error("%s\n", verific_error_msg.c_str());
log_error("%s\n", verific_error_msg);
for (auto nl : nl_todo)
nl.second->ChangePortBusStructures(1 /* hierarchical */);
@ -3051,7 +3057,7 @@ std::string verific_import(Design *design, const std::map<std::string,std::strin
auto it = nl_todo.begin();
Netlist *nl = it->second;
if (nl_done.count(it->first) == 0) {
VerificImporter importer(false, false, false, false, false, false, false);
VerificImporter importer(false, false, false, false, false, false, false, false);
nl_done[it->first] = it->second;
importer.import_netlist(design, nl, nl_todo, top_mod_names.count(nl->CellBaseName()));
}
@ -3060,7 +3066,7 @@ std::string verific_import(Design *design, const std::map<std::string,std::strin
verific_cleanup();
if (!verific_error_msg.empty())
log_error("%s\n", verific_error_msg.c_str());
log_error("%s\n", verific_error_msg);
return top;
}
@ -3288,6 +3294,11 @@ struct VerificPass : public Pass {
log(" -nosva\n");
log(" Ignore SVA properties, do not infer checker logic.\n");
log("\n");
log(" -sva-continue-on-err\n");
log(" Turns unsupported SVA from an error into a warning. Properties are imported\n");
log(" with their trigger condition replaced with 'x and with an `unsupported_sva'\n");
log(" attribute to produce a later error in SBY if they remain in the design.\n");
log("\n");
log(" -L <int>\n");
log(" Maximum number of ctrl bits for SVA checker FSMs (default=16).\n");
log("\n");
@ -3349,7 +3360,7 @@ struct VerificPass : public Pass {
char block[4096];
while (1) {
if (fgets(block, 4096, Frontend::current_script_file == nullptr? stdin : Frontend::current_script_file) == nullptr)
log_error("Unexpected end of file in here document '%s'!\n", filename.c_str());
log_error("Unexpected end of file in here document '%s'!\n", filename);
buffer += block;
if (buffer.size() > 0 && (buffer[buffer.size() - 1] == '\n' || buffer[buffer.size() - 1] == '\r'))
break;
@ -3824,7 +3835,7 @@ struct VerificPass : public Pass {
add_units_to_map(map, work, flag_lib);
std::string filename = frontent_rewrite(args, argidx, tmp_files);
if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_87))
log_cmd_error("Reading `%s' in VHDL_87 mode failed.\n", filename.c_str());
log_cmd_error("Reading `%s' in VHDL_87 mode failed.\n", filename);
set_units_to_blackbox(map, work, flag_lib);
}
verific_import_pending = true;
@ -3849,7 +3860,7 @@ struct VerificPass : public Pass {
add_units_to_map(map, work, flag_lib);
std::string filename = frontent_rewrite(args, argidx, tmp_files);
if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_93))
log_cmd_error("Reading `%s' in VHDL_93 mode failed.\n", filename.c_str());
log_cmd_error("Reading `%s' in VHDL_93 mode failed.\n", filename);
set_units_to_blackbox(map, work, flag_lib);
}
verific_import_pending = true;
@ -3874,7 +3885,7 @@ struct VerificPass : public Pass {
add_units_to_map(map, work, flag_lib);
std::string filename = frontent_rewrite(args, argidx, tmp_files);
if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_2K))
log_cmd_error("Reading `%s' in VHDL_2K mode failed.\n", filename.c_str());
log_cmd_error("Reading `%s' in VHDL_2K mode failed.\n", filename);
set_units_to_blackbox(map, work, flag_lib);
}
verific_import_pending = true;
@ -3899,7 +3910,7 @@ struct VerificPass : public Pass {
add_units_to_map(map, work, flag_lib);
std::string filename = frontent_rewrite(args, argidx, tmp_files);
if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_2019))
log_cmd_error("Reading `%s' in VHDL_2019 mode failed.\n", filename.c_str());
log_cmd_error("Reading `%s' in VHDL_2019 mode failed.\n", filename);
set_units_to_blackbox(map, work, flag_lib);
}
verific_import_pending = true;
@ -3924,7 +3935,7 @@ struct VerificPass : public Pass {
add_units_to_map(map, work, flag_lib);
std::string filename = frontent_rewrite(args, argidx, tmp_files);
if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_2008))
log_cmd_error("Reading `%s' in VHDL_2008 mode failed.\n", filename.c_str());
log_cmd_error("Reading `%s' in VHDL_2008 mode failed.\n", filename);
set_units_to_blackbox(map, work, flag_lib);
}
verific_import_pending = true;
@ -3938,7 +3949,7 @@ struct VerificPass : public Pass {
while (argidx < GetSize(args)) {
std::string filename = frontent_rewrite(args, argidx, tmp_files);
if (!edif.Read(filename.c_str()))
log_cmd_error("Reading `%s' in EDIF mode failed.\n", filename.c_str());
log_cmd_error("Reading `%s' in EDIF mode failed.\n", filename);
}
goto check_error;
}
@ -3961,7 +3972,7 @@ struct VerificPass : public Pass {
while (argidx < GetSize(args)) {
std::string filename = frontent_rewrite(args, argidx, tmp_files);
if (!synlib_file::Read(filename.c_str(), is_work_set ? work.c_str() : nullptr))
log_cmd_error("Reading `%s' in LIBERTY mode failed.\n", filename.c_str());
log_cmd_error("Reading `%s' in LIBERTY mode failed.\n", filename);
SynlibLibrary *lib = synlib_file::GetLastLibraryAnalyzed();
if (lib && flag_lib) {
MapIter mi ;
@ -4033,7 +4044,8 @@ struct VerificPass : public Pass {
{
std::map<std::string,Netlist*> nl_todo, nl_done;
bool mode_all = false, mode_gates = false, mode_keep = false;
bool mode_nosva = false, mode_names = false, mode_verific = false;
bool mode_nosva = false, mode_sva_continue = false;
bool mode_names = false, mode_verific = false;
bool mode_autocover = false, mode_fullinit = false;
bool flatten = false, extnets = false, mode_cells = false;
bool split_complex_ports = true;
@ -4071,6 +4083,10 @@ struct VerificPass : public Pass {
mode_nosva = true;
continue;
}
if (args[argidx] == "-sva-continue-on-err") {
mode_sva_continue = true;
continue;
}
if (args[argidx] == "-L" && argidx+1 < GetSize(args)) {
verific_sva_fsm_limit = atoi(args[++argidx].c_str());
continue;
@ -4098,7 +4114,7 @@ struct VerificPass : public Pass {
unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(),
1 /* force_overwrite */);
if (!new_insertion)
log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str());
log_warning_noprefix("-chparam %s already specified: overwriting.\n", key);
continue;
}
if (args[argidx] == "-V") {
@ -4201,7 +4217,7 @@ struct VerificPass : public Pass {
auto it = nl_todo.begin();
Netlist *nl = it->second;
if (nl_done.count(it->first) == 0) {
VerificImporter importer(mode_gates, mode_keep, mode_nosva,
VerificImporter importer(mode_gates, mode_keep, mode_nosva, mode_sva_continue,
mode_names, mode_verific, mode_autocover, mode_fullinit);
nl_done[it->first] = it->second;
importer.import_netlist(design, nl, nl_todo, top_mod_names.count(nl->CellBaseName()));
@ -4232,7 +4248,7 @@ struct VerificPass : public Pass {
}
lines.sort();
for (auto &line : lines)
log("verific -cfg %s\n", line.c_str());
log("verific -cfg %s\n", line);
goto check_error;
}
@ -4291,7 +4307,7 @@ struct VerificPass : public Pass {
}
if (!verific_error_msg.empty())
log_error("%s\n", verific_error_msg.c_str());
log_error("%s\n", verific_error_msg);
}
#else /* YOSYS_ENABLE_VERIFIC */

View file

@ -73,10 +73,12 @@ struct VerificImporter
std::map<Verific::Net*, Verific::Net*> sva_posedge_map;
pool<Verific::Net*> any_all_nets;
bool mode_gates, mode_keep, mode_nosva, mode_names, mode_verific;
bool mode_gates, mode_keep, mode_nosva, mode_sva_continue, mode_names, mode_verific;
bool mode_autocover, mode_fullinit;
VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit);
int num_sva_continue = 0;
VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_sva_continue, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit);
RTLIL::SigBit net_map_at(Verific::Net *net);

View file

@ -124,6 +124,7 @@ struct SvaFsm
{
Module *module;
VerificClocking clocking;
std::function<void (std::string)> parser_error;
SigBit trigger_sig = State::S1, disable_sig;
SigBit throughout_sig = State::S1;
@ -148,6 +149,7 @@ struct SvaFsm
module = clking.module;
clocking = clking;
trigger_sig = trig;
parser_error = [](std::string msg){ log_error("%s", msg); };
startNode = createNode();
acceptNode = createNode();
@ -475,8 +477,8 @@ struct SvaFsm
dump();
log(" ctrl signal: %s\n", log_signal(dnode.ctrl));
}
log_error("SVA DFSM state ctrl signal has %d (>%d) bits. Stopping to prevent exponential design size explosion.\n",
GetSize(dnode.ctrl), verific_sva_fsm_limit);
parser_error(stringf("SVA DFSM state ctrl signal has %d (>%d) bits. Stopping to prevent exponential design size explosion.\n",
GetSize(dnode.ctrl), verific_sva_fsm_limit));
}
for (unsigned long long i = 0; i < (1ull << GetSize(dnode.ctrl)); i++)
@ -1023,20 +1025,20 @@ struct VerificSvaImporter
[[noreturn]] void parser_error(std::string errmsg)
{
if (!importer->mode_keep)
log_error("%s", errmsg.c_str());
log_warning("%s", errmsg.c_str());
if (!importer->mode_keep && !importer->mode_sva_continue)
log_error("%s", errmsg);
log_warning("%s", errmsg);
throw ParserErrorException();
}
[[noreturn]] void parser_error(std::string errmsg, linefile_type loc)
{
parser_error(stringf("%s at %s:%d.\n", errmsg.c_str(), LineFile::GetFileName(loc), LineFile::GetLineNo(loc)));
parser_error(stringf("%s at %s:%d.\n", errmsg, LineFile::GetFileName(loc), LineFile::GetLineNo(loc)));
}
[[noreturn]] void parser_error(std::string errmsg, Instance *inst)
{
parser_error(stringf("%s at %s (%s)", errmsg.c_str(), inst->View()->Owner()->Name(), inst->Name()), inst->Linefile());
parser_error(stringf("%s at %s (%s)", errmsg, inst->View()->Owner()->Name(), inst->Name()), inst->Linefile());
}
[[noreturn]] void parser_error(Instance *inst)
@ -1260,6 +1262,7 @@ struct VerificSvaImporter
if (inst->Type() == PRIM_SVA_FIRST_MATCH)
{
SvaFsm match_fsm(clocking);
match_fsm.parser_error = [&](std::string msg) { this->parser_error(msg); };
match_fsm.createLink(parse_sequence(match_fsm, match_fsm.createStartNode(), inst->GetInput()), match_fsm.acceptNode);
int node = fsm.createNode();
@ -1426,12 +1429,15 @@ struct VerificSvaImporter
if (inst->Type() == PRIM_SVA_SEQ_AND || inst->Type() == PRIM_SVA_AND)
{
SvaFsm fsm1(clocking);
fsm1.parser_error = [&](std::string msg) { this->parser_error(msg); };
fsm1.createLink(parse_sequence(fsm1, fsm1.createStartNode(), inst->GetInput1()), fsm1.acceptNode);
SvaFsm fsm2(clocking);
fsm2.parser_error = [&](std::string msg) { this->parser_error(msg); };
fsm2.createLink(parse_sequence(fsm2, fsm2.createStartNode(), inst->GetInput2()), fsm2.acceptNode);
SvaFsm combined_fsm(clocking);
combined_fsm.parser_error = [&](std::string msg) { this->parser_error(msg); };
fsm1.getDFsm(combined_fsm, combined_fsm.createStartNode(), -1, combined_fsm.acceptNode);
fsm2.getDFsm(combined_fsm, combined_fsm.createStartNode(), -1, combined_fsm.acceptNode);
@ -1456,6 +1462,7 @@ struct VerificSvaImporter
if (inst->Type() == PRIM_SVA_INTERSECT || inst->Type() == PRIM_SVA_WITHIN)
{
SvaFsm intersect_fsm(clocking);
intersect_fsm.parser_error = [&](std::string msg) { this->parser_error(msg); };
if (inst->Type() == PRIM_SVA_INTERSECT)
{
@ -1562,6 +1569,7 @@ struct VerificSvaImporter
int node;
SvaFsm antecedent_fsm(clocking, trig);
antecedent_fsm.parser_error = [&](std::string msg) { this->parser_error(msg); };
node = parse_sequence(antecedent_fsm, antecedent_fsm.createStartNode(), antecedent_net);
if (inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION) {
int next_node = antecedent_fsm.createNode();
@ -1623,6 +1631,7 @@ struct VerificSvaImporter
int node;
SvaFsm antecedent_fsm(clocking, trig);
antecedent_fsm.parser_error = [&](std::string msg) { this->parser_error(msg); };
node = parse_sequence(antecedent_fsm, antecedent_fsm.createStartNode(), antecedent_net);
if (inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION || inst->Type() == PRIM_SVA_NON_OVERLAPPED_FOLLOWED_BY) {
int next_node = antecedent_fsm.createNode();
@ -1677,6 +1686,7 @@ struct VerificSvaImporter
}
SvaFsm consequent_fsm(clocking, antecedent_match);
consequent_fsm.parser_error = [&](std::string msg) { this->parser_error(msg); };
node = parse_sequence(consequent_fsm, consequent_fsm.createStartNode(), consequent_net);
consequent_fsm.createLink(node, consequent_fsm.acceptNode);
@ -1696,6 +1706,7 @@ struct VerificSvaImporter
}
SvaFsm fsm(clocking, trig);
fsm.parser_error = [&](std::string msg) { this->parser_error(msg); };
int node = parse_sequence(fsm, fsm.createStartNode(), net);
fsm.createLink(node, fsm.acceptNode);
@ -1710,30 +1721,34 @@ struct VerificSvaImporter
void import()
{
try
{
module = importer->module;
netlist = root->Owner();
module = importer->module;
netlist = root->Owner();
if (verific_verbose)
log(" importing SVA property at root cell %s (%s) at %s:%d.\n", root->Name(), root->View()->Owner()->Name(),
LineFile::GetFileName(root->Linefile()), LineFile::GetLineNo(root->Linefile()));
int initial_cell_count = GetSize(module->cells_);
int initial_wire_count = GetSize(module->wires_);
int initial_connection_count = GetSize(module->connections_);
bool is_user_declared = root->IsUserDeclared();
if (verific_verbose)
log(" importing SVA property at root cell %s (%s) at %s:%d.\n", root->Name(), root->View()->Owner()->Name(),
LineFile::GetFileName(root->Linefile()), LineFile::GetLineNo(root->Linefile()));
// FIXME
if (!is_user_declared) {
const char *name = root->Name();
for (int i = 0; name[i]; i++) {
if (i ? (name[i] < '0' || name[i] > '9') : (name[i] != 'i')) {
is_user_declared = true;
break;
}
bool is_user_declared = root->IsUserDeclared();
// FIXME
if (!is_user_declared) {
const char *name = root->Name();
for (int i = 0; name[i]; i++) {
if (i ? (name[i] < '0' || name[i] > '9') : (name[i] != 'i')) {
is_user_declared = true;
break;
}
}
}
RTLIL::IdString root_name = module->uniquify(importer->mode_names || is_user_declared ? RTLIL::escape_id(root->Name()) : NEW_ID);
RTLIL::IdString root_name = module->uniquify(importer->mode_names || is_user_declared ? RTLIL::escape_id(root->Name()) : NEW_ID);
try
{
// parse SVA sequence into trigger signal
clocking = VerificClocking(importer, root->GetInput(), true);
@ -1836,6 +1851,36 @@ struct VerificSvaImporter
}
catch (ParserErrorException)
{
if (importer->mode_sva_continue) {
std::vector<Cell *> remove_cells;
pool<Wire *> remove_wires;
for (int i = 0, end = GetSize(module->cells_) - initial_cell_count; i != end; ++i)
remove_cells.push_back(module->cells_.element(i)->second);
for (int i = 0, end = GetSize(module->wires_) - initial_wire_count; i != end; ++i)
remove_wires.emplace(module->wires_.element(i)->second);
for (auto cell : remove_cells)
module->remove(cell);
module->remove(remove_wires);
module->connections_.resize(initial_connection_count);
RTLIL::Cell *c = nullptr;
if (mode_assert) c = module->addAssert(root_name, State::Sx, State::Sx);
if (mode_assume) c = module->addAssume(root_name, State::Sx, State::Sx);
if (mode_cover) c = module->addCover(root_name, State::Sx, State::Sx);
if (c) {
importer->import_attributes(c->attributes, root);
c->set_bool_attribute(ID(unsupported_sva));
}
importer->num_sva_continue++;
}
}
}
};

View file

@ -45,11 +45,11 @@ using namespace AST;
using namespace VERILOG_FRONTEND;
void ConstParser::log_maybe_loc_error(std::string msg) {
log_file_error(*loc.begin.filename, loc.begin.line, "%s", msg.c_str());
log_file_error(*loc.begin.filename, loc.begin.line, "%s", msg);
}
void ConstParser::log_maybe_loc_warn(std::string msg) {
log_file_warning(*loc.begin.filename, loc.begin.line, "%s", msg.c_str());
log_file_warning(*loc.begin.filename, loc.begin.line, "%s", msg);
}
// divide an arbitrary length decimal number by two and return the rest

View file

@ -242,7 +242,7 @@ struct arg_map_t
void add_arg(const std::string &name, const char *default_value)
{
if (find(name)) {
log_error("Duplicate macro arguments with name `%s'.\n", name.c_str());
log_error("Duplicate macro arguments with name `%s'.\n", name);
}
name_to_pos[name] = args.size();
@ -265,7 +265,7 @@ struct arg_map_t
// (something like macro_foobar_arg2). This doesn't include the leading backtick.
static std::string str_token(const std::string &macro_name, int pos)
{
return stringf("macro_%s_arg%d", macro_name.c_str(), pos);
return stringf("macro_%s_arg%d", macro_name, pos);
}
// Return definitions for the macro arguments (so that substituting in the macro body and
@ -741,7 +741,7 @@ read_define(const std::string &filename,
defines_map.add(name, value, (state == 2) ? &args : nullptr);
global_defines_cache.add(name, value, (state == 2) ? &args : nullptr);
} else {
log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name.c_str());
log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name);
}
}
@ -789,14 +789,14 @@ frontend_verilog_preproc(std::istream &f,
else if (ifdef_pass_level > 0)
ifdef_pass_level--;
else
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
log_error("Found %s outside of macro conditional branch!\n", tok);
continue;
}
if (tok == "`else") {
if (ifdef_fail_level == 0) {
if (ifdef_pass_level == 0)
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
log_error("Found %s outside of macro conditional branch!\n", tok);
ifdef_pass_level--;
ifdef_fail_level = 1;
ifdef_already_satisfied = true;
@ -813,7 +813,7 @@ frontend_verilog_preproc(std::istream &f,
std::string name = next_token(true);
if (ifdef_fail_level == 0) {
if (ifdef_pass_level == 0)
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
log_error("Found %s outside of macro conditional branch!\n", tok);
ifdef_pass_level--;
ifdef_fail_level = 1;
ifdef_already_satisfied = true;

View file

@ -32,37 +32,14 @@ USING_YOSYS_NAMESPACE
*/
[[noreturn]]
static void verr_at(std::string filename, int begin_line, char const *fmt, va_list ap)
void VERILOG_FRONTEND::formatted_err_at_loc(Location loc, std::string str)
{
char buffer[1024];
char *p = buffer;
p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
YOSYS_NAMESPACE_PREFIX log_file_error(filename, begin_line, "%s", buffer);
exit(1);
YOSYS_NAMESPACE_PREFIX log_file_error(loc.begin.filename ? *(loc.begin.filename) : "UNKNOWN", loc.begin.line,
"%s\n", std::move(str));
}
static void vwarn_at(std::string filename, int begin_line, char const *fmt, va_list ap)
void VERILOG_FRONTEND::formatted_warn_at_loc(Location loc, std::string str)
{
char buffer[1024];
char *p = buffer;
p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
YOSYS_NAMESPACE_PREFIX log_file_warning(filename, begin_line, "%s", buffer);
YOSYS_NAMESPACE_PREFIX log_file_warning(loc.begin.filename ? *(loc.begin.filename) : "UNKNOWN", loc.begin.line,
"%s\n", std::move(str));
}
[[noreturn]]
void VERILOG_FRONTEND::err_at_loc(Location loc, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
verr_at(loc.begin.filename ? *(loc.begin.filename) : "UNKNOWN", loc.begin.line, fmt, args);
}
void VERILOG_FRONTEND::warn_at_loc(Location loc, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
vwarn_at(loc.begin.filename ? *(loc.begin.filename) : "UNKNOWN", loc.begin.line, fmt, args);
va_end(args);
}

View file

@ -10,8 +10,20 @@ YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND
{
[[noreturn]]
void err_at_loc(Location loc, char const *fmt, ...);
void warn_at_loc(Location loc, char const *fmt, ...);
void formatted_err_at_loc(Location loc, std::string str);
template <typename... Args>
[[noreturn]]
void err_at_loc(Location loc, FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
formatted_err_at_loc(std::move(loc), fmt.format(args...));
}
void formatted_warn_at_loc(Location loc, std::string str);
template <typename... Args>
void warn_at_loc(Location loc, FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
formatted_warn_at_loc(std::move(loc), fmt.format(args...));
}
};
YOSYS_NAMESPACE_END

View file

@ -51,7 +51,7 @@ static std::list<std::vector<std::string>> verilog_defaults_stack;
static void error_on_dpi_function(AST::AstNode *node)
{
if (node->type == AST::AST_DPI_FUNCTION)
err_at_loc(node->location, "Found DPI function %s.\n", node->str.c_str());
err_at_loc(node->location, "Found DPI function %s.\n", node->str);
for (auto& child : node->children)
error_on_dpi_function(child.get());
}
@ -229,6 +229,10 @@ struct VerilogFrontend : public Frontend {
log(" add 'dir' to the directories which are used when searching include\n");
log(" files\n");
log("\n");
log(" -relativeshare\n");
log(" use paths relative to share directory for source locations\n");
log(" where possible (experimental).\n");
log("\n");
log("The command 'verilog_defaults' can be used to register default options for\n");
log("subsequent calls to 'read_verilog'.\n");
log("\n");
@ -273,6 +277,7 @@ struct VerilogFrontend : public Frontend {
bool flag_nowb = false;
bool flag_nosynthesis = false;
bool flag_yydebug = false;
bool flag_relative_share = false;
define_map_t defines_map;
std::list<std::string> include_dirs;
@ -450,6 +455,11 @@ struct VerilogFrontend : public Frontend {
attributes.push_back(RTLIL::escape_id(args[++argidx]));
continue;
}
if (arg == "-relativeshare") {
flag_relative_share = true;
log_experimental("read_verilog -relativeshare");
continue;
}
if (arg == "-D" && argidx+1 < args.size()) {
std::string name = args[++argidx], value;
size_t equal = name.find('=');
@ -485,11 +495,18 @@ struct VerilogFrontend : public Frontend {
extra_args(f, filename, args, argidx);
log_header(design, "Executing Verilog-2005 frontend: %s\n", filename.c_str());
log_header(design, "Executing Verilog-2005 frontend: %s\n", filename);
log("Parsing %s%s input from `%s' to AST representation.\n",
parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str());
log("verilog frontend filename %s\n", filename.c_str());
if (flag_relative_share) {
auto share_path = proc_share_dirname();
if (filename.substr(0, share_path.length()) == share_path)
filename = std::string("+/") + filename.substr(share_path.length());
log("new filename %s\n", filename.c_str());
}
AST::sv_mode_but_global_and_used_for_literally_one_condition = parse_mode.sv;
std::string code_after_preproc;
@ -497,7 +514,7 @@ struct VerilogFrontend : public Frontend {
if (!flag_nopp) {
code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, *design->verilog_defines, include_dirs, parse_state, parse_mode);
if (flag_ppdump)
log("-- Verilog code after preprocessor --\n%s-- END OF DUMP --\n", code_after_preproc.c_str());
log("-- Verilog code after preprocessor --\n%s-- END OF DUMP --\n", code_after_preproc);
parse_state.lexin = new std::istringstream(code_after_preproc);
}

View file

@ -162,7 +162,7 @@ static bool is_hex_dig(char c, int *val, parser::location_type loc)
*val = c - 'A' + 0xA;
return true;
} else if (c == 'x' || c == 'X' || c == 'z' || c == 'Z' || c == '?') {
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "'%c' not a valid digit in hex escape sequence.\n", c);
log_file_warning(*loc.begin.filename, loc.begin.line, "'%c' not a valid digit in hex escape sequence.\n", c);
*val = 0; // not semantically valid in hex escape...
return true; // ...but still processed as part of hex token
}
@ -176,7 +176,7 @@ static bool is_oct_dig(char c, int *val, parser::location_type loc)
*val = c - '0';
return true;
} else if (c == 'x' || c == 'X' || c == 'z' || c == 'Z' || c == '?') {
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "'%c' not a valid digit in octal escape sequence.\n", c);
log_file_warning(*loc.begin.filename, loc.begin.line, "'%c' not a valid digit in octal escape sequence.\n", c);
*val = 0; // not semantically valid in octal escape...
return true; // ...but still processed as part of octal token
}
@ -196,7 +196,7 @@ static parser::symbol_type process_str(char *str, int len, bool triple, parser::
if (in + 1 < str + len && (in[1] ^ *in) == ('\n' ^ '\r'))
in++;
if (!triple)
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "Multi-line string literals should be triple-quoted or escaped.\n");
log_file_warning(*loc.begin.filename, loc.begin.line, "Multi-line string literals should be triple-quoted or escaped.\n");
*out++ = '\n';
break;
case '\\':
@ -233,7 +233,7 @@ static parser::symbol_type process_str(char *str, int len, bool triple, parser::
}
out++;
} else
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "ignoring invalid hex escape.\n");
log_file_warning(*loc.begin.filename, loc.begin.line, "ignoring invalid hex escape.\n");
break;
case '\\':
*out++ = '\\';
@ -256,7 +256,7 @@ static parser::symbol_type process_str(char *str, int len, bool triple, parser::
in++;
if (in + 1 < str + len && is_oct_dig(in[1], &val, loc)) {
if (*out >= 040)
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "octal escape exceeds \\377\n");
log_file_warning(*loc.begin.filename, loc.begin.line, "octal escape exceeds \\377\n");
*out = *out * 010 + val;
in++;
}
@ -377,6 +377,7 @@ TIME_SCALE_SUFFIX [munpf]?s
"begin" { return parser::make_TOK_BEGIN(out_loc); }
"end" { return parser::make_TOK_END(out_loc); }
"if" { return parser::make_TOK_IF(out_loc); }
"ifnone" { return parser::make_TOK_IFNONE(out_loc); }
"else" { return parser::make_TOK_ELSE(out_loc); }
"for" { return parser::make_TOK_FOR(out_loc); }
"posedge" { return parser::make_TOK_POSEDGE(out_loc); }
@ -492,7 +493,7 @@ TIME_SCALE_SUFFIX [munpf]?s
\"{3}(\"{0,2}([^\\"]|\\.|\\\n))*\"{3} { return process_str(yytext + 3, yyleng - 6, true, out_loc); }
and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1|tran {
auto val = std::make_unique<std::string>(YYText());
return parser::make_TOK_PRIMITIVE(std::move(val), out_loc);
}

File diff suppressed because it is too large Load diff

View file

@ -100,7 +100,7 @@ struct BitPatternPool
bits_t sig2bits(RTLIL::SigSpec sig)
{
bits_t bits;
bits.bitdata = sig.as_const().bits();
bits.bitdata = sig.as_const().to_bits();
for (auto &b : bits.bitdata)
if (b > RTLIL::State::S1)
b = RTLIL::State::Sa;

View file

@ -33,10 +33,7 @@ static void extend_u0(RTLIL::Const &arg, int width, bool is_signed)
if (arg.size() > 0 && is_signed)
padding = arg.back();
while (GetSize(arg) < width)
arg.bits().push_back(padding);
arg.bits().resize(width);
arg.resize(width, padding);
}
static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_bit_pos)
@ -79,12 +76,12 @@ static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_b
{
mag--;
for (auto i = 0; i < result_len; i++)
result.bits()[i] = mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1;
result.set(i, mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1);
}
else
{
for (auto i = 0; i < result_len; i++)
result.bits()[i] = mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0;
result.set(i, mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0);
}
}
@ -140,11 +137,11 @@ RTLIL::Const RTLIL::const_not(const RTLIL::Const &arg1, const RTLIL::Const&, boo
RTLIL::Const result(RTLIL::State::Sx, result_len);
for (auto i = 0; i < result_len; i++) {
if (i >= GetSize(arg1_ext))
result.bits()[i] = RTLIL::State::S0;
else if (arg1_ext.bits()[i] == RTLIL::State::S0)
result.bits()[i] = RTLIL::State::S1;
else if (arg1_ext.bits()[i] == RTLIL::State::S1)
result.bits()[i] = RTLIL::State::S0;
result.set(i, RTLIL::State::S0);
else if (arg1_ext[i] == RTLIL::State::S0)
result.set(i, RTLIL::State::S1);
else if (arg1_ext[i] == RTLIL::State::S1)
result.set(i, RTLIL::State::S0);
}
return result;
@ -161,9 +158,9 @@ static RTLIL::Const logic_wrapper(RTLIL::State(*logic_func)(RTLIL::State, RTLIL:
RTLIL::Const result(RTLIL::State::Sx, result_len);
for (auto i = 0; i < result_len; i++) {
RTLIL::State a = i < GetSize(arg1) ? arg1.bits()[i] : RTLIL::State::S0;
RTLIL::State b = i < GetSize(arg2) ? arg2.bits()[i] : RTLIL::State::S0;
result.bits()[i] = logic_func(a, b);
RTLIL::State a = i < GetSize(arg1) ? arg1[i] : RTLIL::State::S0;
RTLIL::State b = i < GetSize(arg2) ? arg2[i] : RTLIL::State::S0;
result.set(i, logic_func(a, b));
}
return result;
@ -197,8 +194,8 @@ static RTLIL::Const logic_reduce_wrapper(RTLIL::State initial, RTLIL::State(*log
temp = logic_func(temp, arg1[i]);
RTLIL::Const result(temp);
while (GetSize(result) < result_len)
result.bits().push_back(RTLIL::State::S0);
if (GetSize(result) < result_len)
result.resize(result_len, RTLIL::State::S0);
return result;
}
@ -222,9 +219,9 @@ RTLIL::Const RTLIL::const_reduce_xnor(const RTLIL::Const &arg1, const RTLIL::Con
RTLIL::Const buffer = logic_reduce_wrapper(RTLIL::State::S0, logic_xor, arg1, result_len);
if (!buffer.empty()) {
if (buffer.front() == RTLIL::State::S0)
buffer.bits().front() = RTLIL::State::S1;
buffer.set(0, RTLIL::State::S1);
else if (buffer.front() == RTLIL::State::S1)
buffer.bits().front() = RTLIL::State::S0;
buffer.set(0, RTLIL::State::S0);
}
return buffer;
}
@ -239,9 +236,8 @@ RTLIL::Const RTLIL::const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const
int undef_bit_pos_a = -1;
BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
RTLIL::Const result(a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S1 : RTLIL::State::S0);
while (GetSize(result) < result_len)
result.bits().push_back(RTLIL::State::S0);
if (GetSize(result) < result_len)
result.resize(result_len, RTLIL::State::S0);
return result;
}
@ -254,9 +250,8 @@ RTLIL::Const RTLIL::const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const
RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
RTLIL::Const result(logic_and(bit_a, bit_b));
while (GetSize(result) < result_len)
result.bits().push_back(RTLIL::State::S0);
if (GetSize(result) < result_len)
result.resize(result_len, RTLIL::State::S0);
return result;
}
@ -269,9 +264,8 @@ RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const
RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
RTLIL::Const result(logic_or(bit_a, bit_b));
while (GetSize(result) < result_len)
result.bits().push_back(RTLIL::State::S0);
if (GetSize(result) < result_len)
result.resize(result_len, RTLIL::State::S0);
return result;
}
@ -295,11 +289,11 @@ static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Co
for (int i = 0; i < result_len; i++) {
BigInteger pos = BigInteger(i) + offset;
if (pos < 0)
result.bits()[i] = vacant_bits;
result.set(i, vacant_bits);
else if (pos >= BigInteger(GetSize(arg1)))
result.bits()[i] = sign_ext ? arg1.back() : vacant_bits;
result.set(i, sign_ext ? arg1.back() : vacant_bits);
else
result.bits()[i] = arg1[pos.toInt()];
result.set(i, arg1[pos.toInt()]);
}
return result;
@ -346,9 +340,8 @@ RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) < const2big(arg2, signed2, undef_bit_pos);
RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
while (GetSize(result) < result_len)
result.bits().push_back(RTLIL::State::S0);
if (GetSize(result) < result_len)
result.resize(result_len, RTLIL::State::S0);
return result;
}
@ -357,9 +350,8 @@ RTLIL::Const RTLIL::const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) <= const2big(arg2, signed2, undef_bit_pos);
RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
while (GetSize(result) < result_len)
result.bits().push_back(RTLIL::State::S0);
if (GetSize(result) < result_len)
result.resize(result_len, RTLIL::State::S0);
return result;
}
@ -383,7 +375,7 @@ RTLIL::Const RTLIL::const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
matched_status = RTLIL::State::Sx;
}
result.bits().front() = matched_status;
result.set(0, matched_status);
return result;
}
@ -391,9 +383,9 @@ RTLIL::Const RTLIL::const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
{
RTLIL::Const result = RTLIL::const_eq(arg1, arg2, signed1, signed2, result_len);
if (result.front() == RTLIL::State::S0)
result.bits().front() = RTLIL::State::S1;
result.set(0, RTLIL::State::S1);
else if (result.front() == RTLIL::State::S1)
result.bits().front() = RTLIL::State::S0;
result.set(0, RTLIL::State::S0);
return result;
}
@ -412,7 +404,7 @@ RTLIL::Const RTLIL::const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2
return result;
}
result.bits().front() = RTLIL::State::S1;
result.set(0, RTLIL::State::S1);
return result;
}
@ -420,9 +412,9 @@ RTLIL::Const RTLIL::const_nex(const RTLIL::Const &arg1, const RTLIL::Const &arg2
{
RTLIL::Const result = RTLIL::const_eqx(arg1, arg2, signed1, signed2, result_len);
if (result.front() == RTLIL::State::S0)
result.bits().front() = RTLIL::State::S1;
result.set(0, RTLIL::State::S1);
else if (result.front() == RTLIL::State::S1)
result.bits().front() = RTLIL::State::S0;
result.set(0, RTLIL::State::S0);
return result;
}
@ -431,9 +423,8 @@ RTLIL::Const RTLIL::const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) >= const2big(arg2, signed2, undef_bit_pos);
RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
while (GetSize(result) < result_len)
result.bits().push_back(RTLIL::State::S0);
if (GetSize(result) < result_len)
result.resize(result_len, RTLIL::State::S0);
return result;
}
@ -442,9 +433,8 @@ RTLIL::Const RTLIL::const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) > const2big(arg2, signed2, undef_bit_pos);
RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
while (GetSize(result) < result_len)
result.bits().push_back(RTLIL::State::S0);
if (GetSize(result) < result_len)
result.resize(result_len, RTLIL::State::S0);
return result;
}
@ -628,7 +618,7 @@ RTLIL::Const RTLIL::const_mux(const RTLIL::Const &arg1, const RTLIL::Const &arg2
RTLIL::Const ret = arg1;
for (auto i = 0; i < ret.size(); i++)
if (ret[i] != arg2[i])
ret.bits()[i] = State::Sx;
ret.set(i, State::Sx);
return ret;
}
@ -703,7 +693,7 @@ RTLIL::Const RTLIL::const_bweqx(const RTLIL::Const &arg1, const RTLIL::Const &ar
log_assert(arg2.size() == arg1.size());
RTLIL::Const result(RTLIL::State::S0, arg1.size());
for (auto i = 0; i < arg1.size(); i++)
result.bits()[i] = arg1[i] == arg2[i] ? State::S1 : State::S0;
result.set(i, arg1[i] == arg2[i] ? State::S1 : State::S0);
return result;
}
@ -715,7 +705,7 @@ RTLIL::Const RTLIL::const_bwmux(const RTLIL::Const &arg1, const RTLIL::Const &ar
RTLIL::Const result(RTLIL::State::Sx, arg1.size());
for (auto i = 0; i < arg1.size(); i++) {
if (arg3[i] != State::Sx || arg1[i] == arg2[i])
result.bits()[i] = arg3[i] == State::S1 ? arg2[i] : arg1[i];
result.set(i, arg3[i] == State::S1 ? arg2[i] : arg1[i]);
}
return result;

View file

@ -447,7 +447,7 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL
return true;
}
if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
if (cell->is_builtin_ff()) {
ff_op(this, cell);
return true;
}

View file

@ -111,6 +111,8 @@ struct CellTypes
setup_type(ID($original_tag), {ID::A}, {ID::Y});
setup_type(ID($future_ff), {ID::A}, {ID::Y});
setup_type(ID($scopeinfo), {}, {});
setup_type(ID($input_port), {}, {ID::Y});
setup_type(ID($connect), {ID::A, ID::B}, {});
}
void setup_internals_eval()
@ -303,24 +305,34 @@ struct CellTypes
cell_types.clear();
}
bool cell_known(RTLIL::IdString type) const
bool cell_known(const RTLIL::IdString &type) const
{
return cell_types.count(type) != 0;
}
bool cell_output(RTLIL::IdString type, RTLIL::IdString port) const
bool cell_output(const RTLIL::IdString &type, const RTLIL::IdString &port) const
{
auto it = cell_types.find(type);
return it != cell_types.end() && it->second.outputs.count(port) != 0;
}
bool cell_input(RTLIL::IdString type, RTLIL::IdString port) const
bool cell_input(const RTLIL::IdString &type, const RTLIL::IdString &port) const
{
auto it = cell_types.find(type);
return it != cell_types.end() && it->second.inputs.count(port) != 0;
}
bool cell_evaluable(RTLIL::IdString type) const
RTLIL::PortDir cell_port_dir(RTLIL::IdString type, RTLIL::IdString port) const
{
auto it = cell_types.find(type);
if (it == cell_types.end())
return RTLIL::PD_UNKNOWN;
bool is_input = it->second.inputs.count(port);
bool is_output = it->second.outputs.count(port);
return RTLIL::PortDir(is_input + is_output * 2);
}
bool cell_evaluable(const RTLIL::IdString &type) const
{
auto it = cell_types.find(type);
return it != cell_types.end() && it->second.is_evaluable;
@ -328,7 +340,7 @@ struct CellTypes
static RTLIL::Const eval_not(RTLIL::Const v)
{
for (auto &bit : v.bits())
for (auto bit : v)
if (bit == State::S0) bit = State::S1;
else if (bit == State::S1) bit = State::S0;
return v;
@ -421,16 +433,14 @@ struct CellTypes
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr)
{
if (cell->type == ID($slice)) {
RTLIL::Const ret;
int width = cell->parameters.at(ID::Y_WIDTH).as_int();
int offset = cell->parameters.at(ID::OFFSET).as_int();
ret.bits().insert(ret.bits().end(), arg1.begin()+offset, arg1.begin()+offset+width);
return ret;
return arg1.extract(offset, width);
}
if (cell->type == ID($concat)) {
RTLIL::Const ret = arg1;
ret.bits().insert(ret.bits().end(), arg2.begin(), arg2.end());
ret.append(arg2);
return ret;
}

View file

@ -115,7 +115,7 @@ struct ConstEval
for (int i = 0; i < GetSize(coval); i++) {
carry = (sig_g[i] == State::S1) || (sig_p[i] == RTLIL::S1 && carry);
coval.bits()[i] = carry ? State::S1 : State::S0;
coval.set(i, carry ? State::S1 : State::S0);
}
set(sig_co, coval);
@ -249,7 +249,7 @@ struct ConstEval
for (int i = 0; i < GetSize(val_y); i++)
if (val_y[i] == RTLIL::Sx)
val_x.bits()[i] = RTLIL::Sx;
val_x.set(i, RTLIL::Sx);
set(sig_y, val_y);
set(sig_x, val_x);

File diff suppressed because it is too large Load diff

View file

@ -143,14 +143,14 @@ unsigned int CellCosts::get(RTLIL::Cell *cell)
return 1;
if (design_ && design_->module(cell->type) && cell->parameters.empty()) {
log_debug("%s is a module, recurse\n", cell->name.c_str());
log_debug("%s is a module, recurse\n", cell->name);
return get(design_->module(cell->type));
} else if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
} else if (cell->is_builtin_ff()) {
log_assert(cell->hasPort(ID::Q) && "Weird flip flop");
log_debug("%s is ff\n", cell->name.c_str());
log_debug("%s is ff\n", cell->name);
return cell->getParam(ID::WIDTH).as_int();
} else if (cell->type.in(ID($mem), ID($mem_v2))) {
log_debug("%s is mem\n", cell->name.c_str());
log_debug("%s is mem\n", cell->name);
return cell->getParam(ID::WIDTH).as_int() * cell->getParam(ID::SIZE).as_int();
} else if (y_coef(cell->type)) {
// linear with Y_WIDTH or WIDTH
@ -159,23 +159,23 @@ unsigned int CellCosts::get(RTLIL::Cell *cell)
int width = cell->getParam(param).as_int();
if (cell->type == ID($demux))
width <<= cell->getParam(ID::S_WIDTH).as_int();
log_debug("%s Y*coef %d * %d\n", cell->name.c_str(), width, y_coef(cell->type));
log_debug("%s Y*coef %d * %d\n", cell->name, width, y_coef(cell->type));
return width * y_coef(cell->type);
} else if (sum_coef(cell->type)) {
// linear with sum of port widths
unsigned int sum = port_width_sum(cell);
log_debug("%s sum*coef %d * %d\n", cell->name.c_str(), sum, sum_coef(cell->type));
log_debug("%s sum*coef %d * %d\n", cell->name, sum, sum_coef(cell->type));
return sum * sum_coef(cell->type);
} else if (max_inp_coef(cell->type)) {
// linear with largest input width
unsigned int max = max_inp_width(cell);
log_debug("%s max*coef %d * %d\n", cell->name.c_str(), max, max_inp_coef(cell->type));
log_debug("%s max*coef %d * %d\n", cell->name, max, max_inp_coef(cell->type));
return max * max_inp_coef(cell->type);
} else if (is_div_mod(cell->type) || cell->type == ID($mul)) {
// quadratic with sum of port widths
unsigned int sum = port_width_sum(cell);
unsigned int coef = cell->type == ID($mul) ? 3 : 5;
log_debug("%s coef*(sum**2) %d * %d\n", cell->name.c_str(), coef, sum * sum);
log_debug("%s coef*(sum**2) %d * %d\n", cell->name, coef, sum * sum);
return coef * sum * sum;
} else if (cell->type.in(ID($macc), ID($macc_v2))) {
// quadratic per term
@ -196,15 +196,15 @@ unsigned int CellCosts::get(RTLIL::Cell *cell)
} else if (cell->type == ID($lut)) {
int width = cell->getParam(ID::WIDTH).as_int();
unsigned int cost = 1U << (unsigned int)width;
log_debug("%s is 2**%d\n", cell->name.c_str(), width);
log_debug("%s is 2**%d\n", cell->name, width);
return cost;
} else if (cell->type == ID($sop)) {
int width = cell->getParam(ID::WIDTH).as_int();
int depth = cell->getParam(ID::DEPTH).as_int();
log_debug("%s is (2*%d + 1)*%d\n", cell->name.c_str(), width, depth);
log_debug("%s is (2*%d + 1)*%d\n", cell->name, width, depth);
return (2 * width + 1) * depth;
} else if (is_free(cell->type)) {
log_debug("%s is free\n", cell->name.c_str());
log_debug("%s is free\n", cell->name);
return 0;
}
// TODO: $fsm

View file

@ -585,7 +585,7 @@ int main(int argc, char **argv)
FILE *scriptfp = fopen(scriptfile.c_str(), "r");
if (scriptfp == nullptr) {
log_error("Failed to open file '%s' for reading.\n", scriptfile.c_str());
log_error("Failed to open file '%s' for reading.\n", scriptfile);
}
if (PyRun_SimpleFile(scriptfp, scriptfile.c_str()) != 0) {
log_flush();
@ -664,7 +664,7 @@ int main(int argc, char **argv)
log("Warnings: %d experimental features used (not excluded with -x).\n", GetSize(log_experimentals));
#ifdef _WIN32
log("End of script. Logfile hash: %s\n", hash.c_str());
log("End of script. Logfile hash: %s\n", hash);
#else
std::string meminfo;
std::string stats_divider = ", ";
@ -690,7 +690,7 @@ int main(int argc, char **argv)
meminfo = stringf(", MEM: %.2f MB peak",
ru_buffer.ru_maxrss / (1024.0 * 1024.0));
#endif
log("End of script. Logfile hash: %s%sCPU: user %.2fs system %.2fs%s\n", hash.c_str(),
log("End of script. Logfile hash: %s%sCPU: user %.2fs system %.2fs%s\n", hash,
stats_divider.c_str(), ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec,
ru_buffer.ru_stime.tv_sec + 1e-6 * ru_buffer.ru_stime.tv_usec, meminfo.c_str());
#endif
@ -768,9 +768,9 @@ int main(int argc, char **argv)
f = fopen(filename.c_str(), "a+");
if (f == NULL)
log_error("Can't create coverage file `%s'.\n", filename.c_str());
log_error("Can't create coverage file `%s'.\n", filename);
log("<writing coverage file \"%s\">\n", filename.c_str());
log("<writing coverage file \"%s\">\n", filename);
for (auto &it : get_coverage_data())
fprintf(f, "%-60s %10d %s\n", it.second.first.c_str(), it.second.second, it.first.c_str());

View file

@ -260,7 +260,7 @@ bool DriveChunkMultiple::try_append(DriveBitMultiple const &bit)
switch (single.type())
{
case DriveType::CONSTANT: {
single.constant().bits().push_back(constant);
single.constant().append(RTLIL::Const(constant));
} break;
case DriveType::WIRE: {
single.wire().width += 1;
@ -295,8 +295,7 @@ bool DriveChunkMultiple::try_append(DriveChunkMultiple const &chunk)
switch (single.type())
{
case DriveType::CONSTANT: {
auto &bits = single.constant().bits();
bits.insert(bits.end(), constant.bits().begin(), constant.bits().end());
single.constant().append(constant);
} break;
case DriveType::WIRE: {
single.wire().width += width;
@ -349,7 +348,7 @@ bool DriveChunk::try_append(DriveBit const &bit)
none_ += 1;
return true;
case DriveType::CONSTANT:
constant_.bits().push_back(bit.constant());
constant_.append(RTLIL::Const(bit.constant()));
return true;
case DriveType::WIRE:
return wire_.try_append(bit.wire());
@ -375,7 +374,7 @@ bool DriveChunk::try_append(DriveChunk const &chunk)
none_ += chunk.none_;
return true;
case DriveType::CONSTANT:
constant_.bits().insert(constant_.bits().end(), chunk.constant_.begin(), chunk.constant_.end());
constant_.append(chunk.constant_);
return true;
case DriveType::WIRE:
return wire_.try_append(chunk.wire());
@ -865,41 +864,41 @@ DriveSpec DriverMap::operator()(DriveSpec spec)
return result;
}
const char *log_signal(DriveChunkWire const &chunk)
std::string log_signal(DriveChunkWire const &chunk)
{
const char *id = log_id(chunk.wire->name);
if (chunk.is_whole())
return id;
if (chunk.width == 1)
return log_str(stringf("%s [%d]", id, chunk.offset));
return log_str(stringf("%s [%d:%d]", id, chunk.offset + chunk.width - 1, chunk.offset));
return stringf("%s [%d]", id, chunk.offset);
return stringf("%s [%d:%d]", id, chunk.offset + chunk.width - 1, chunk.offset);
}
const char *log_signal(DriveChunkPort 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);
if (chunk.is_whole())
return log_str(stringf("%s <%s>", cell_id, port_id));
return stringf("%s <%s>", cell_id, port_id);
if (chunk.width == 1)
return log_str(stringf("%s <%s> [%d]", cell_id, port_id, chunk.offset));
return log_str(stringf("%s <%s> [%d:%d]", cell_id, port_id, chunk.offset + chunk.width - 1, chunk.offset));
return stringf("%s <%s> [%d]", cell_id, port_id, chunk.offset);
return stringf("%s <%s> [%d:%d]", cell_id, port_id, chunk.offset + chunk.width - 1, chunk.offset);
}
const char *log_signal(DriveChunkMarker const &chunk)
std::string log_signal(DriveChunkMarker const &chunk)
{
if (chunk.width == 1)
return log_str(stringf("<marker %d> [%d]", chunk.marker, chunk.offset));
return log_str(stringf("<marker %d> [%d:%d]", chunk.marker, chunk.offset + chunk.width - 1, chunk.offset));
return stringf("<marker %d> [%d]", chunk.marker, chunk.offset);
return stringf("<marker %d> [%d:%d]", chunk.marker, chunk.offset + chunk.width - 1, chunk.offset);
}
const char *log_signal(DriveChunk const &chunk)
std::string log_signal(DriveChunk const &chunk)
{
switch (chunk.type())
{
case DriveType::NONE:
return log_str(stringf("<none x%d>", chunk.size()));
return stringf("<none x%d>", chunk.size());
case DriveType::CONSTANT:
return log_const(chunk.constant());
case DriveType::WIRE:
@ -917,14 +916,14 @@ const char *log_signal(DriveChunk const &chunk)
str += log_signal(single);
}
str += ">";
return log_str(str);
return str;
}
default:
log_abort();
}
}
const char *log_signal(DriveSpec const &spec)
std::string log_signal(DriveSpec const &spec)
{
auto &chunks = spec.chunks();
if (chunks.empty())
@ -943,7 +942,7 @@ const char *log_signal(DriveSpec const &spec)
}
str += " }";
return log_str(str);
return str;
}
YOSYS_NAMESPACE_END

View file

@ -20,6 +20,7 @@
#ifndef DRIVERTOOLS_H
#define DRIVERTOOLS_H
#include <string>
#include <type_traits>
#include "kernel/rtlil.h"
@ -39,11 +40,11 @@ struct DriveChunk;
struct DriveSpec;
const char *log_signal(DriveChunkWire const &chunk);
const char *log_signal(DriveChunkPort const &chunk);
const char *log_signal(DriveChunkMarker const &chunk);
const char *log_signal(DriveChunk const &chunk);
const char *log_signal(DriveSpec const &chunk);
std::string log_signal(DriveChunkWire const &chunk);
std::string log_signal(DriveChunkPort const &chunk);
std::string log_signal(DriveChunkMarker const &chunk);
std::string log_signal(DriveChunk const &chunk);
std::string log_signal(DriveSpec const &chunk);
enum class DriveType : unsigned char
{

View file

@ -287,6 +287,16 @@ FfData FfData::slice(const std::vector<int> &bits) {
res.pol_clr = pol_clr;
res.pol_set = pol_set;
res.attributes = attributes;
std::optional<Const::Builder> arst_bits;
if (has_arst)
arst_bits.emplace(bits.size());
std::optional<Const::Builder> srst_bits;
if (has_srst)
srst_bits.emplace(bits.size());
std::optional<Const::Builder> init_bits;
if (initvals)
init_bits.emplace(bits.size());
for (int i : bits) {
res.sig_q.append(sig_q[i]);
if (has_clk || has_gclk)
@ -298,12 +308,19 @@ FfData FfData::slice(const std::vector<int> &bits) {
res.sig_set.append(sig_set[i]);
}
if (has_arst)
res.val_arst.bits().push_back(val_arst[i]);
arst_bits->push_back(val_arst[i]);
if (has_srst)
res.val_srst.bits().push_back(val_srst[i]);
srst_bits->push_back(val_srst[i]);
if (initvals)
res.val_init.bits().push_back(val_init[i]);
init_bits->push_back(val_init[i]);
}
if (has_arst)
res.val_arst = arst_bits->build();
if (has_srst)
res.val_srst = srst_bits->build();
if (initvals)
res.val_init = init_bits->build();
res.width = GetSize(res.sig_q);
return res;
}
@ -688,10 +705,10 @@ void FfData::flip_rst_bits(const pool<int> &bits) {
for (auto bit: bits) {
if (has_arst)
val_arst.bits()[bit] = invert(val_arst[bit]);
val_arst.set(bit, invert(val_arst[bit]));
if (has_srst)
val_srst.bits()[bit] = invert(val_srst[bit]);
val_init.bits()[bit] = invert(val_init[bit]);
val_srst.set(bit, invert(val_srst[bit]));
val_init.set(bit, invert(val_init[bit]));
}
}
@ -760,7 +777,7 @@ void FfData::flip_bits(const pool<int> &bits) {
Const mask = Const(State::S0, width);
for (auto bit: bits)
mask.bits()[bit] = State::S1;
mask.set(bit, State::S1);
if (has_clk || has_gclk)
sig_d = module->Xor(NEW_ID, sig_d, mask);

View file

@ -74,10 +74,10 @@ struct FfInitVals
RTLIL::Const operator()(const RTLIL::SigSpec &sig) const
{
RTLIL::Const res;
RTLIL::Const::Builder res_bits(GetSize(sig));
for (auto bit : sig)
res.bits().push_back((*this)(bit));
return res;
res_bits.push_back((*this)(bit));
return res_bits.build();
}
void set_init(RTLIL::SigBit bit, RTLIL::State val)
@ -93,12 +93,12 @@ struct FfInitVals
initbits[mbit] = std::make_pair(val,abit);
auto it2 = abit.wire->attributes.find(ID::init);
if (it2 != abit.wire->attributes.end()) {
it2->second.bits()[abit.offset] = val;
it2->second.set(abit.offset, val);
if (it2->second.is_fully_undef())
abit.wire->attributes.erase(it2);
} else if (val != State::Sx) {
Const cval(State::Sx, GetSize(abit.wire));
cval.bits()[abit.offset] = val;
cval.set(abit.offset, val);
abit.wire->attributes[ID::init] = cval;
}
}

View file

@ -42,9 +42,9 @@ bool FfMergeHelper::find_output_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pai
ff.sig_d.append(bit);
ff.sig_clr.append(State::Sx);
ff.sig_set.append(State::Sx);
ff.val_init.bits().push_back(State::Sx);
ff.val_srst.bits().push_back(State::Sx);
ff.val_arst.bits().push_back(State::Sx);
ff.val_init.append(RTLIL::Const(State::Sx));
ff.val_srst.append(RTLIL::Const(State::Sx));
ff.val_arst.append(RTLIL::Const(State::Sx));
continue;
}
@ -147,9 +147,9 @@ bool FfMergeHelper::find_output_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pai
ff.sig_q.append(cur_ff.sig_q[idx]);
ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0);
ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0);
ff.val_arst.bits().push_back(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx);
ff.val_srst.bits().push_back(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx);
ff.val_init.bits().push_back(cur_ff.val_init[idx]);
ff.val_arst.append(RTLIL::Const(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx));
ff.val_srst.append(RTLIL::Const(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx));
ff.val_init.append(RTLIL::Const(cur_ff.val_init[idx]));
found = true;
}
@ -174,9 +174,9 @@ bool FfMergeHelper::find_input_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair
// These two will be fixed up later.
ff.sig_clr.append(State::Sx);
ff.sig_set.append(State::Sx);
ff.val_init.bits().push_back(bit.data);
ff.val_srst.bits().push_back(bit.data);
ff.val_arst.bits().push_back(bit.data);
ff.val_init.append(RTLIL::Const(bit.data));
ff.val_srst.append(RTLIL::Const(bit.data));
ff.val_arst.append(RTLIL::Const(bit.data));
continue;
}
@ -274,9 +274,9 @@ bool FfMergeHelper::find_input_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair
ff.sig_q.append(cur_ff.sig_q[idx]);
ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0);
ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0);
ff.val_arst.bits().push_back(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx);
ff.val_srst.bits().push_back(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx);
ff.val_init.bits().push_back(cur_ff.val_init[idx]);
ff.val_arst.append(RTLIL::Const(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx));
ff.val_srst.append(RTLIL::Const(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx));
ff.val_init.append(RTLIL::Const(cur_ff.val_init[idx]));
found = true;
}
@ -335,7 +335,7 @@ void FfMergeHelper::set(FfInitVals *initvals_, RTLIL::Module *module_)
}
for (auto cell : module->cells()) {
if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
if (cell->is_builtin_ff()) {
if (cell->hasPort(ID::D)) {
SigSpec d = (*sigmap)(cell->getPort(ID::D));
for (int i = 0; i < GetSize(d); i++)

View file

@ -401,11 +401,11 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik
part = {};
}
if (++i == fmt.size()) {
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1);
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name, fmtarg - args.begin() + 1);
}
if (++arg == args.end()) {
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with fewer arguments than the format specifiers in argument %zu require.\n", task_name.c_str(), fmtarg - args.begin() + 1);
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with fewer arguments than the format specifiers in argument %zu require.\n", task_name, fmtarg - args.begin() + 1);
}
part.sig = arg->sig;
part.signed_ = arg->signed_;
@ -420,7 +420,7 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik
} else break;
}
if (i == fmt.size()) {
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1);
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name, fmtarg - args.begin() + 1);
}
bool has_leading_zero = false, has_width = false;
@ -465,15 +465,15 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik
if (!has_width && !has_leading_zero)
part.width = 20;
} else {
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with format character `%c' in argument %zu, but the argument is not $time or $realtime.\n", task_name.c_str(), fmt[i], fmtarg - args.begin() + 1);
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with format character `%c' in argument %zu, but the argument is not $time or $realtime.\n", task_name, fmt[i], fmtarg - args.begin() + 1);
}
} else {
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with unrecognized format character `%c' in argument %zu.\n", task_name.c_str(), fmt[i], fmtarg - args.begin() + 1);
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with unrecognized format character `%c' in argument %zu.\n", task_name, fmt[i], fmtarg - args.begin() + 1);
}
break;
}
if (i == fmt.size()) {
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1);
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name, fmtarg - args.begin() + 1);
}
if (part.padding == '\0') {
@ -486,7 +486,7 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik
}
if (part.type == FmtPart::INTEGER && part.base != 10 && part.sign != FmtPart::MINUS)
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with invalid format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1);
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with invalid format specifier in argument %zu.\n", task_name, fmtarg - args.begin() + 1);
if (part.base != 10)
part.signed_ = false;

View file

@ -33,9 +33,9 @@ FstData::FstData(std::string filename) : ctx(nullptr)
std::string filename_trim = file_base_name(filename);
if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".vcd") == 0) {
filename_trim.erase(filename_trim.size()-4);
tmp_file = stringf("%s/converted_%s.fst", get_base_tmpdir().c_str(), filename_trim.c_str());
std::string cmd = stringf("vcd2fst %s %s", filename.c_str(), tmp_file.c_str());
log("Exec: %s\n", cmd.c_str());
tmp_file = stringf("%s/converted_%s.fst", get_base_tmpdir(), filename_trim);
std::string cmd = stringf("vcd2fst %s %s", filename, tmp_file);
log("Exec: %s\n", cmd);
if (run_command(cmd) != 0)
log_cmd_error("Shell command failed!\n");
filename = tmp_file;
@ -44,7 +44,7 @@ FstData::FstData(std::string filename) : ctx(nullptr)
const std::vector<std::string> g_units = { "s", "ms", "us", "ns", "ps", "fs", "as", "zs" };
ctx = (fstReaderContext *)fstReaderOpen(filename.c_str());
if (!ctx)
log_error("Error opening '%s' as FST file\n", filename.c_str());
log_error("Error opening '%s' as FST file\n", filename);
int scale = (int)fstReaderGetTimescale(ctx);
timescale = pow(10.0, scale);
timescale_str = "";
@ -162,7 +162,7 @@ void FstData::extractVarNames()
char *endptr;
int mem_addr = strtol(addr.c_str(), &endptr, 16);
if (*endptr) {
log_debug("Error parsing memory address in : %s\n", clean_name.c_str());
log_debug("Error parsing memory address in : %s\n", clean_name);
} else {
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
}
@ -176,7 +176,7 @@ void FstData::extractVarNames()
char *endptr;
int mem_addr = strtol(addr.c_str(), &endptr, 10);
if (*endptr) {
log_debug("Error parsing memory address in : %s\n", clean_name.c_str());
log_debug("Error parsing memory address in : %s\n", clean_name);
} else {
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
}

View file

@ -395,7 +395,7 @@ public:
Node y = neg_if(y_flipped, sign(b));
return factory.extend(y, y_width, true);
} else
log_error("unhandled cell in CellSimplifier %s\n", cellType.c_str());
log_error("unhandled cell in CellSimplifier %s\n", cellType);
} else {
if(cellType.in(ID($mod), ID($modfloor)))
return factory.extend(factory.unsigned_mod(a, b), y_width, false);
@ -458,9 +458,9 @@ public:
return factory.value(state);
}
} else if(cellType == ID($check)) {
log_error("The design contains a $check cell `%s'. This is not supported by the functional backend. Call `chformal -lower' to avoid this error.\n", cellName.c_str());
log_error("The design contains a $check cell `%s'. This is not supported by the functional backend. Call `chformal -lower' to avoid this error.\n", cellName);
} else {
log_error("`%s' cells are not supported by the functional backend\n", cellType.c_str());
log_error("`%s' cells are not supported by the functional backend\n", cellType);
}
}
};
@ -605,7 +605,7 @@ private:
}
Node node = handle_memory(mem);
factory.update_pending(cell_outputs.at({cell, ID(RD_DATA)}), node);
} else if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
} else if (cell->is_builtin_ff()) {
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. "
@ -638,7 +638,7 @@ private:
}
}
}
void undriven(const char *name) {
void undriven(const std::string& name) {
log_error("The design contains an undriven signal %s. This is not supported by the functional backend. "
"Call setundef with appropriate options to avoid this error.\n", name);
}
@ -646,7 +646,7 @@ private:
void check_undriven(DriveSpec const& spec, std::string const& name) {
for(auto const &chunk : spec.chunks())
if(chunk.is_none())
undriven(name.c_str());
undriven(name);
}
public:
void process_queue()
@ -744,7 +744,7 @@ void IR::topological_sort() {
log_warning("Combinational loop:\n");
for (int *i = begin; i != end; ++i) {
Node node(_graph[*i]);
log("- %s = %s\n", RTLIL::unescape_id(node.name()).c_str(), node.to_string().c_str());
log("- %s = %s\n", RTLIL::unescape_id(node.name()), node.to_string());
}
log("\n");
scc = true;
@ -836,7 +836,7 @@ void Writer::print_impl(const char *fmt, vector<std::function<void()>> &fns)
else
p = pe;
if(index >= fns.size())
log_error("invalid format string: index %zu out of bounds (%zu): \"%s\"\n", index, fns.size(), quote_fmt(fmt).c_str());
log_error("invalid format string: index %zu out of bounds (%zu): \"%s\"\n", index, fns.size(), quote_fmt(fmt));
fns[index]();
next_index = index + 1;
}
@ -844,7 +844,7 @@ void Writer::print_impl(const char *fmt, vector<std::function<void()>> &fns)
case '}':
p++;
if(*p != '}')
log_error("invalid format string: unescaped }: \"%s\"\n", quote_fmt(fmt).c_str());
log_error("invalid format string: unescaped }: \"%s\"\n", quote_fmt(fmt));
*os << '}';
break;
default:

View file

@ -552,17 +552,17 @@ namespace Functional {
}
IRInput &add_input(IdString name, IdString kind, Sort sort) {
auto [it, inserted] = _ir._inputs.emplace({name, kind}, IRInput(_ir, name, kind, std::move(sort)));
if (!inserted) log_error("input `%s` was re-defined", name.c_str());
if (!inserted) log_error("input `%s` was re-defined", name);
return it->second;
}
IROutput &add_output(IdString name, IdString kind, Sort sort) {
auto [it, inserted] = _ir._outputs.emplace({name, kind}, IROutput(_ir, name, kind, std::move(sort)));
if (!inserted) log_error("output `%s` was re-defined", name.c_str());
if (!inserted) log_error("output `%s` was re-defined", name);
return it->second;
}
IRState &add_state(IdString name, IdString kind, Sort sort) {
auto [it, inserted] = _ir._states.emplace({name, kind}, IRState(_ir, name, kind, std::move(sort)));
if (!inserted) log_error("state `%s` was re-defined", name.c_str());
if (!inserted) log_error("state `%s` was re-defined", name);
return it->second;
}
Node value(IRInput const& input) {

View file

@ -103,11 +103,11 @@ gzip_istream::ibuf::~ibuf() {
// Never returns nullptr or failed state istream*
std::istream* uncompressed(const std::string filename, std::ios_base::openmode mode) {
if (!check_file_exists(filename))
log_cmd_error("File `%s' not found or is a directory\n", filename.c_str());
log_cmd_error("File `%s' not found or is a directory\n", filename);
std::ifstream* f = new std::ifstream();
f->open(filename, mode);
if (f->fail())
log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
log_cmd_error("Can't open input file `%s' for reading: %s\n", filename, strerror(errno));
// Check for gzip magic
unsigned char magic[3];
int n = 0;
@ -121,7 +121,7 @@ std::istream* uncompressed(const std::string filename, std::ios_base::openmode m
}
if (n == 3 && magic[0] == 0x1f && magic[1] == 0x8b) {
#ifdef YOSYS_ENABLE_ZLIB
log("Found gzip magic in file `%s', decompressing using zlib.\n", filename.c_str());
log("Found gzip magic in file `%s', decompressing using zlib.\n", filename);
if (magic[2] != 8)
log_cmd_error("gzip file `%s' uses unsupported compression type %02x\n",
filename.c_str(), unsigned(magic[2]));
@ -131,7 +131,7 @@ std::istream* uncompressed(const std::string filename, std::ios_base::openmode m
log_assert(ok && "Failed to open gzipped file.\n");
return s;
#else
log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", filename.c_str());
log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", filename);
#endif // YOSYS_ENABLE_ZLIB
} else {
f->clear();

View file

@ -168,8 +168,17 @@ struct hash_ops {
} else if constexpr (std::is_pointer_v<T>) {
return hash_ops<uintptr_t>::hash_into((uintptr_t) a, h);
} else if constexpr (std::is_same_v<T, std::string>) {
for (auto c : a)
h.hash32(c);
int size = a.size();
int i = 0;
while (i + 8 < size) {
uint64_t v;
memcpy(&v, a.data() + i, 8);
h.hash64(v);
i += 8;
}
uint64_t v = 0;
memcpy(&v, a.data() + i, size - i);
h.hash64(v);
return h;
} else {
return a.hash_into(h);
@ -188,6 +197,12 @@ template<typename P, typename Q> struct hash_ops<std::pair<P, Q>> {
return h;
}
HASH_TOP_LOOP_FST (const std::pair<P, Q> &a) HASH_TOP_LOOP_SND
[[nodiscard]] static inline Hasher hash(const P &p, const Q &q) {
Hasher h;
h = hash_ops<P>::hash_into(p, h);
h = hash_ops<Q>::hash_into(q, h);
return h;
}
};
template<typename... T> struct hash_ops<std::tuple<T...>> {
@ -509,12 +524,11 @@ class dict {
return do_lookup_internal(key, hash);
}
int do_insert(const K &key, Hasher::hash_t &hash)
int do_insert(const K &key, const Hasher::hash_t &hash)
{
if (hashtable.empty()) {
entries.emplace_back(std::pair<K, T>(key, T()), -1);
do_rehash();
hash = do_hash(key);
} else {
entries.emplace_back(std::pair<K, T>(key, T()), hashtable[hash]);
hashtable[hash] = entries.size() - 1;
@ -522,12 +536,11 @@ class dict {
return entries.size() - 1;
}
int do_insert(const std::pair<K, T> &value, Hasher::hash_t &hash)
int do_insert(const std::pair<K, T> &value, const Hasher::hash_t &hash)
{
if (hashtable.empty()) {
entries.emplace_back(value, -1);
do_rehash();
hash = do_hash(value.first);
} else {
entries.emplace_back(value, hashtable[hash]);
hashtable[hash] = entries.size() - 1;
@ -535,13 +548,11 @@ class dict {
return entries.size() - 1;
}
int do_insert(std::pair<K, T> &&rvalue, Hasher::hash_t &hash)
int do_insert(std::pair<K, T> &&rvalue, const Hasher::hash_t &hash)
{
if (hashtable.empty()) {
auto key = rvalue.first;
entries.emplace_back(std::forward<std::pair<K, T>>(rvalue), -1);
do_rehash();
hash = do_hash(key);
} else {
entries.emplace_back(std::forward<std::pair<K, T>>(rvalue), hashtable[hash]);
hashtable[hash] = entries.size() - 1;
@ -558,13 +569,16 @@ public:
int index;
const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { }
public:
typedef std::forward_iterator_tag iterator_category;
typedef std::bidirectional_iterator_tag iterator_category;
typedef std::pair<K, T> value_type;
typedef ptrdiff_t difference_type;
typedef std::pair<K, T>* pointer;
typedef std::pair<K, T>& reference;
typedef const std::pair<K, T>* pointer;
typedef const std::pair<K, T>& reference;
const_iterator() { }
const_iterator operator++() { index--; return *this; }
const_iterator operator++(int) { const_iterator tmp = *this; index--; return tmp; }
const_iterator operator--() { index++; return *this; }
const_iterator operator--(int) { const_iterator tmp = *this; index++; return tmp; }
const_iterator operator+=(int amt) { index -= amt; return *this; }
bool operator<(const const_iterator &other) const { return index > other.index; }
bool operator==(const const_iterator &other) const { return index == other.index; }
@ -598,6 +612,13 @@ public:
const std::pair<K, T> *operator->() const { return &ptr->entries[index].udata; }
operator const_iterator() const { return const_iterator(ptr, index); }
};
using reverse_iterator = std::reverse_iterator<const_iterator>;
reverse_iterator rbegin() const {
return std::make_reverse_iterator(end());
}
reverse_iterator rend() const {
return std::make_reverse_iterator(begin());
}
constexpr dict()
{
@ -847,7 +868,7 @@ public:
const_iterator begin() const { return const_iterator(this, int(entries.size())-1); }
const_iterator element(int n) const { return const_iterator(this, int(entries.size())-1-n); }
const_iterator end() const { return const_iterator(nullptr, -1); }
const_iterator end() const { return const_iterator(this, -1); }
};
template<typename K, typename OPS>

View file

@ -307,7 +307,7 @@ bool is_absolute_path(std::string filename)
void remove_directory(std::string dirname)
{
#ifdef _WIN32
run_command(stringf("rmdir /s /q \"%s\"", dirname.c_str()));
run_command(stringf("rmdir /s /q \"%s\"", dirname));
#else
struct stat stbuf;
struct dirent **namelist;
@ -315,7 +315,7 @@ void remove_directory(std::string dirname)
log_assert(n >= 0);
for (int i = 0; i < n; i++) {
if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) {
std::string buffer = stringf("%s/%s", dirname.c_str(), namelist[i]->d_name);
std::string buffer = stringf("%s/%s", dirname, namelist[i]->d_name);
if (!stat(buffer.c_str(), &stbuf) && S_ISREG(stbuf.st_mode)) {
remove(buffer.c_str());
} else
@ -575,6 +575,17 @@ void format_emit_string_view(std::string &result, std::string_view spec, int *dy
format_emit_stringf(result, spec, dynamic_ints, num_dynamic_ints, std::string(arg).c_str());
}
void format_emit_idstring(std::string &result, std::string_view spec, int *dynamic_ints,
DynamicIntCount num_dynamic_ints, const IdString &arg)
{
if (spec == "%s") {
// Format checking will have guaranteed num_dynamic_ints == 0.
result += arg.c_str();
return;
}
format_emit_stringf(result, spec, dynamic_ints, num_dynamic_ints, arg.c_str());
}
void format_emit_void_ptr(std::string &result, std::string_view spec, int *dynamic_ints,
DynamicIntCount num_dynamic_ints, const void *arg)
{

View file

@ -8,6 +8,10 @@
YOSYS_NAMESPACE_BEGIN
namespace RTLIL {
struct IdString;
}
inline std::string vstringf(const char *fmt, va_list ap)
{
// For the common case of strings shorter than 128, save a heap
@ -240,7 +244,8 @@ constexpr void check_format(std::string_view fmt, int fmt_start, bool *has_escap
case CONVSPEC_CHAR_PTR:
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 std::string_view &> &&
!std::is_convertible_v<Arg, const RTLIL::IdString &>) {
YOSYS_ABORT("Expected type convertible to char *");
}
*specs = found;
@ -279,6 +284,10 @@ void format_emit_string(std::string &result, std::string_view spec, int *dynamic
void format_emit_string_view(std::string &result, std::string_view spec, int *dynamic_ints,
DynamicIntCount num_dynamic_ints, std::string_view arg);
// Emit the string representation of `arg` that has been converted to a `RTLIL::IdString'.
void format_emit_idstring(std::string &result, std::string_view spec, int *dynamic_ints,
DynamicIntCount num_dynamic_ints, const RTLIL::IdString &arg);
// Emit the string representation of `arg` that has been converted to a `double'.
void format_emit_void_ptr(std::string &result, std::string_view spec, int *dynamic_ints,
DynamicIntCount num_dynamic_ints, const void *arg);
@ -329,6 +338,11 @@ inline void format_emit_one(std::string &result, std::string_view fmt, const Fou
format_emit_string_view(result, spec, dynamic_ints, num_dynamic_ints, s);
return;
}
if constexpr (std::is_convertible_v<Arg, const RTLIL::IdString &>) {
const RTLIL::IdString &s = arg;
format_emit_idstring(result, spec, dynamic_ints, num_dynamic_ints, s);
return;
}
break;
case CONVSPEC_VOID_PTR:
if constexpr (std::is_convertible_v<Arg, const void *>) {
@ -423,6 +437,7 @@ public:
{
return format_emit_toplevel(fmt, has_escapes, specs, args...);
}
std::string_view format_string() const { return fmt; }
private:
std::string_view fmt;
bool has_escapes = false;
@ -433,7 +448,7 @@ template <typename T> struct WrapType { using type = T; };
template <typename T> using TypeIdentity = typename WrapType<T>::type;
template <typename... Args>
inline std::string stringf(FmtString<TypeIdentity<Args>...> fmt, Args... args)
inline std::string stringf(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
return fmt.format(args...);
}

View file

@ -68,8 +68,6 @@ int log_debug_suppressed = 0;
vector<int> header_count;
vector<char*> log_id_cache;
vector<shared_str> string_buf;
int string_buf_index = -1;
static struct timeval initial_tv = { 0, 0 };
static bool next_print_log = false;
@ -102,17 +100,16 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
}
#endif
void logv(const char *format, va_list ap)
{
while (format[0] == '\n' && format[1] != 0) {
log("\n");
format++;
static void logv_string(std::string_view format, std::string str) {
size_t remove_leading = 0;
while (format.size() > 1 && format[0] == '\n') {
logv_string("\n", "\n");
format = format.substr(1);
++remove_leading;
}
if (remove_leading > 0) {
str = str.substr(remove_leading);
}
if (log_make_debug && !ys_debug(1))
return;
std::string str = vstringf(format, ap);
if (str.empty())
return;
@ -145,13 +142,13 @@ void logv(const char *format, va_list ap)
time_str += stringf("[%05d.%06d] ", int(tv.tv_sec), int(tv.tv_usec));
}
if (format[0] && format[strlen(format)-1] == '\n')
if (!format.empty() && format[format.size() - 1] == '\n')
next_print_log = true;
// Special case to detect newlines in Python log output, since
// the binding always calls `log("%s", payload)` and the newline
// is then in the first formatted argument
if (!strcmp(format, "%s") && str.back() == '\n')
if (format == "%s" && str.back() == '\n')
next_print_log = true;
for (auto f : log_files)
@ -190,7 +187,7 @@ void logv(const char *format, va_list ap)
if (!linebuffer.empty() && linebuffer.back() == '\n') {
for (auto &re : log_warn_regexes)
if (std::regex_search(linebuffer, re))
log_warning("Found log message matching -W regex:\n%s", str.c_str());
log_warning("Found log message matching -W regex:\n%s", str);
for (auto &[_, item] : log_expect_log)
if (std::regex_search(linebuffer, item.pattern))
@ -204,7 +201,14 @@ void logv(const char *format, va_list ap)
}
}
void logv_header(RTLIL::Design *design, const char *format, va_list ap)
void log_formatted_string(std::string_view format, std::string str)
{
if (log_make_debug && !ys_debug(1))
return;
logv_string(format, std::move(str));
}
void log_formatted_header(RTLIL::Design *design, std::string_view format, std::string str)
{
bool pop_errfile = false;
@ -222,8 +226,8 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap)
for (int c : header_count)
header_id += stringf("%s%d", header_id.empty() ? "" : ".", c);
log("%s. ", header_id.c_str());
logv(format, ap);
log("%s. ", header_id);
log_formatted_string(format, std::move(str));
log_flush();
if (log_hdump_all)
@ -231,7 +235,7 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap)
if (log_hdump.count(header_id) && design != nullptr)
for (auto &filename : log_hdump.at(header_id)) {
log("Dumping current design to '%s'.\n", filename.c_str());
log("Dumping current design to '%s'.\n", filename);
if (yosys_xtrace)
IdString::xtrace_db_dump();
Pass::call(design, {"dump", "-o", filename});
@ -243,10 +247,8 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap)
log_files.pop_back();
}
static void logv_warning_with_prefix(const char *prefix,
const char *format, va_list ap)
void log_formatted_warning(std::string_view prefix, std::string message)
{
std::string message = vstringf(format, ap);
bool suppressed = false;
for (auto &re : log_nowarn_regexes)
@ -255,7 +257,7 @@ static void logv_warning_with_prefix(const char *prefix,
if (suppressed)
{
log("Suppressed %s%s", prefix, message.c_str());
log("Suppressed %s%s", prefix, message);
}
else
{
@ -264,7 +266,7 @@ static void logv_warning_with_prefix(const char *prefix,
for (auto &re : log_werror_regexes)
if (std::regex_search(message, re))
log_error("%s", message.c_str());
log_error("%s", message);
bool warning_match = false;
for (auto &[_, item] : log_expect_warning)
@ -281,7 +283,7 @@ static void logv_warning_with_prefix(const char *prefix,
if (log_warnings.count(message))
{
log("%s%s", prefix, message.c_str());
log("%s%s", prefix, message);
log_flush();
}
else
@ -289,7 +291,7 @@ static void logv_warning_with_prefix(const char *prefix,
if (log_errfile != NULL && !log_quiet_warnings)
log_files.push_back(log_errfile);
log("%s%s", prefix, message.c_str());
log("%s%s", prefix, message);
log_flush();
if (log_errfile != NULL && !log_quiet_warnings)
@ -305,41 +307,19 @@ static void logv_warning_with_prefix(const char *prefix,
}
}
void logv_warning(const char *format, va_list ap)
void log_formatted_file_warning(std::string_view filename, int lineno, std::string str)
{
logv_warning_with_prefix("Warning: ", format, ap);
std::string prefix = stringf("%s:%d: Warning: ", filename, lineno);
log_formatted_warning(prefix, std::move(str));
}
void logv_warning_noprefix(const char *format, va_list ap)
void log_formatted_file_info(std::string_view filename, int lineno, std::string str)
{
logv_warning_with_prefix("", format, ap);
}
void log_file_warning(const std::string &filename, int lineno,
const char *format, ...)
{
va_list ap;
va_start(ap, format);
std::string prefix = stringf("%s:%d: Warning: ",
filename.c_str(), lineno);
logv_warning_with_prefix(prefix.c_str(), format, ap);
va_end(ap);
}
void log_file_info(const std::string &filename, int lineno,
const char *format, ...)
{
va_list ap;
va_start(ap, format);
std::string fmt = stringf("%s:%d: Info: %s",
filename.c_str(), lineno, format);
logv(fmt.c_str(), ap);
va_end(ap);
log("%s:%d: Info: %s", filename, lineno, str);
}
[[noreturn]]
static void logv_error_with_prefix(const char *prefix,
const char *format, va_list ap)
static void log_error_with_prefix(std::string_view prefix, std::string str)
{
#ifdef EMSCRIPTEN
auto backup_log_files = log_files;
@ -351,13 +331,15 @@ static void logv_error_with_prefix(const char *prefix,
if (log_errfile != NULL)
log_files.push_back(log_errfile);
if (log_error_stderr)
if (log_error_stderr) {
log_flush(); // Make sure we flush stdout before replacing it with stderr
for (auto &f : log_files)
if (f == stdout)
f = stderr;
}
log_last_error = vstringf(format, ap);
log("%s%s", prefix, log_last_error.c_str());
log_last_error = std::move(str);
log("%s%s", prefix, log_last_error);
log_flush();
log_make_debug = bak_log_make_debug;
@ -390,86 +372,50 @@ static void logv_error_with_prefix(const char *prefix,
#endif
}
void logv_error(const char *format, va_list ap)
void log_formatted_file_error(std::string_view filename, int lineno, std::string str)
{
logv_error_with_prefix("ERROR: ", format, ap);
std::string prefix = stringf("%s:%d: ERROR: ", filename, lineno);
log_error_with_prefix(prefix, str);
}
void logv_file_error(const string &filename, int lineno,
const char *format, va_list ap)
{
std::string prefix = stringf("%s:%d: ERROR: ",
filename.c_str(), lineno);
logv_error_with_prefix(prefix.c_str(), format, ap);
log_formatted_file_error(filename, lineno, vstringf(format, ap));
}
void log_file_error(const string &filename, int lineno,
const char *format, ...)
void log_experimental(const std::string &str)
{
va_list ap;
va_start(ap, format);
logv_file_error(filename, lineno, format, ap);
}
void log(const char *format, ...)
{
va_list ap;
va_start(ap, format);
logv(format, ap);
va_end(ap);
}
void log_header(RTLIL::Design *design, const char *format, ...)
{
va_list ap;
va_start(ap, format);
logv_header(design, format, ap);
va_end(ap);
}
void log_warning(const char *format, ...)
{
va_list ap;
va_start(ap, format);
logv_warning(format, ap);
va_end(ap);
}
void log_experimental(const char *format, ...)
{
va_list ap;
va_start(ap, format);
string s = vstringf(format, ap);
va_end(ap);
if (log_experimentals_ignored.count(s) == 0 && log_experimentals.count(s) == 0) {
log_warning("Feature '%s' is experimental.\n", s.c_str());
log_experimentals.insert(s);
if (log_experimentals_ignored.count(str) == 0 && log_experimentals.count(str) == 0) {
log_warning("Feature '%s' is experimental.\n", str);
log_experimentals.insert(str);
}
}
void log_warning_noprefix(const char *format, ...)
void log_formatted_error(std::string str)
{
va_list ap;
va_start(ap, format);
logv_warning_noprefix(format, ap);
va_end(ap);
log_error_with_prefix("ERROR: ", std::move(str));
}
void log_error(const char *format, ...)
void log_assert_failure(const char *expr, const char *file, int line)
{
va_list ap;
va_start(ap, format);
logv_error(format, ap);
log_error("Assert `%s' failed in %s:%d.\n", expr, file, line);
}
void log_cmd_error(const char *format, ...)
void log_abort_internal(const char *file, int line)
{
va_list ap;
va_start(ap, format);
log_error("Abort in %s:%d.\n", file, line);
}
void log_yosys_abort_message(std::string_view file, int line, std::string_view func, std::string_view message)
{
log_error("Abort in %s:%d (%s): %s\n", file, line, func, message);
}
void log_formatted_cmd_error(std::string str)
{
if (log_cmd_error_throw) {
log_last_error = vstringf(format, ap);
log_last_error = str;
// Make sure the error message gets through any selective silencing
// of log output
@ -479,7 +425,7 @@ void log_cmd_error(const char *format, ...)
pop_errfile = true;
}
log("ERROR: %s", log_last_error.c_str());
log("ERROR: %s", log_last_error);
log_flush();
if (pop_errfile)
@ -488,7 +434,7 @@ void log_cmd_error(const char *format, ...)
throw log_cmd_error_exception();
}
logv_error(format, ap);
log_formatted_error(str);
}
void log_spacer()
@ -506,8 +452,6 @@ void log_pop()
{
header_count.pop_back();
log_id_cache_clear();
string_buf.clear();
string_buf_index = -1;
log_flush();
}
@ -613,8 +557,6 @@ void log_reset_stack()
while (header_count.size() > 1)
header_count.pop_back();
log_id_cache_clear();
string_buf.clear();
string_buf_index = -1;
log_flush();
}
@ -639,38 +581,19 @@ void log_dump_val_worker(RTLIL::State v) {
log("%s", log_signal(v));
}
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint)
std::string log_signal(const RTLIL::SigSpec &sig, bool autoint)
{
std::stringstream buf;
RTLIL_BACKEND::dump_sigspec(buf, sig, autoint);
if (string_buf.size() < 100) {
string_buf.push_back(buf.str());
return string_buf.back().c_str();
} else {
if (++string_buf_index == 100)
string_buf_index = 0;
string_buf[string_buf_index] = buf.str();
return string_buf[string_buf_index].c_str();
}
return buf.str();
}
const char *log_const(const RTLIL::Const &value, bool autoint)
std::string log_const(const RTLIL::Const &value, bool autoint)
{
if ((value.flags & RTLIL::CONST_FLAG_STRING) == 0)
return log_signal(value, autoint);
std::string str = "\"" + value.decode_string() + "\"";
if (string_buf.size() < 100) {
string_buf.push_back(str);
return string_buf.back().c_str();
} else {
if (++string_buf_index == 100)
string_buf_index = 0;
string_buf[string_buf_index] = str;
return string_buf[string_buf_index].c_str();
}
return "\"" + value.decode_string() + "\"";
}
const char *log_id(const RTLIL::IdString &str)
@ -680,35 +603,25 @@ const char *log_id(const RTLIL::IdString &str)
return log_id_cache.back();
}
const char *log_str(const char *str)
{
log_id_cache.push_back(strdup(str));
return log_id_cache.back();
}
const char *log_str(std::string const &str) {
return log_str(str.c_str());
}
void log_module(RTLIL::Module *module, std::string indent)
{
std::stringstream buf;
RTLIL_BACKEND::dump_module(buf, indent, module, module->design, false);
log("%s", buf.str().c_str());
log("%s", buf.str());
}
void log_cell(RTLIL::Cell *cell, std::string indent)
{
std::stringstream buf;
RTLIL_BACKEND::dump_cell(buf, indent, cell);
log("%s", buf.str().c_str());
log("%s", buf.str());
}
void log_wire(RTLIL::Wire *wire, std::string indent)
{
std::stringstream buf;
RTLIL_BACKEND::dump_wire(buf, indent, wire);
log("%s", buf.str().c_str());
log("%s", buf.str());
}
void log_check_expected()
@ -727,7 +640,7 @@ void log_check_expected()
auto check = [&](const std::string kind, std::string pattern, LogExpectedItem item) {
if (item.current_count == 0) {
log_warn_regexes.clear();
log_error("Expected %s pattern '%s' not found !\n", kind.c_str(), pattern.c_str());
log_error("Expected %s pattern '%s' not found !\n", kind, pattern);
}
if (item.current_count != item.expected_count) {
log_warn_regexes.clear();
@ -748,7 +661,7 @@ void log_check_expected()
auto check_err = [&](const std::string kind, std::string pattern, LogExpectedItem item) {
if (item.current_count == item.expected_count) {
log_warn_regexes.clear();
log("Expected %s pattern '%s' found !!!\n", kind.c_str(), pattern.c_str());
log("Expected %s pattern '%s' found !!!\n", kind, pattern);
yosys_shutdown();
#ifdef EMSCRIPTEN
throw 0;
@ -759,7 +672,7 @@ void log_check_expected()
#endif
} else {
log_warn_regexes.clear();
log_error("Expected %s pattern '%s' not found !\n", kind.c_str(), pattern.c_str());
log_error("Expected %s pattern '%s' not found !\n", kind, pattern);
}
};
for (auto &[pattern, item] : expect_error)
@ -791,14 +704,14 @@ dict<std::string, std::pair<std::string, int>> get_coverage_data()
dict<std::string, std::pair<std::string, int>> coverage_data;
for (auto &it : pass_register) {
std::string key = stringf("passes.%s", it.first.c_str());
std::string key = stringf("passes.%s", it.first);
coverage_data[key].first = stringf("%s:%d:%s", __FILE__, __LINE__, __FUNCTION__);
coverage_data[key].second += it.second->call_counter;
}
for (auto &it : extra_coverage_data) {
if (coverage_data.count(it.first))
log_warning("found duplicate coverage id \"%s\".\n", it.first.c_str());
log_warning("found duplicate coverage id \"%s\".\n", it.first);
coverage_data[it.first].first = it.second.first;
coverage_data[it.first].second += it.second.second;
}

View file

@ -119,30 +119,12 @@ extern int log_make_debug;
extern int log_force_debug;
extern int log_debug_suppressed;
void logv(const char *format, va_list ap);
void logv_header(RTLIL::Design *design, const char *format, va_list ap);
void logv_warning(const char *format, va_list ap);
void logv_warning_noprefix(const char *format, va_list ap);
[[noreturn]] void logv_error(const char *format, va_list ap);
[[deprecated]]
[[noreturn]] void logv_file_error(const string &filename, int lineno, const char *format, va_list ap);
void log(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
void log_header(RTLIL::Design *design, const char *format, ...) YS_ATTRIBUTE(format(printf, 2, 3));
void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
void log_experimental(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
void set_verific_logging(void (*cb)(int msg_type, const char *message_id, const char* file_path, unsigned int left_line, unsigned int left_col, unsigned int right_line, unsigned int right_col, const char *msg));
extern void (*log_verific_callback)(int msg_type, const char *message_id, const char* file_path, unsigned int left_line, unsigned int left_col, unsigned int right_line, unsigned int right_col, const char *msg);
// Log with filename to report a problem in a source file.
void log_file_warning(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4));
void log_file_info(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4));
void log_warning_noprefix(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
[[noreturn]] void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
[[noreturn]] void log_file_error(const string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4));
[[noreturn]] void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
#ifndef NDEBUG
static inline bool ys_debug(int n = 0) { if (log_force_debug) return true; log_debug_suppressed += n; return false; }
#else
@ -150,6 +132,79 @@ static inline bool ys_debug(int = 0) { return false; }
#endif
# define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0)
void log_formatted_string(std::string_view format, std::string str);
template <typename... Args>
inline void log(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
if (log_make_debug && !ys_debug(1))
return;
log_formatted_string(fmt.format_string(), fmt.format(args...));
}
void log_formatted_header(RTLIL::Design *design, std::string_view format, std::string str);
template <typename... Args>
inline void log_header(RTLIL::Design *design, FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
log_formatted_header(design, fmt.format_string(), fmt.format(args...));
}
void log_formatted_warning(std::string_view prefix, std::string str);
template <typename... Args>
inline void log_warning(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
log_formatted_warning("Warning: ", fmt.format(args...));
}
inline void log_formatted_warning_noprefix(std::string str)
{
log_formatted_warning("", str);
}
template <typename... Args>
inline void log_warning_noprefix(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
log_formatted_warning("", fmt.format(args...));
}
void log_experimental(const std::string &str);
// Log with filename to report a problem in a source file.
void log_formatted_file_warning(std::string_view filename, int lineno, std::string str);
template <typename... Args>
void log_file_warning(std::string_view filename, int lineno, FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
log_formatted_file_warning(filename, lineno, fmt.format(args...));
}
void log_formatted_file_info(std::string_view filename, int lineno, std::string str);
template <typename... Args>
void log_file_info(std::string_view filename, int lineno, FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
if (log_make_debug && !ys_debug(1))
return;
log_formatted_file_info(filename, lineno, fmt.format(args...));
}
[[noreturn]] void log_formatted_error(std::string str);
template <typename... Args>
[[noreturn]] void log_error(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
log_formatted_error(fmt.format(args...));
}
[[noreturn]] void log_formatted_file_error(std::string_view filename, int lineno, std::string str);
template <typename... Args>
[[noreturn]] void log_file_error(std::string_view filename, int lineno, FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
log_formatted_file_error(filename, lineno, fmt.format(args...));
}
[[noreturn]] void log_formatted_cmd_error(std::string str);
template <typename... Args>
[[noreturn]] void log_cmd_error(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
log_formatted_cmd_error(fmt.format(args...));
}
static inline void log_suppressed() {
if (log_debug_suppressed && !log_make_debug) {
log("<suppressed ~%d debug messages>\n", log_debug_suppressed);
@ -204,11 +259,9 @@ extern dict<std::string, LogExpectedItem> log_expect_log, log_expect_warning, lo
extern dict<std::string, LogExpectedItem> log_expect_prefix_log, log_expect_prefix_warning, log_expect_prefix_error;
void log_check_expected();
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true);
const char *log_const(const RTLIL::Const &value, bool autoint = true);
std::string log_signal(const RTLIL::SigSpec &sig, bool autoint = true);
std::string log_const(const RTLIL::Const &value, bool autoint = true);
const char *log_id(const RTLIL::IdString &id);
const char *log_str(const char *str);
const char *log_str(std::string const &str);
template<typename T> static inline const char *log_id(T *obj, const char *nullstr = nullptr) {
if (nullstr && obj == nullptr)
@ -220,16 +273,20 @@ void log_module(RTLIL::Module *module, std::string indent = "");
void log_cell(RTLIL::Cell *cell, std::string indent = "");
void log_wire(RTLIL::Wire *wire, std::string indent = "");
[[noreturn]]
void log_assert_failure(const char *expr, const char *file, int line);
#ifndef NDEBUG
static inline void log_assert_worker(bool cond, const char *expr, const char *file, int line) {
if (!cond) log_error("Assert `%s' failed in %s:%d.\n", expr, file, line);
if (!cond) log_assert_failure(expr, file, line);
}
# define log_assert(_assert_expr_) YOSYS_NAMESPACE_PREFIX log_assert_worker(_assert_expr_, #_assert_expr_, __FILE__, __LINE__)
#else
# define log_assert(_assert_expr_) do { if (0) { (void)(_assert_expr_); } } while(0)
#endif
#define log_abort() YOSYS_NAMESPACE_PREFIX log_error("Abort in %s:%d.\n", __FILE__, __LINE__)
[[noreturn]]
void log_abort_internal(const char *file, int line);
#define log_abort() YOSYS_NAMESPACE_PREFIX log_abort_internal(__FILE__, __LINE__)
#define log_ping() YOSYS_NAMESPACE_PREFIX log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__)
@ -351,13 +408,27 @@ static inline void log_dump_val_worker(unsigned long int v) { log("%lu", v); }
static inline void log_dump_val_worker(long long int v) { log("%lld", v); }
static inline void log_dump_val_worker(unsigned long long int v) { log("%lld", v); }
#endif
static inline void log_dump_val_worker(char c) { log(c >= 32 && c < 127 ? "'%c'" : "'\\x%02x'", c); }
static inline void log_dump_val_worker(unsigned char c) { log(c >= 32 && c < 127 ? "'%c'" : "'\\x%02x'", c); }
static inline void log_dump_val_worker(char c)
{
if (c >= 32 && c < 127) {
log("'%c'", c);
} else {
log("'\\x%02x'", c);
}
}
static inline void log_dump_val_worker(unsigned char c)
{
if (c >= 32 && c < 127) {
log("'%c'", c);
} else {
log("'\\x%02x'", c);
}
}
static inline void log_dump_val_worker(bool v) { log("%s", v ? "true" : "false"); }
static inline void log_dump_val_worker(double v) { log("%f", v); }
static inline void log_dump_val_worker(char *v) { log("%s", v); }
static inline void log_dump_val_worker(const char *v) { log("%s", v); }
static inline void log_dump_val_worker(std::string v) { log("%s", v.c_str()); }
static inline void log_dump_val_worker(std::string v) { log("%s", v); }
static inline void log_dump_val_worker(PerformanceTimer p) { log("%f seconds", p.sec()); }
static inline void log_dump_args_worker(const char *p) { log_assert(*p == 0); }
void log_dump_val_worker(RTLIL::IdString v);
@ -374,7 +445,7 @@ static inline void log_dump_val_worker(dict<K, T> &v) {
log("{");
bool first = true;
for (auto &it : v) {
log(first ? " " : ", ");
log("%s ", first ? "" : ",");
log_dump_val_worker(it.first);
log(": ");
log_dump_val_worker(it.second);
@ -388,7 +459,7 @@ static inline void log_dump_val_worker(pool<K> &v) {
log("{");
bool first = true;
for (auto &it : v) {
log(first ? " " : ", ");
log("%s ", first ? "" : ",");
log_dump_val_worker(it);
first = false;
}
@ -400,7 +471,7 @@ static inline void log_dump_val_worker(std::vector<K> &v) {
log("{");
bool first = true;
for (auto &it : v) {
log(first ? " " : ", ");
log("%s ", first ? "" : ",");
log_dump_val_worker(it);
first = false;
}

86
kernel/log_compat.cc Normal file
View file

@ -0,0 +1,86 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/log.h"
YOSYS_NAMESPACE_BEGIN
// ABI compatibility for the YosysHQ Verific Extensions
// The YosysHQ Verific Extensions are compiled separately using their own
// stripped-down version of the Yosys headers. To maintain ABI compatibility
// with older extension builds post C++-ification of Yosys's logging APIs,
// which are backwards compatible on the API but not ABI level, this file
// provides ABI compatible versions of a subset of the old logging API used by
// the extensions.
void log_cmd_error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
std::string formatted = vstringf(format, ap);
va_end(ap);
log_formatted_cmd_error(formatted);
}
void log_warning(const char *format, ...)
{
va_list ap;
va_start(ap, format);
std::string formatted = vstringf(format, ap);
va_end(ap);
log_formatted_warning("Warning: ", formatted);
}
void log_warning_noprefix(const char *format, ...)
{
va_list ap;
va_start(ap, format);
std::string formatted = vstringf(format, ap);
va_end(ap);
log_formatted_warning("", formatted);
}
void log_error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
std::string formatted = vstringf(format, ap);
va_end(ap);
log_formatted_error(formatted);
}
static inline void log_formatted(std::string const &str)
{
// We use this inline wrapper as the following becomes ambiguous as soon as
// the `log` function below is declared.
return log("%s", str);
}
void log(const char *format, ...)
{
va_list ap;
va_start(ap, format);
std::string formatted = vstringf(format, ap);
va_end(ap);
log_formatted(formatted);
}
YOSYS_NAMESPACE_END

View file

@ -85,7 +85,7 @@ void log_pass_str(const std::string &pass_str, std::string indent_str, bool lead
if (leading_newline)
log("\n");
for (std::string line; std::getline(iss, line);) {
log("%s", indent_str.c_str());
log("%s", indent_str);
auto curr_len = indent_str.length();
std::istringstream lss(line);
for (std::string word; std::getline(lss, word, ' ');) {
@ -93,10 +93,10 @@ void log_pass_str(const std::string &pass_str, std::string indent_str, bool lead
word = word.substr(1, word.length()-2);
if (curr_len + word.length() >= MAX_LINE_LEN-1) {
curr_len = 0;
log("\n%s", indent_str.c_str());
log("\n%s", indent_str);
}
if (word.length()) {
log("%s ", word.c_str());
log("%s ", word);
curr_len += word.length() + 1;
}
}

View file

@ -262,7 +262,7 @@ struct Macc
bool eval(RTLIL::Const &result) const
{
for (auto &bit : result.bits())
for (auto bit : result)
bit = State::S0;
for (auto &port : terms)

View file

@ -131,9 +131,6 @@ void Mem::emit() {
cell->parameters[ID::WIDTH] = Const(width);
cell->parameters[ID::OFFSET] = Const(start_offset);
cell->parameters[ID::SIZE] = Const(size);
Const rd_wide_continuation, rd_clk_enable, rd_clk_polarity, rd_transparency_mask, rd_collision_x_mask;
Const wr_wide_continuation, wr_clk_enable, wr_clk_polarity, wr_priority_mask;
Const rd_ce_over_srst, rd_arst_value, rd_srst_value, rd_init_value;
SigSpec rd_clk, rd_en, rd_addr, rd_data;
SigSpec wr_clk, wr_en, wr_addr, wr_data;
SigSpec rd_arst, rd_srst;
@ -147,6 +144,15 @@ void Mem::emit() {
for (int i = 0; i < GetSize(wr_ports); i++)
for (int j = 0; j < (1 << wr_ports[i].wide_log2); j++)
wr_port_xlat.push_back(i);
Const::Builder rd_wide_continuation_builder;
Const::Builder rd_clk_enable_builder;
Const::Builder rd_clk_polarity_builder;
Const::Builder rd_transparency_mask_builder;
Const::Builder rd_collision_x_mask_builder;
Const::Builder rd_ce_over_srst_builder;
Const::Builder rd_arst_value_builder;
Const::Builder rd_srst_value_builder;
Const::Builder rd_init_value_builder;
for (auto &port : rd_ports) {
for (auto attr: port.attributes)
if (!cell->has_attribute(attr.first))
@ -157,10 +163,10 @@ void Mem::emit() {
}
for (int sub = 0; sub < (1 << port.wide_log2); sub++)
{
rd_wide_continuation.bits().push_back(State(sub != 0));
rd_clk_enable.bits().push_back(State(port.clk_enable));
rd_clk_polarity.bits().push_back(State(port.clk_polarity));
rd_ce_over_srst.bits().push_back(State(port.ce_over_srst));
rd_wide_continuation_builder.push_back(State(sub != 0));
rd_clk_enable_builder.push_back(State(port.clk_enable));
rd_clk_polarity_builder.push_back(State(port.clk_polarity));
rd_ce_over_srst_builder.push_back(State(port.ce_over_srst));
rd_clk.append(port.clk);
rd_arst.append(port.arst);
rd_srst.append(port.srst);
@ -170,18 +176,27 @@ void Mem::emit() {
rd_addr.append(addr);
log_assert(GetSize(addr) == abits);
for (auto idx : wr_port_xlat) {
rd_transparency_mask.bits().push_back(State(bool(port.transparency_mask[idx])));
rd_collision_x_mask.bits().push_back(State(bool(port.collision_x_mask[idx])));
rd_transparency_mask_builder.push_back(State(bool(port.transparency_mask[idx])));
rd_collision_x_mask_builder.push_back(State(bool(port.collision_x_mask[idx])));
}
}
rd_data.append(port.data);
for (auto bit : port.arst_value)
rd_arst_value.bits().push_back(bit);
rd_arst_value_builder.push_back(bit);
for (auto bit : port.srst_value)
rd_srst_value.bits().push_back(bit);
rd_srst_value_builder.push_back(bit);
for (auto bit : port.init_value)
rd_init_value.bits().push_back(bit);
rd_init_value_builder.push_back(bit);
}
Const rd_wide_continuation = rd_wide_continuation_builder.build();
Const rd_clk_enable = rd_clk_enable_builder.build();
Const rd_clk_polarity = rd_clk_polarity_builder.build();
Const rd_transparency_mask = rd_transparency_mask_builder.build();
Const rd_collision_x_mask = rd_collision_x_mask_builder.build();
Const rd_ce_over_srst = rd_ce_over_srst_builder.build();
Const rd_arst_value = rd_arst_value_builder.build();
Const rd_srst_value = rd_srst_value_builder.build();
Const rd_init_value = rd_init_value_builder.build();
if (rd_ports.empty()) {
rd_wide_continuation = State::S0;
rd_clk_enable = State::S0;
@ -212,6 +227,10 @@ void Mem::emit() {
cell->setPort(ID::RD_SRST, rd_srst);
cell->setPort(ID::RD_ADDR, rd_addr);
cell->setPort(ID::RD_DATA, rd_data);
Const::Builder wr_wide_continuation_builder;
Const::Builder wr_clk_enable_builder;
Const::Builder wr_clk_polarity_builder;
Const::Builder wr_priority_mask_builder;
for (auto &port : wr_ports) {
for (auto attr: port.attributes)
if (!cell->has_attribute(attr.first))
@ -222,12 +241,12 @@ void Mem::emit() {
}
for (int sub = 0; sub < (1 << port.wide_log2); sub++)
{
wr_wide_continuation.bits().push_back(State(sub != 0));
wr_clk_enable.bits().push_back(State(port.clk_enable));
wr_clk_polarity.bits().push_back(State(port.clk_polarity));
wr_wide_continuation_builder.push_back(State(sub != 0));
wr_clk_enable_builder.push_back(State(port.clk_enable));
wr_clk_polarity_builder.push_back(State(port.clk_polarity));
wr_clk.append(port.clk);
for (auto idx : wr_port_xlat)
wr_priority_mask.bits().push_back(State(bool(port.priority_mask[idx])));
wr_priority_mask_builder.push_back(State(bool(port.priority_mask[idx])));
SigSpec addr = port.sub_addr(sub);
addr.extend_u0(abits, false);
wr_addr.append(addr);
@ -236,6 +255,10 @@ void Mem::emit() {
wr_en.append(port.en);
wr_data.append(port.data);
}
Const wr_wide_continuation = wr_wide_continuation_builder.build();
Const wr_clk_enable = wr_clk_enable_builder.build();
Const wr_clk_polarity = wr_clk_polarity_builder.build();
Const wr_priority_mask = wr_priority_mask_builder.build();
if (wr_ports.empty()) {
wr_wide_continuation = State::S0;
wr_clk_enable = State::S0;
@ -414,7 +437,7 @@ void Mem::coalesce_inits() {
if (!init.en.is_fully_ones()) {
for (int i = 0; i < GetSize(init.data); i++)
if (init.en[i % width] != State::S1)
init.data.bits()[i] = State::Sx;
init.data.set(i, State::Sx);
init.en = Const(State::S1, width);
}
continue;
@ -427,7 +450,7 @@ void Mem::coalesce_inits() {
log_assert(offset + GetSize(init.data) <= GetSize(cdata));
for (int i = 0; i < GetSize(init.data); i++)
if (init.en[i % width] == State::S1)
cdata.bits()[i+offset] = init.data[i];
cdata.set(i+offset, init.data[i]);
init.removed = true;
}
MemInit new_init;
@ -446,7 +469,7 @@ Const Mem::get_init_data() const {
int offset = (init.addr.as_int() - start_offset) * width;
for (int i = 0; i < GetSize(init.data); i++)
if (0 <= i+offset && i+offset < GetSize(init_data) && init.en[i % width] == State::S1)
init_data.bits()[i+offset] = init.data[i];
init_data.set(i+offset, init.data[i]);
}
return init_data;
}
@ -900,7 +923,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
if (width)
{
SigSpec sig_q = module->addWire(stringf("$%s$rdreg[%d]$q", memid.c_str(), idx), width);
SigSpec sig_q = module->addWire(stringf("$%s$rdreg[%d]$q", memid, idx), width);
SigSpec sig_d;
int pos = 0;
@ -910,7 +933,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
port.addr[i] = sig_q[pos++];
}
c = module->addDff(stringf("$%s$rdreg[%d]", memid.c_str(), idx), port.clk, sig_d, sig_q, port.clk_polarity);
c = module->addDff(stringf("$%s$rdreg[%d]", memid, idx), port.clk, sig_d, sig_q, port.clk_polarity);
} else {
c = nullptr;
}
@ -919,7 +942,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
{
log_assert(port.arst == State::S0 || port.srst == State::S0);
SigSpec async_d = module->addWire(stringf("$%s$rdreg[%d]$d", memid.c_str(), idx), GetSize(port.data));
SigSpec async_d = module->addWire(stringf("$%s$rdreg[%d]$d", memid, idx), GetSize(port.data));
SigSpec sig_d = async_d;
for (int i = 0; i < GetSize(wr_ports); i++) {
@ -942,7 +965,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
raddr = port.sub_addr(sub);
SigSpec addr_eq;
if (raddr != waddr)
addr_eq = module->Eq(stringf("$%s$rdtransen[%d][%d][%d]$d", memid.c_str(), idx, i, sub), raddr, waddr);
addr_eq = module->Eq(stringf("$%s$rdtransen[%d][%d][%d]$d", memid, idx, i, sub), raddr, waddr);
int pos = 0;
int ewidth = width << min_wide_log2;
int wsub = wide_write ? sub : 0;
@ -955,10 +978,10 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
SigSpec other = port.transparency_mask[i] ? wport.data.extract(pos + wsub * width, epos-pos) : Const(State::Sx, epos-pos);
SigSpec cond;
if (raddr != waddr)
cond = module->And(stringf("$%s$rdtransgate[%d][%d][%d][%d]$d", memid.c_str(), idx, i, sub, pos), wport.en[pos + wsub * width], addr_eq);
cond = module->And(stringf("$%s$rdtransgate[%d][%d][%d][%d]$d", memid, idx, i, sub, pos), wport.en[pos + wsub * width], addr_eq);
else
cond = wport.en[pos + wsub * width];
SigSpec merged = module->Mux(stringf("$%s$rdtransmux[%d][%d][%d][%d]$d", memid.c_str(), idx, i, sub, pos), cur, other, cond);
SigSpec merged = module->Mux(stringf("$%s$rdtransmux[%d][%d][%d][%d]$d", memid, idx, i, sub, pos), cur, other, cond);
sig_d.replace(pos + rsub * width, merged);
pos = epos;
}
@ -966,7 +989,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
}
}
IdString name = stringf("$%s$rdreg[%d]", memid.c_str(), idx);
IdString name = stringf("$%s$rdreg[%d]", memid, idx);
FfData ff(module, initvals, name);
ff.width = GetSize(port.data);
ff.has_clk = true;
@ -1700,7 +1723,7 @@ MemContents::MemContents(Mem *mem) :
RTLIL::Const previous = (*this)[addr + i];
for(int j = 0; j < _data_width; j++)
if(init.en[j] != State::S1)
data.bits()[_data_width * i + j] = previous[j];
data.set(_data_width * i + j, previous[j]);
}
insert_concatenated(init.addr.as_int(), data);
}
@ -1846,7 +1869,7 @@ std::map<MemContents::addr_t, RTLIL::Const>::iterator MemContents::_reserve_rang
// we have two different ranges touching at either end, we need to merge them
auto upper_end = _range_end(upper_it);
// make range bigger (maybe reserve here instead of resize?)
lower_it->second.bits().resize(_range_offset(lower_it, upper_end), State::Sx);
lower_it->second.resize(_range_offset(lower_it, upper_end), State::Sx);
// copy only the data beyond our range
std::copy(_range_data(upper_it, end_addr), _range_data(upper_it, upper_end), _range_data(lower_it, end_addr));
// keep lower_it, but delete upper_it
@ -1854,16 +1877,16 @@ std::map<MemContents::addr_t, RTLIL::Const>::iterator MemContents::_reserve_rang
return lower_it;
} else if (lower_touch) {
// we have a range to the left, just make it bigger and delete any other that may exist.
lower_it->second.bits().resize(_range_offset(lower_it, end_addr), State::Sx);
lower_it->second.resize(_range_offset(lower_it, end_addr), State::Sx);
// keep lower_it and upper_it
_values.erase(std::next(lower_it), upper_it);
return lower_it;
} else if (upper_touch) {
// we have a range to the right, we need to expand it
// since we need to erase and reinsert to a new address, steal the data
RTLIL::Const data = std::move(upper_it->second);
// note that begin_addr is not in upper_it, otherwise the whole range covered check would have tripped
data.bits().insert(data.bits().begin(), (_range_begin(upper_it) - begin_addr) * _data_width, State::Sx);
RTLIL::Const data(State::Sx, (_range_begin(upper_it) - begin_addr) * _data_width);
data.append(std::move(upper_it->second));
// delete lower_it and upper_it, then reinsert
_values.erase(lower_it, std::next(upper_it));
return _values.emplace(begin_addr, std::move(data)).first;
@ -1886,7 +1909,7 @@ void MemContents::insert_concatenated(addr_t addr, RTLIL::Const const &values) {
std::fill(to_begin + values.size(), to_begin + words * _data_width, State::S0);
}
std::vector<State>::iterator MemContents::_range_write(std::vector<State>::iterator it, RTLIL::Const const &word) {
RTLIL::Const::iterator MemContents::_range_write(RTLIL::Const::iterator it, RTLIL::Const const &word) {
auto from_end = word.size() <= _data_width ? word.end() : word.begin() + _data_width;
auto to_end = std::copy(word.begin(), from_end, it);
auto it_next = std::next(it, _data_width);

View file

@ -255,11 +255,13 @@ private:
// return the offset the addr would have in the range at `it`
size_t _range_offset(std::map<addr_t, RTLIL::Const>::iterator it, addr_t addr) const { return (addr - it->first) * _data_width; }
// assuming _range_contains(it, addr), return an iterator pointing to the data at addr
std::vector<State>::iterator _range_data(std::map<addr_t, RTLIL::Const>::iterator it, addr_t addr) { return it->second.bits().begin() + _range_offset(it, addr); }
RTLIL::Const::iterator _range_data(std::map<addr_t, RTLIL::Const>::iterator it, addr_t addr) {
return RTLIL::Const::iterator(it->second, _range_offset(it, addr));
}
// internal version of reserve_range that returns an iterator to the range
std::map<addr_t, RTLIL::Const>::iterator _reserve_range(addr_t begin_addr, addr_t end_addr);
// write a single word at addr, return iterator to next word
std::vector<State>::iterator _range_write(std::vector<State>::iterator it, RTLIL::Const const &data);
RTLIL::Const::iterator _range_write(RTLIL::Const::iterator it, RTLIL::Const const &data);
public:
class range {
int _data_width;

View file

@ -54,7 +54,7 @@ Pass::Pass(std::string name, std::string short_help, source_location location) :
void Pass::run_register()
{
if (pass_register.count(pass_name) && !replace_existing_pass())
log_error("Unable to register pass '%s', pass already exists!\n", pass_name.c_str());
log_error("Unable to register pass '%s', pass already exists!\n", pass_name);
pass_register[pass_name] = this;
}
@ -123,7 +123,7 @@ void Pass::help()
prettyHelp.log_help();
} else {
log("\n");
log("No help message for command `%s'.\n", pass_name.c_str());
log("No help message for command `%s'.\n", pass_name);
log("\n");
}
}
@ -143,7 +143,7 @@ void Pass::cmd_log_args(const std::vector<std::string> &args)
return;
log("Full command line:");
for (size_t i = 0; i < args.size(); i++)
log(" %s", args[i].c_str());
log(" %s", args[i]);
log("\n");
}
@ -158,7 +158,7 @@ void Pass::cmd_error(const std::vector<std::string> &args, size_t argidx, std::s
command_text = command_text + (command_text.empty() ? "" : " ") + args[i];
}
log("\nSyntax error in command `%s':\n", command_text.c_str());
log("\nSyntax error in command `%s':\n", command_text);
help();
log_cmd_error("Command syntax error: %s\n> %s\n> %*s^\n",
@ -199,7 +199,7 @@ void Pass::call(RTLIL::Design *design, std::string command)
while (!cmd_buf.empty() && (cmd_buf.back() == ' ' || cmd_buf.back() == '\t' ||
cmd_buf.back() == '\r' || cmd_buf.back() == '\n'))
cmd_buf.resize(cmd_buf.size()-1);
log_header(design, "Shell command: %s\n", cmd_buf.c_str());
log_header(design, "Shell command: %s\n", cmd_buf);
int retCode = run_command(cmd_buf);
if (retCode != 0)
log_cmd_error("Shell command returned error code %d.\n", retCode);
@ -257,15 +257,15 @@ void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
if (echo_mode) {
log("%s", create_prompt(design, 0));
for (size_t i = 0; i < args.size(); i++)
log("%s%s", i ? " " : "", args[i].c_str());
log("%s%s", i ? " " : "", args[i]);
log("\n");
}
if (pass_register.count(args[0]) == 0)
log_cmd_error("No such command: %s (type 'help' for a command overview)\n", args[0].c_str());
log_cmd_error("No such command: %s (type 'help' for a command overview)\n", args[0]);
if (pass_register[args[0]]->experimental_flag)
log_experimental("%s", args[0].c_str());
log_experimental(args[0]);
size_t orig_sel_stack_pos = design->selection_stack.size();
auto state = pass_register[args[0]]->pre_execute();
@ -330,9 +330,9 @@ bool ScriptPass::check_label(std::string label, std::string info)
if (active_design == nullptr) {
log("\n");
if (info.empty())
log(" %s:\n", label.c_str());
log(" %s:\n", label);
else
log(" %s: %s\n", label.c_str(), info.c_str());
log(" %s: %s\n", label, info);
return true;
} else {
if (!active_run_from.empty() && active_run_from == active_run_to) {
@ -351,9 +351,9 @@ void ScriptPass::run(std::string command, std::string info)
{
if (active_design == nullptr) {
if (info.empty())
log(" %s\n", command.c_str());
log(" %s\n", command);
else
log(" %s %s\n", command.c_str(), info.c_str());
log(" %s %s\n", command, info);
} else {
Pass::call(active_design, command);
active_design->check();
@ -364,9 +364,9 @@ void ScriptPass::run_nocheck(std::string command, std::string info)
{
if (active_design == nullptr) {
if (info.empty())
log(" %s\n", command.c_str());
log(" %s\n", command);
else
log(" %s %s\n", command.c_str(), info.c_str());
log(" %s %s\n", command, info);
} else {
Pass::call(active_design, command);
}
@ -402,11 +402,11 @@ Frontend::Frontend(std::string name, std::string short_help, source_location loc
void Frontend::run_register()
{
if (pass_register.count(pass_name) && !replace_existing_pass())
log_error("Unable to register pass '%s', pass already exists!\n", pass_name.c_str());
log_error("Unable to register pass '%s', pass already exists!\n", pass_name);
pass_register[pass_name] = this;
if (frontend_register.count(frontend_name) && !replace_existing_pass())
log_error("Unable to register frontend '%s', frontend already exists!\n", frontend_name.c_str());
log_error("Unable to register frontend '%s', frontend already exists!\n", frontend_name);
frontend_register[frontend_name] = this;
}
@ -462,7 +462,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
char block[4096];
while (1) {
if (fgets(block, 4096, Frontend::current_script_file == nullptr? stdin : Frontend::current_script_file) == nullptr)
log_error("Unexpected end of file in here document '%s'!\n", filename.c_str());
log_error("Unexpected end of file in here document '%s'!\n", filename);
buffer += block;
if (buffer.size() > 0 && (buffer[buffer.size() - 1] == '\n' || buffer[buffer.size() - 1] == '\r'))
break;
@ -521,7 +521,7 @@ void Frontend::frontend_call(RTLIL::Design *design, std::istream *f, std::string
if (args.size() == 0)
return;
if (frontend_register.count(args[0]) == 0)
log_cmd_error("No such frontend: %s\n", args[0].c_str());
log_cmd_error("No such frontend: %s\n", args[0]);
if (f != NULL) {
auto state = frontend_register[args[0]]->pre_execute();
@ -548,11 +548,11 @@ Backend::Backend(std::string name, std::string short_help, source_location locat
void Backend::run_register()
{
if (pass_register.count(pass_name))
log_error("Unable to register pass '%s', pass already exists!\n", pass_name.c_str());
log_error("Unable to register pass '%s', pass already exists!\n", pass_name);
pass_register[pass_name] = this;
if (backend_register.count(backend_name))
log_error("Unable to register backend '%s', backend already exists!\n", backend_name.c_str());
log_error("Unable to register backend '%s', backend already exists!\n", backend_name);
backend_register[backend_name] = this;
}
@ -596,7 +596,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
gzip_ostream *gf = new gzip_ostream;
if (!gf->open(filename)) {
delete gf;
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename, strerror(errno));
}
yosys_output_files.insert(filename);
f = gf;
@ -609,7 +609,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
yosys_output_files.insert(filename);
if (ff->fail()) {
delete ff;
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename, strerror(errno));
}
f = ff;
}
@ -641,7 +641,7 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f
if (args.size() == 0)
return;
if (backend_register.count(args[0]) == 0)
log_cmd_error("No such backend: %s\n", args[0].c_str());
log_cmd_error("No such backend: %s\n", args[0]);
size_t orig_sel_stack_pos = design->selection_stack.size();
@ -699,12 +699,12 @@ static void log_warning_flags(Pass *pass) {
if (pass->experimental_flag) {
if (!has_warnings) log("\n");
has_warnings = true;
log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", name.c_str());
log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", name);
}
if (pass->internal_flag) {
if (!has_warnings) log("\n");
has_warnings = true;
log("WARNING: THE '%s' COMMAND IS INTENDED FOR INTERNAL DEVELOPER USE ONLY.\n", name.c_str());
log("WARNING: THE '%s' COMMAND IS INTENDED FOR INTERNAL DEVELOPER USE ONLY.\n", name);
}
if (has_warnings)
log("\n");
@ -956,23 +956,17 @@ struct HelpPass : public Pass {
auto name = it.first.str();
if (cell_help_messages.contains(name)) {
auto cell_help = cell_help_messages.get(name);
if (groups.count(cell_help.group) != 0) {
auto group_cells = &groups.at(cell_help.group);
group_cells->push_back(name);
} else {
auto group_cells = new vector<string>(1, name);
groups.emplace(cell_help.group, *group_cells);
}
groups[cell_help.group].emplace_back(name);
auto cell_pair = pair<SimHelper, CellType>(cell_help, it.second);
cells.emplace(name, cell_pair);
} else {
log("ERROR: Missing cell help for cell '%s'.\n", name.c_str());
log("ERROR: Missing cell help for cell '%s'.\n", name);
raise_error |= true;
}
}
for (auto &it : cell_help_messages.cell_help) {
if (cells.count(it.first) == 0) {
log_warning("Found cell model '%s' without matching cell type.\n", it.first.c_str());
log_warning("Found cell model '%s' without matching cell type.\n", it.first);
}
}
@ -1028,7 +1022,7 @@ struct HelpPass : public Pass {
if (args.size() == 1) {
log("\n");
for (auto &it : pass_register)
log(" %-20s %s\n", it.first.c_str(), it.second->short_help.c_str());
log(" %-20s %s\n", it.first, it.second->short_help);
log("\n");
log("Type 'help <command>' for more information on a command.\n");
log("Type 'help -cells' for a list of all cell types.\n");
@ -1040,7 +1034,7 @@ struct HelpPass : public Pass {
if (args[1] == "-all") {
for (auto &it : pass_register) {
log("\n\n");
log("%s -- %s\n", it.first.c_str(), it.second->short_help.c_str());
log("%s -- %s\n", it.first, it.second->short_help);
for (size_t i = 0; i < it.first.size() + it.second->short_help.size() + 6; i++)
log("=");
log("\n");
@ -1052,7 +1046,7 @@ struct HelpPass : public Pass {
log("\n");
for (auto &it : cell_help_messages.cell_help) {
SimHelper help_cell = it.second;
log(" %-15s %s\n", help_cell.name.c_str(), help_cell.ports.c_str());
log(" %-15s %s\n", help_cell.name, help_cell.ports);
}
log("\n");
log("Type 'help <cell_type>' for more information on a cell type.\n");
@ -1067,34 +1061,34 @@ struct HelpPass : public Pass {
auto help_cell = cell_help_messages.get(args[1]);
if (is_code_getter(args[1])) {
log("\n");
log("%s\n", help_cell.code.c_str());
log("%s\n", help_cell.code);
} else {
log("\n %s %s\n\n", help_cell.name.c_str(), help_cell.ports.c_str());
log("\n %s %s\n\n", help_cell.name, help_cell.ports);
if (help_cell.ver == "2" || help_cell.ver == "2a") {
if (help_cell.title != "") log("%s:\n", help_cell.title.c_str());
if (help_cell.title != "") log("%s:\n", help_cell.title);
std::stringstream ss;
ss << help_cell.desc;
for (std::string line; std::getline(ss, line, '\n');) {
if (line != "::") log("%s\n", line.c_str());
if (line != "::") log("%s\n", line);
}
} else if (help_cell.desc.length()) {
log("%s\n", help_cell.desc.c_str());
log("%s\n", help_cell.desc);
} else {
log("No help message for this cell type found.\n");
}
log("\nRun 'help %s+' to display the Verilog model for this cell type.\n", args[1].c_str());
log("\nRun 'help %s+' to display the Verilog model for this cell type.\n", args[1]);
log("\n");
}
}
else
log("No such command or cell type: %s\n", args[1].c_str());
log("No such command or cell type: %s\n", args[1]);
return;
} else if (args.size() == 3) {
// this option is undocumented as it is for internal use only
if (args[1] == "-dump-cmds-json") {
PrettyJson json;
if (!json.write_to_file(args[2]))
log_error("Can't open file `%s' for writing: %s\n", args[2].c_str(), strerror(errno));
log_error("Can't open file `%s' for writing: %s\n", args[2], strerror(errno));
if (dump_cmds_json(json)) {
log_abort();
}
@ -1103,13 +1097,13 @@ struct HelpPass : public Pass {
else if (args[1] == "-dump-cells-json") {
PrettyJson json;
if (!json.write_to_file(args[2]))
log_error("Can't open file `%s' for writing: %s\n", args[2].c_str(), strerror(errno));
log_error("Can't open file `%s' for writing: %s\n", args[2], strerror(errno));
if (dump_cells_json(json)) {
log_error("One or more cells defined in celltypes.h are missing help documentation.\n");
}
}
else
log("Unknown help command: `%s %s'\n", args[1].c_str(), args[2].c_str());
log("Unknown help command: `%s %s'\n", args[1], args[2]);
return;
}

View file

@ -29,6 +29,7 @@
#include <string.h>
#include <algorithm>
#include <optional>
#include <string_view>
YOSYS_NAMESPACE_BEGIN
@ -37,7 +38,7 @@ RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard;
std::vector<char*> RTLIL::IdString::global_id_storage_;
std::unordered_map<std::string_view, int> RTLIL::IdString::global_id_index_;
#ifndef YOSYS_NO_IDS_REFCNT
std::vector<int> RTLIL::IdString::global_refcount_storage_;
std::vector<uint32_t> RTLIL::IdString::global_refcount_storage_;
std::vector<int> RTLIL::IdString::global_free_idx_list_;
#endif
#ifdef YOSYS_USE_STICKY_IDS
@ -45,13 +46,48 @@ int RTLIL::IdString::last_created_idx_[8];
int RTLIL::IdString::last_created_idx_ptr_;
#endif
#define X(_id) IdString RTLIL::ID::_id;
#define X(_id) const RTLIL::IdString RTLIL::IDInternal::_id(RTLIL::StaticId::_id);
#include "kernel/constids.inc"
#undef X
static void populate(std::string_view name)
{
if (name[1] == '$') {
// Skip prepended '\'
name = name.substr(1);
}
RTLIL::IdString::global_id_index_.insert({name, GetSize(RTLIL::IdString::global_id_storage_)});
RTLIL::IdString::global_id_storage_.push_back(const_cast<char*>(name.data()));
}
void RTLIL::IdString::prepopulate()
{
int size = static_cast<short>(RTLIL::StaticId::STATIC_ID_END);
global_id_storage_.reserve(size);
RTLIL::IdString::global_id_storage_.push_back(const_cast<char*>(""));
global_id_index_.reserve(size);
global_refcount_storage_.resize(size, 1);
#define X(N) populate("\\" #N);
#include "kernel/constids.inc"
#undef X
}
static constexpr bool check_well_known_id_order()
{
int size = sizeof(IdTable) / sizeof(IdTable[0]);
for (int i = 1; i < size; ++i)
if (IdTable[i - 1].name >= IdTable[i].name)
return false;
return true;
}
// Ensure the statically allocated IdStrings in kernel/constids.inc are unique
// and in sorted ascii order, as required by the ID macro.
static_assert(check_well_known_id_order());
dict<std::string, std::string> RTLIL::constpad;
const pool<IdString> &RTLIL::builtin_ff_cell_types() {
static const pool<IdString> &builtin_ff_cell_types_internal() {
static const pool<IdString> res = {
ID($sr),
ID($ff),
@ -202,14 +238,28 @@ const pool<IdString> &RTLIL::builtin_ff_cell_types() {
return res;
}
const pool<IdString> &RTLIL::builtin_ff_cell_types() {
return builtin_ff_cell_types_internal();
}
#define check(condition) log_assert(condition && "malformed Const union")
Const::bitvectype& Const::get_bits() const {
const Const::bitvectype& Const::get_bits() const {
check(is_bits());
return *get_if_bits();
}
std::string& Const::get_str() const {
const std::string& Const::get_str() const {
check(is_str());
return *get_if_str();
}
Const::bitvectype& Const::get_bits() {
check(is_bits());
return *get_if_bits();
}
std::string& Const::get_str() {
check(is_str());
return *get_if_str();
}
@ -221,9 +271,34 @@ RTLIL::Const::Const(const std::string &str)
tag = backing_tag::string;
}
RTLIL::Const::Const(long long val) // default width 32
{
flags = RTLIL::CONST_FLAG_NONE;
char bytes[] = {
(char)(val >> 24), (char)(val >> 16), (char)(val >> 8), (char)val
};
new ((void*)&str_) std::string(bytes, 4);
tag = backing_tag::string;
}
RTLIL::Const::Const(long long val, int width)
{
flags = RTLIL::CONST_FLAG_NONE;
if ((width & 7) == 0) {
new ((void*)&str_) std::string();
tag = backing_tag::string;
std::string& str = get_str();
int bytes = width >> 3;
signed char sign_byte = val < 0 ? -1 : 0;
str.resize(bytes, sign_byte);
bytes = std::min<int>(bytes, sizeof(val));
for (int i = 0; i < bytes; i++) {
str[str.size() - 1 - i] = val;
val = val >> 8;
}
return;
}
new ((void*)&bits_) bitvectype();
tag = backing_tag::bits;
bitvectype& bv = get_bits();
@ -327,6 +402,11 @@ bool RTLIL::Const::operator<(const RTLIL::Const &other) const
bool RTLIL::Const::operator ==(const RTLIL::Const &other) const
{
if (is_str() && other.is_str())
return get_str() == other.get_str();
if (is_bits() && other.is_bits())
return get_bits() == other.get_bits();
if (size() != other.size())
return false;
@ -342,9 +422,9 @@ bool RTLIL::Const::operator !=(const RTLIL::Const &other) const
return !(*this == other);
}
std::vector<RTLIL::State>& RTLIL::Const::bits()
std::vector<RTLIL::State>& RTLIL::Const::bits_internal()
{
bitvectorize();
bitvectorize_internal();
return get_bits();
}
@ -358,8 +438,14 @@ std::vector<RTLIL::State> RTLIL::Const::to_bits() const
bool RTLIL::Const::as_bool() const
{
bitvectorize();
bitvectype& bv = get_bits();
if (is_str()) {
for (char ch : get_str())
if (ch != 0)
return true;
return false;
}
const bitvectype& bv = get_bits();
for (size_t i = 0; i < bv.size(); i++)
if (bv[i] == State::S1)
return true;
@ -368,15 +454,25 @@ bool RTLIL::Const::as_bool() const
int RTLIL::Const::as_int(bool is_signed) const
{
bitvectorize();
bitvectype& bv = get_bits();
int32_t ret = 0;
for (size_t i = 0; i < bv.size() && i < 32; i++)
if (const std::string *s = get_if_str()) {
int size = GetSize(*s);
// Ignore any bytes after the first 4 since bits beyond 32 are truncated.
for (int i = std::min(4, size); i > 0; i--)
ret |= static_cast<unsigned char>((*s)[size - i]) << ((i - 1) * 8);
// If is_signed and the string is shorter than 4 bytes then apply sign extension.
if (is_signed && size > 0 && size < 4 && ((*s)[0] & 0x80))
ret |= UINT32_MAX << size*8;
return ret;
}
const bitvectype& bv = get_bits();
int significant_bits = std::min(GetSize(bv), 32);
for (int i = 0; i < significant_bits; i++)
if (bv[i] == State::S1)
ret |= 1 << i;
if (is_signed && bv.back() == State::S1)
for (size_t i = bv.size(); i < 32; i++)
ret |= 1 << i;
if (is_signed && significant_bits > 0 && significant_bits < 32 && bv.back() == State::S1 )
ret |= UINT32_MAX << significant_bits;
return ret;
}
@ -396,7 +492,7 @@ bool RTLIL::Const::convertible_to_int(bool is_signed) const
if (size == 32) {
if (is_signed)
return true;
return get_bits().at(31) != State::S1;
return back() != State::S1;
}
return false;
@ -417,7 +513,7 @@ int RTLIL::Const::as_int_saturating(bool is_signed) const
const auto min_size = get_min_size(is_signed);
log_assert(min_size > 0);
const auto neg = get_bits().at(min_size - 1);
const auto neg = (*this)[min_size - 1];
return neg ? std::numeric_limits<int>::min() : std::numeric_limits<int>::max();
}
return as_int(is_signed);
@ -450,7 +546,7 @@ int RTLIL::Const::get_min_size(bool is_signed) const
void RTLIL::Const::compress(bool is_signed)
{
auto idx = get_min_size(is_signed);
bits().erase(bits().begin() + idx, bits().end());
resize(idx, RTLIL::State::S0);
}
std::optional<int> RTLIL::Const::as_int_compress(bool is_signed) const
@ -460,18 +556,17 @@ std::optional<int> RTLIL::Const::as_int_compress(bool is_signed) const
std::string RTLIL::Const::as_string(const char* any) const
{
bitvectorize();
bitvectype& bv = get_bits();
int sz = size();
std::string ret;
ret.reserve(bv.size());
for (size_t i = bv.size(); i > 0; i--)
switch (bv[i-1]) {
case S0: ret += "0"; break;
case S1: ret += "1"; break;
case Sx: ret += "x"; break;
case Sz: ret += "z"; break;
ret.reserve(sz);
for (int i = sz - 1; i >= 0; --i)
switch ((*this)[i]) {
case S0: ret.push_back('0'); break;
case S1: ret.push_back('1'); break;
case Sx: ret.push_back('x'); break;
case Sz: ret.push_back('z'); break;
case Sa: ret += any; break;
case Sm: ret += "m"; break;
case Sm: ret.push_back('m'); break;
}
return ret;
}
@ -498,8 +593,7 @@ std::string RTLIL::Const::decode_string() const
if (auto str = get_if_str())
return *str;
bitvectorize();
bitvectype& bv = get_bits();
const bitvectype& bv = get_bits();
const int n = GetSize(bv);
const int n_over_8 = n / 8;
std::string s;
@ -547,7 +641,7 @@ bool RTLIL::Const::empty() const {
}
}
void RTLIL::Const::bitvectorize() const {
void RTLIL::Const::bitvectorize_internal() {
if (tag == backing_tag::bits)
return;
@ -573,26 +667,33 @@ void RTLIL::Const::bitvectorize() const {
}
void RTLIL::Const::append(const RTLIL::Const &other) {
bitvectorize();
bitvectorize_internal();
bitvectype& bv = get_bits();
bv.insert(bv.end(), other.begin(), other.end());
}
RTLIL::State RTLIL::Const::const_iterator::operator*() const {
if (auto bv = parent.get_if_bits())
if (auto bv = parent->get_if_bits())
return (*bv)[idx];
int char_idx = parent.get_str().size() - idx / 8 - 1;
bool bit = (parent.get_str()[char_idx] & (1 << (idx % 8)));
int char_idx = parent->get_str().size() - idx / 8 - 1;
bool bit = (parent->get_str()[char_idx] & (1 << (idx % 8)));
return bit ? State::S1 : State::S0;
}
bool RTLIL::Const::is_fully_zero() const
{
bitvectorize();
bitvectype& bv = get_bits();
cover("kernel.rtlil.const.is_fully_zero");
if (auto str = get_if_str()) {
for (char ch : *str)
if (ch != 0)
return false;
return true;
}
const bitvectype& bv = get_bits();
for (const auto &bit : bv)
if (bit != RTLIL::State::S0)
return false;
@ -602,10 +703,16 @@ bool RTLIL::Const::is_fully_zero() const
bool RTLIL::Const::is_fully_ones() const
{
bitvectorize();
bitvectype& bv = get_bits();
cover("kernel.rtlil.const.is_fully_ones");
if (auto str = get_if_str()) {
for (char ch : *str)
if (ch != (char)0xff)
return false;
return true;
}
const bitvectype& bv = get_bits();
for (const auto &bit : bv)
if (bit != RTLIL::State::S1)
return false;
@ -617,9 +724,10 @@ bool RTLIL::Const::is_fully_def() const
{
cover("kernel.rtlil.const.is_fully_def");
bitvectorize();
bitvectype& bv = get_bits();
if (is_str())
return true;
const bitvectype& bv = get_bits();
for (const auto &bit : bv)
if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1)
return false;
@ -631,9 +739,10 @@ bool RTLIL::Const::is_fully_undef() const
{
cover("kernel.rtlil.const.is_fully_undef");
bitvectorize();
bitvectype& bv = get_bits();
if (auto str = get_if_str())
return str->empty();
const bitvectype& bv = get_bits();
for (const auto &bit : bv)
if (bit != RTLIL::State::Sx && bit != RTLIL::State::Sz)
return false;
@ -645,9 +754,10 @@ bool RTLIL::Const::is_fully_undef_x_only() const
{
cover("kernel.rtlil.const.is_fully_undef_x_only");
bitvectorize();
bitvectype& bv = get_bits();
if (auto str = get_if_str())
return str->empty();
const bitvectype& bv = get_bits();
for (const auto &bit : bv)
if (bit != RTLIL::State::Sx)
return false;
@ -659,12 +769,10 @@ bool RTLIL::Const::is_onehot(int *pos) const
{
cover("kernel.rtlil.const.is_onehot");
bitvectorize();
bitvectype& bv = get_bits();
bool found = false;
for (int i = 0; i < GetSize(*this); i++) {
auto &bit = bv[i];
int size = GetSize(*this);
for (int i = 0; i < size; i++) {
State bit = (*this)[i];
if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1)
return false;
if (bit == RTLIL::State::S1) {
@ -678,6 +786,40 @@ bool RTLIL::Const::is_onehot(int *pos) const
return found;
}
Hasher RTLIL::Const::hash_into(Hasher h) const
{
if (auto str = get_if_str())
return hashlib::hash_ops<std::string>::hash_into(*str, h);
// If the bits are all 0/1, hash packed bits using the string hash.
// Otherwise hash the leading packed bits with the rest of the bits individually.
const bitvectype &bv = get_bits();
int size = GetSize(bv);
std::string packed;
int packed_size = (size + 7) >> 3;
packed.resize(packed_size, 0);
for (int bi = 0; bi < packed_size; ++bi) {
char ch = 0;
int end = std::min((bi + 1)*8, size);
for (int i = bi*8; i < end; ++i) {
RTLIL::State b = bv[i];
if (b > RTLIL::State::S1) {
// Hash the packed bits we've seen so far, plus the remaining bits.
h = hashlib::hash_ops<std::string>::hash_into(packed, h);
h = hashlib::hash_ops<char>::hash_into(ch, h);
for (; i < size; ++i) {
h = hashlib::hash_ops<RTLIL::State>::hash_into(bv[i], h);
}
h.eat(size);
return h;
}
ch |= static_cast<int>(b) << (i & 7);
}
packed[packed_size - 1 - bi] = ch;
}
return hashlib::hash_ops<std::string>::hash_into(packed, h);
}
RTLIL::Const RTLIL::Const::extract(int offset, int len, RTLIL::State padding) const {
bitvectype ret_bv;
ret_bv.reserve(len);
@ -1020,7 +1162,7 @@ void RTLIL::Design::add(RTLIL::Binding *binding)
RTLIL::Module *RTLIL::Design::addModule(RTLIL::IdString name)
{
if (modules_.count(name) != 0)
log_error("Attempted to add new module named '%s', but a module by that name already exists\n", name.c_str());
log_error("Attempted to add new module named '%s', but a module by that name already exists\n", name);
log_assert(refcount_modules_ == 0);
RTLIL::Module *module = new RTLIL::Module;
@ -2309,6 +2451,19 @@ namespace {
check_expected();
return;
}
if (cell->type.in(ID($input_port))) {
param(ID::WIDTH);
port(ID::Y, param(ID::WIDTH));
check_expected();
return;
}
if (cell->type.in(ID($connect))) {
param(ID::WIDTH);
port(ID::A, param(ID::WIDTH));
port(ID::B, param(ID::WIDTH));
check_expected();
return;
}
/*
* Checklist for adding internal cell types
* ========================================
@ -2674,6 +2829,13 @@ void RTLIL::Module::remove(const pool<RTLIL::Wire*> &wires)
delete_wire_worker.wires_p = &wires;
rewrite_sigspecs2(delete_wire_worker);
if (design->flagBufferedNormalized) {
for (auto wire : wires) {
buf_norm_wire_queue.erase(wire);
buf_norm_connect_index.erase(wire);
}
}
for (auto &it : wires) {
log_assert(wires_.count(it->name) != 0);
wires_.erase(it->name);
@ -2689,7 +2851,13 @@ void RTLIL::Module::remove(RTLIL::Cell *cell)
log_assert(cells_.count(cell->name) != 0);
log_assert(refcount_cells_ == 0);
cells_.erase(cell->name);
delete cell;
if (design && design->flagBufferedNormalized && buf_norm_cell_queue.count(cell)) {
cell->type.clear();
cell->name.clear();
pending_deleted_cells.insert(cell);
} else {
delete cell;
}
}
void RTLIL::Module::remove(RTLIL::Process *process)
@ -2773,7 +2941,7 @@ RTLIL::IdString RTLIL::Module::uniquify(RTLIL::IdString name, int &index)
}
while (1) {
RTLIL::IdString new_name = stringf("%s_%d", name.c_str(), index);
RTLIL::IdString new_name = stringf("%s_%d", name, index);
if (count_id(new_name) == 0)
return new_name;
index++;
@ -2864,6 +3032,14 @@ void RTLIL::Module::fixup_ports()
std::sort(all_ports.begin(), all_ports.end(), fixup_ports_compare);
if (design && design->flagBufferedNormalized) {
for (auto &w : wires_)
if (w.second->driverCell_ && w.second->driverCell_->type == ID($input_port))
buf_norm_wire_queue.insert(w.second);
buf_norm_wire_queue.insert(all_ports.begin(), all_ports.end());
}
ports.clear();
for (size_t i = 0; i < all_ports.size(); i++) {
ports.push_back(all_ports[i]->name);
@ -4008,188 +4184,7 @@ bool RTLIL::Cell::hasPort(const RTLIL::IdString& portname) const
return connections_.count(portname) != 0;
}
void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
{
RTLIL::SigSpec signal;
auto conn_it = connections_.find(portname);
if (conn_it != connections_.end())
{
for (auto mon : module->monitors)
mon->notify_connect(this, conn_it->first, conn_it->second, signal);
if (module->design)
for (auto mon : module->design->monitors)
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_backtrace("-X- ", yosys_xtrace-1);
}
connections_.erase(conn_it);
}
}
void RTLIL::Design::bufNormalize(bool enable)
{
if (!enable)
{
if (!flagBufferedNormalized)
return;
for (auto module : modules()) {
module->bufNormQueue.clear();
for (auto wire : module->wires()) {
wire->driverCell_ = nullptr;
wire->driverPort_ = IdString();
}
}
flagBufferedNormalized = false;
return;
}
if (!flagBufferedNormalized)
{
for (auto module : modules())
{
for (auto cell : module->cells())
for (auto &conn : cell->connections()) {
if (!cell->output(conn.first) || GetSize(conn.second) == 0)
continue;
if (conn.second.is_wire()) {
Wire *wire = conn.second.as_wire();
log_assert(wire->driverCell_ == nullptr);
wire->driverCell_ = cell;
wire->driverPort_ = conn.first;
} else {
pair<RTLIL::Cell*, RTLIL::IdString> key(cell, conn.first);
module->bufNormQueue.insert(key);
}
}
}
flagBufferedNormalized = true;
}
for (auto module : modules())
module->bufNormalize();
}
void RTLIL::Module::bufNormalize()
{
if (!design->flagBufferedNormalized)
return;
while (GetSize(bufNormQueue) || !connections_.empty())
{
pool<pair<RTLIL::Cell*, RTLIL::IdString>> queue;
bufNormQueue.swap(queue);
pool<Wire*> outWires;
for (auto &conn : connections())
for (auto &chunk : conn.first.chunks())
if (chunk.wire) outWires.insert(chunk.wire);
SigMap sigmap(this);
new_connections({});
for (auto &key : queue)
{
Cell *cell = key.first;
const IdString &portname = key.second;
const SigSpec &sig = cell->getPort(portname);
if (GetSize(sig) == 0) continue;
if (sig.is_wire()) {
Wire *wire = sig.as_wire();
if (wire->driverCell_) {
log_error("Conflict between %s %s in module %s\n",
log_id(cell), log_id(wire->driverCell_), log_id(this));
}
log_assert(wire->driverCell_ == nullptr);
wire->driverCell_ = cell;
wire->driverPort_ = portname;
continue;
}
for (auto &chunk : sig.chunks())
if (chunk.wire) outWires.insert(chunk.wire);
Wire *wire = addWire(NEW_ID, GetSize(sig));
sigmap.add(sig, wire);
cell->setPort(portname, wire);
// FIXME: Move init attributes from old 'sig' to new 'wire'
}
for (auto wire : outWires)
{
SigSpec outsig = wire, insig = sigmap(wire);
for (int i = 0; i < GetSize(wire); i++)
if (insig[i] == outsig[i])
insig[i] = State::Sx;
addBuf(NEW_ID, insig, outsig);
}
}
}
void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal)
{
auto r = connections_.insert(portname);
auto conn_it = r.first;
if (!r.second && conn_it->second == signal)
return;
for (auto mon : module->monitors)
mon->notify_connect(this, conn_it->first, conn_it->second, signal);
if (module->design)
for (auto mon : module->design->monitors)
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_backtrace("-X- ", yosys_xtrace-1);
}
while (module->design && module->design->flagBufferedNormalized && output(portname))
{
pair<RTLIL::Cell*, RTLIL::IdString> key(this, portname);
if (conn_it->second.is_wire()) {
Wire *w = conn_it->second.as_wire();
if (w->driverCell_ == this && w->driverPort_ == portname) {
w->driverCell_ = nullptr;
w->driverPort_ = IdString();
}
}
if (GetSize(signal) == 0) {
module->bufNormQueue.erase(key);
break;
}
if (!signal.is_wire()) {
module->bufNormQueue.insert(key);
break;
}
Wire *w = signal.as_wire();
if (w->driverCell_ != nullptr) {
pair<RTLIL::Cell*, RTLIL::IdString> other_key(w->driverCell_, w->driverPort_);
module->bufNormQueue.insert(other_key);
}
w->driverCell_ = this;
w->driverPort_ = portname;
module->bufNormQueue.erase(key);
break;
}
conn_it->second = std::move(signal);
}
// bufnorm
const RTLIL::SigSpec &RTLIL::Cell::getPort(const RTLIL::IdString& portname) const
{
@ -4234,6 +4229,22 @@ bool RTLIL::Cell::output(const RTLIL::IdString& portname) const
return false;
}
RTLIL::PortDir RTLIL::Cell::port_dir(const RTLIL::IdString& portname) const
{
if (yosys_celltypes.cell_known(type))
return yosys_celltypes.cell_port_dir(type, portname);
if (module && module->design) {
RTLIL::Module *m = module->design->module(type);
if (m == nullptr)
return PortDir::PD_UNKNOWN;
RTLIL::Wire *w = m->wire(portname);
if (w == nullptr)
return PortDir::PD_UNKNOWN;
return PortDir(w->port_input + w->port_output * 2);
}
return PortDir::PD_UNKNOWN;
}
bool RTLIL::Cell::hasParam(const RTLIL::IdString& paramname) const
{
return parameters.count(paramname) != 0;
@ -4359,6 +4370,10 @@ bool RTLIL::Cell::is_mem_cell() const
return type.in(ID($mem), ID($mem_v2)) || has_memid();
}
bool RTLIL::Cell::is_builtin_ff() const {
return builtin_ff_cell_types_internal().count(type) > 0;
}
RTLIL::SigChunk::SigChunk(const RTLIL::SigBit &bit)
{
wire = bit.wire;
@ -4391,7 +4406,7 @@ RTLIL::SigChunk RTLIL::SigChunk::extract(int offset, int length) const
RTLIL::SigBit RTLIL::SigChunk::operator[](int offset) const
{
log_assert(offset >= 0);
log_assert(offset <= width);
log_assert(offset < width);
RTLIL::SigBit ret;
if (wire) {
ret.wire = wire;
@ -5372,6 +5387,15 @@ bool RTLIL::SigSpec::is_chunk() const
return GetSize(chunks_) == 1;
}
bool RTLIL::SigSpec::known_driver() const
{
pack();
for (auto &chunk : chunks_)
if (chunk.is_wire() && !chunk.wire->known_driver())
return false;
return true;
}
bool RTLIL::SigSpec::is_fully_const() const
{
cover("kernel.rtlil.sigspec.is_fully_const");
@ -5454,6 +5478,18 @@ bool RTLIL::SigSpec::has_const() const
return false;
}
bool RTLIL::SigSpec::has_const(State state) const
{
cover("kernel.rtlil.sigspec.has_const");
pack();
for (auto it = chunks_.begin(); it != chunks_.end(); it++)
if (it->width > 0 && it->wire == NULL && std::find(it->data.begin(), it->data.end(), state) != it->data.end())
return true;
return false;
}
bool RTLIL::SigSpec::has_marked_bits() const
{
cover("kernel.rtlil.sigspec.has_marked_bits");
@ -5836,7 +5872,11 @@ bool RTLIL::SigSpec::parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, R
}
}
return parse(sig, module, str);
if (!parse(sig, module, str))
return false;
if (sig.width_ > lhs.width_)
sig.remove(lhs.width_, sig.width_ - lhs.width_);
return true;
}
RTLIL::CaseRule::~CaseRule()
@ -5855,6 +5895,7 @@ RTLIL::CaseRule *RTLIL::CaseRule::clone() const
RTLIL::CaseRule *new_caserule = new RTLIL::CaseRule;
new_caserule->compare = compare;
new_caserule->actions = actions;
new_caserule->attributes = attributes;
for (auto &it : switches)
new_caserule->switches.push_back(it->clone());
return new_caserule;

View file

@ -83,6 +83,21 @@ namespace RTLIL
SB_EXCL_BB_CMDERR = 15 // call log_cmd_error on black boxed module
};
enum class StaticId : short {
STATIC_ID_BEGIN = 0,
#define X(N) N,
#include "kernel/constids.inc"
#undef X
STATIC_ID_END,
};
enum PortDir : unsigned char {
PD_UNKNOWN = 0,
PD_INPUT = 1,
PD_OUTPUT = 2,
PD_INOUT = 3
};
struct Const;
struct AttrObject;
struct NamedObject;
@ -105,8 +120,19 @@ namespace RTLIL
struct Process;
struct Binding;
struct IdString;
struct StaticIdString;
typedef std::pair<SigSpec, SigSpec> SigSig;
struct StaticIdString {
constexpr StaticIdString(StaticId id, const IdString &id_str) : id_str(id_str), id(id) {}
constexpr inline operator const IdString &() const { return id_str; }
constexpr inline int index() const { return static_cast<short>(id); }
constexpr inline const IdString &id_string() const { return id_str; }
const IdString &id_str;
const StaticId id;
};
};
struct RTLIL::IdString
@ -127,7 +153,13 @@ struct RTLIL::IdString
static std::vector<char*> global_id_storage_;
static std::unordered_map<std::string_view, int> global_id_index_;
#ifndef YOSYS_NO_IDS_REFCNT
static std::vector<int> global_refcount_storage_;
// For prepopulated IdStrings, the refcount is meaningless since they
// are never freed even if the refcount is zero. For code efficiency
// we increment the refcount of prepopulated IdStrings like any other string,
// but we never decrement the refcount or check whether it's zero.
// So, make this unsigned because refcounts of preopulated IdStrings may overflow
// and overflow of signed integers is undefined behavior.
static std::vector<uint32_t> global_refcount_storage_;
static std::vector<int> global_free_idx_list_;
#endif
@ -144,7 +176,7 @@ struct RTLIL::IdString
if (global_id_storage_.at(idx) == nullptr)
log("#X# DB-DUMP index %d: FREE\n", idx);
else
log("#X# DB-DUMP index %d: '%s' (ref %d)\n", idx, global_id_storage_.at(idx), global_refcount_storage_.at(idx));
log("#X# DB-DUMP index %d: '%s' (ref %u)\n", idx, global_id_storage_.at(idx), global_refcount_storage_.at(idx));
}
#endif
}
@ -166,15 +198,13 @@ struct RTLIL::IdString
static inline int get_reference(int idx)
{
if (idx) {
#ifndef YOSYS_NO_IDS_REFCNT
global_refcount_storage_[idx]++;
global_refcount_storage_[idx]++;
#endif
#ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace)
log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
if (yosys_xtrace && idx >= static_cast<short>(StaticId::STATIC_ID_END))
log("#X# GET-BY-INDEX '%s' (index %d, refcount %u)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
#endif
}
return idx;
}
@ -182,9 +212,6 @@ struct RTLIL::IdString
{
log_assert(destruct_guard_ok);
if (!p[0])
return 0;
auto it = global_id_index_.find((char*)p);
if (it != global_id_index_.end()) {
#ifndef YOSYS_NO_IDS_REFCNT
@ -192,11 +219,16 @@ struct RTLIL::IdString
#endif
#ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace)
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second));
log("#X# GET-BY-NAME '%s' (index %d, refcount %u)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second));
#endif
return it->second;
}
ensure_prepopulated();
if (!p[0])
return 0;
log_assert(p[0] == '$' || p[0] == '\\');
log_assert(p[1] != 0);
for (const char *c = p; *c; c++)
@ -205,11 +237,6 @@ struct RTLIL::IdString
#ifndef YOSYS_NO_IDS_REFCNT
if (global_free_idx_list_.empty()) {
if (global_id_storage_.empty()) {
global_refcount_storage_.push_back(0);
global_id_storage_.push_back((char*)"");
global_id_index_[global_id_storage_.back()] = 0;
}
log_assert(global_id_storage_.size() < 0x40000000);
global_free_idx_list_.push_back(global_id_storage_.size());
global_id_storage_.push_back(nullptr);
@ -222,10 +249,6 @@ struct RTLIL::IdString
global_id_index_[global_id_storage_.at(idx)] = idx;
global_refcount_storage_.at(idx)++;
#else
if (global_id_storage_.empty()) {
global_id_storage_.push_back((char*)"");
global_id_index_[global_id_storage_.back()] = 0;
}
int idx = global_id_storage_.size();
global_id_storage_.push_back(strdup(p));
global_id_index_[global_id_storage_.back()] = idx;
@ -238,7 +261,7 @@ struct RTLIL::IdString
#ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace)
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
log("#X# GET-BY-NAME '%s' (index %d, refcount %u)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
#endif
#ifdef YOSYS_USE_STICKY_IDS
@ -258,21 +281,20 @@ struct RTLIL::IdString
{
// put_reference() may be called from destructors after the destructor of
// global_refcount_storage_ has been run. in this case we simply do nothing.
if (!destruct_guard_ok || !idx)
if (idx < static_cast<short>(StaticId::STATIC_ID_END) || !destruct_guard_ok)
return;
#ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace) {
log("#X# PUT '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
log("#X# PUT '%s' (index %d, refcount %u)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
}
#endif
int &refcount = global_refcount_storage_[idx];
uint32_t &refcount = global_refcount_storage_[idx];
if (--refcount > 0)
return;
log_assert(refcount == 0);
free_reference(idx);
}
static inline void free_reference(int idx)
@ -281,6 +303,7 @@ struct RTLIL::IdString
log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx);
log_backtrace("-X- ", yosys_xtrace-1);
}
log_assert(idx >= static_cast<short>(StaticId::STATIC_ID_END));
global_id_index_.erase(global_id_storage_.at(idx));
free(global_id_storage_.at(idx));
@ -300,6 +323,7 @@ struct RTLIL::IdString
inline IdString(const IdString &str) : index_(get_reference(str.index_)) { }
inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
inline IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
inline IdString(StaticId id) : index_(static_cast<short>(id)) {}
inline ~IdString() { put_reference(index_); }
inline void operator=(const IdString &rhs) {
@ -317,6 +341,8 @@ struct RTLIL::IdString
*this = id;
}
constexpr inline const IdString &id_string() const { return *this; }
inline const char *c_str() const {
return global_id_storage_.at(index_);
}
@ -331,6 +357,8 @@ struct RTLIL::IdString
inline bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
inline bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
inline bool operator==(const StaticIdString &rhs) const;
inline bool operator!=(const StaticIdString &rhs) const;
// The methods below are just convenience functions for better compatibility with std::string.
@ -411,17 +439,27 @@ struct RTLIL::IdString
// often one needs to check if a given IdString is part of a list (for example a list
// of cell types). the following functions helps with that.
template<typename... Args>
bool in(Args... args) const {
bool in(const Args &... args) const {
return (... || in(args));
}
bool in(const IdString &rhs) const { return *this == rhs; }
bool in(const StaticIdString &rhs) const { return *this == rhs; }
bool in(const char *rhs) const { return *this == rhs; }
bool in(const std::string &rhs) const { return *this == rhs; }
inline bool in(const pool<IdString> &rhs) const;
inline bool in(const pool<IdString> &&rhs) const;
bool isPublic() const { return begins_with("\\"); }
private:
static void prepopulate();
public:
static void ensure_prepopulated() {
if (global_id_index_.empty())
prepopulate();
}
};
namespace hashlib {
@ -430,10 +468,10 @@ namespace hashlib {
static inline bool cmp(const RTLIL::IdString &a, const RTLIL::IdString &b) {
return a == b;
}
[[nodiscard]] static inline Hasher hash(const RTLIL::IdString id) {
[[nodiscard]] static inline Hasher hash(const RTLIL::IdString &id) {
return id.hash_top();
}
[[nodiscard]] static inline Hasher hash_into(const RTLIL::IdString id, Hasher h) {
[[nodiscard]] static inline Hasher hash_into(const RTLIL::IdString &id, Hasher h) {
return id.hash_into(h);
}
};
@ -449,14 +487,88 @@ inline bool RTLIL::IdString::in(const pool<IdString> &rhs) const { return rhs.co
[[deprecated]]
inline bool RTLIL::IdString::in(const pool<IdString> &&rhs) const { return rhs.count(*this) != 0; }
inline bool RTLIL::IdString::operator==(const RTLIL::StaticIdString &rhs) const {
return index_ == rhs.index();
}
inline bool RTLIL::IdString::operator!=(const RTLIL::StaticIdString &rhs) const {
return index_ != rhs.index();
}
namespace RTLIL {
namespace ID {
#define X(_id) extern IdString _id;
namespace IDInternal {
#define X(_id) extern const IdString _id;
#include "kernel/constids.inc"
#undef X
};
}
namespace ID {
#define X(_id) constexpr StaticIdString _id(StaticId::_id, IDInternal::_id);
#include "kernel/constids.inc"
#undef X
}
}
struct IdTableEntry {
const std::string_view name;
const RTLIL::StaticIdString static_id;
};
constexpr IdTableEntry IdTable[] = {
#define X(_id) {#_id, ID::_id},
#include "kernel/constids.inc"
#undef X
};
constexpr int lookup_well_known_id(std::string_view name)
{
int low = 0;
int high = sizeof(IdTable) / sizeof(IdTable[0]);
while (high - low >= 2) {
int mid = (low + high) / 2;
if (name < IdTable[mid].name)
high = mid;
else
low = mid;
}
if (IdTable[low].name == name)
return low;
return -1;
}
// Create a statically allocated IdString object, using for example ID::A or ID($add).
//
// Recipe for Converting old code that is using conversion of strings like ID::A and
// "$add" for creating IdStrings: Run below SED command on the .cc file and then use for
// example "meld foo.cc foo.cc.orig" to manually compile errors, if necessary.
//
// sed -i.orig -r 's/"\\\\([a-zA-Z0-9_]+)"/ID(\1)/g; s/"(\$[a-zA-Z0-9_]+)"/ID(\1)/g;' <filename>
//
typedef const RTLIL::IdString &IDMacroHelperFunc();
template <int IdTableIndex> struct IDMacroHelper {
static constexpr RTLIL::StaticIdString eval(IDMacroHelperFunc) {
return IdTable[IdTableIndex].static_id;
}
};
template <> struct IDMacroHelper<-1> {
static constexpr const RTLIL::IdString &eval(IDMacroHelperFunc func) {
return func();
}
};
#define ID(_id) \
YOSYS_NAMESPACE_PREFIX IDMacroHelper< \
YOSYS_NAMESPACE_PREFIX lookup_well_known_id(#_id) \
>::eval([]() \
-> const YOSYS_NAMESPACE_PREFIX RTLIL::IdString & { \
const char *p = "\\" #_id, *q = p[1] == '$' ? p+1 : p; \
static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id(q); \
return id; \
})
namespace RTLIL {
extern dict<std::string, std::string> constpad;
[[deprecated("Call cell->is_builtin_ff() instead")]]
const pool<IdString> &builtin_ff_cell_types();
static inline std::string escape_id(const std::string &str) {
@ -723,38 +835,61 @@ private:
using bitvectype = std::vector<RTLIL::State>;
enum class backing_tag: bool { bits, string };
// Do not access the union or tag even in Const methods unless necessary
mutable backing_tag tag;
backing_tag tag;
union {
mutable bitvectype bits_;
mutable std::string str_;
bitvectype bits_;
std::string str_;
};
// Use these private utilities instead
bool is_bits() const { return tag == backing_tag::bits; }
bool is_str() const { return tag == backing_tag::string; }
bitvectype* get_if_bits() const { return is_bits() ? &bits_ : NULL; }
std::string* get_if_str() const { return is_str() ? &str_ : NULL; }
bitvectype* get_if_bits() { return is_bits() ? &bits_ : NULL; }
std::string* get_if_str() { return is_str() ? &str_ : NULL; }
const bitvectype* get_if_bits() const { return is_bits() ? &bits_ : NULL; }
const std::string* get_if_str() const { return is_str() ? &str_ : NULL; }
bitvectype& get_bits();
std::string& get_str();
const bitvectype& get_bits() const;
const std::string& get_str() const;
std::vector<RTLIL::State>& bits_internal();
void bitvectorize_internal();
bitvectype& get_bits() const;
std::string& get_str() const;
public:
Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector<RTLIL::State>()) {}
Const(const std::string &str);
Const(long long val, int width = 32);
Const(long long val); // default width is 32
Const(long long val, int width);
Const(RTLIL::State bit, int width = 1);
Const(const std::vector<RTLIL::State> &bits) : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(bits) {}
Const(std::vector<RTLIL::State> bits) : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::move(bits)) {}
Const(const std::vector<bool> &bits);
Const(const RTLIL::Const &other);
Const(RTLIL::Const &&other);
RTLIL::Const &operator =(const RTLIL::Const &other);
~Const();
struct Builder
{
Builder() {}
Builder(int expected_width) { bits.reserve(expected_width); }
void push_back(RTLIL::State b) { bits.push_back(b); }
int size() const { return static_cast<int>(bits.size()); }
Const build() { return Const(std::move(bits)); }
private:
std::vector<RTLIL::State> bits;
};
bool operator <(const RTLIL::Const &other) const;
bool operator ==(const RTLIL::Const &other) const;
bool operator !=(const RTLIL::Const &other) const;
std::vector<RTLIL::State>& bits();
[[deprecated("Don't use direct access to the internal std::vector<State>, that's an implementation detail.")]]
std::vector<RTLIL::State>& bits() { return bits_internal(); }
[[deprecated("Don't call bitvectorize() directly, it's an implementation detail.")]]
void bitvectorize() const { const_cast<Const*>(this)->bitvectorize_internal(); }
bool as_bool() const;
// Convert the constant value to a C++ int.
@ -783,37 +918,42 @@ public:
std::string decode_string() const;
int size() const;
bool empty() const;
void bitvectorize() const;
void append(const RTLIL::Const &other);
void set(int i, RTLIL::State state) {
bits_internal()[i] = state;
}
void resize(int size, RTLIL::State fill) {
bits_internal().resize(size, fill);
}
class const_iterator {
private:
const Const& parent;
const Const* parent;
size_t idx;
public:
using iterator_category = std::input_iterator_tag;
using iterator_category = std::bidirectional_iterator_tag;
using value_type = State;
using difference_type = std::ptrdiff_t;
using pointer = const State*;
using reference = const State&;
const_iterator(const Const& c, size_t i) : parent(c), idx(i) {}
const_iterator(const Const& c, size_t i) : parent(&c), idx(i) {}
State operator*() const;
const_iterator& operator++() { ++idx; return *this; }
const_iterator& operator--() { --idx; return *this; }
const_iterator& operator++(int) { ++idx; return *this; }
const_iterator& operator--(int) { --idx; return *this; }
const_iterator operator++(int) { const_iterator result(*this); ++idx; return result; }
const_iterator operator--(int) { const_iterator result(*this); --idx; return result; }
const_iterator& operator+=(int i) { idx += i; return *this; }
const_iterator operator+(int add) {
return const_iterator(parent, idx + add);
return const_iterator(*parent, idx + add);
}
const_iterator operator-(int sub) {
return const_iterator(parent, idx - sub);
return const_iterator(*parent, idx - sub);
}
int operator-(const const_iterator& other) {
return idx - other.idx;
@ -828,12 +968,69 @@ public:
}
};
class iterator {
private:
Const* parent;
size_t idx;
public:
class proxy {
private:
Const* parent;
size_t idx;
public:
proxy(Const* parent, size_t idx) : parent(parent), idx(idx) {}
operator State() const { return (*parent)[idx]; }
proxy& operator=(State s) { parent->set(idx, s); return *this; }
proxy& operator=(const proxy& other) { parent->set(idx, (*other.parent)[other.idx]); return *this; }
};
using iterator_category = std::bidirectional_iterator_tag;
using value_type = State;
using difference_type = std::ptrdiff_t;
using pointer = proxy*;
using reference = proxy;
iterator(Const& c, size_t i) : parent(&c), idx(i) {}
proxy operator*() const { return proxy(parent, idx); }
iterator& operator++() { ++idx; return *this; }
iterator& operator--() { --idx; return *this; }
iterator operator++(int) { iterator result(*this); ++idx; return result; }
iterator operator--(int) { iterator result(*this); --idx; return result; }
iterator& operator+=(int i) { idx += i; return *this; }
iterator operator+(int add) {
return iterator(*parent, idx + add);
}
iterator operator-(int sub) {
return iterator(*parent, idx - sub);
}
int operator-(const iterator& other) {
return idx - other.idx;
}
bool operator==(const iterator& other) const {
return idx == other.idx;
}
bool operator!=(const iterator& other) const {
return !(*this == other);
}
};
const_iterator begin() const {
return const_iterator(*this, 0);
}
const_iterator end() const {
return const_iterator(*this, size());
}
iterator begin() {
return iterator(*this, 0);
}
iterator end() {
return iterator(*this, size());
}
State back() const {
return *(end() - 1);
}
@ -865,20 +1062,14 @@ public:
std::optional<int> as_int_compress(bool is_signed) const;
void extu(int width) {
bits().resize(width, RTLIL::State::S0);
resize(width, RTLIL::State::S0);
}
void exts(int width) {
bitvectype& bv = bits();
bv.resize(width, bv.empty() ? RTLIL::State::Sx : bv.back());
resize(width, empty() ? RTLIL::State::Sx : back());
}
[[nodiscard]] Hasher hash_into(Hasher h) const {
h.eat(size());
for (auto b : *this)
h.eat(b);
return h;
}
[[nodiscard]] Hasher hash_into(Hasher h) const;
};
struct RTLIL::AttrObject
@ -933,7 +1124,8 @@ struct RTLIL::SigChunk
SigChunk(RTLIL::Wire *wire) : wire(wire), width(GetSize(wire)), offset(0) {}
SigChunk(RTLIL::Wire *wire, int offset, int width = 1) : wire(wire), width(width), offset(offset) {}
SigChunk(const std::string &str) : SigChunk(RTLIL::Const(str)) {}
SigChunk(int val, int width = 32) : SigChunk(RTLIL::Const(val, width)) {}
SigChunk(int val) /*default width 32*/ : SigChunk(RTLIL::Const(val)) {}
SigChunk(int val, int width) : SigChunk(RTLIL::Const(val, width)) {}
SigChunk(RTLIL::State bit, int width = 1) : SigChunk(RTLIL::Const(bit, width)) {}
SigChunk(const RTLIL::SigBit &bit);
@ -1052,7 +1244,8 @@ private:
public:
SigSpec() : width_(0), hash_(0) {}
SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
SigSpec(const SigSpec &value) = default;
SigSpec(SigSpec &&value) = default;
SigSpec(const RTLIL::Const &value);
SigSpec(RTLIL::Const &&value);
SigSpec(const RTLIL::SigChunk &chunk);
@ -1069,6 +1262,9 @@ public:
SigSpec(const std::set<RTLIL::SigBit> &bits);
explicit SigSpec(bool bit);
SigSpec &operator=(const SigSpec &rhs) = default;
SigSpec &operator=(SigSpec &&rhs) = default;
inline const std::vector<RTLIL::SigChunk> &chunks() const { pack(); return chunks_; }
inline const std::vector<RTLIL::SigBit> &bits() const { inline_unpack(); return bits_; }
@ -1142,12 +1338,15 @@ public:
bool is_chunk() const;
inline bool is_bit() const { return width_ == 1; }
bool known_driver() const;
bool is_fully_const() const;
bool is_fully_zero() const;
bool is_fully_ones() const;
bool is_fully_def() const;
bool is_fully_undef() const;
bool has_const() const;
bool has_const(State state) const;
bool has_marked_bits() const;
bool is_onehot(int *pos = nullptr) const;
@ -1539,7 +1738,11 @@ public:
std::vector<RTLIL::IdString> ports;
void fixup_ports();
pool<pair<RTLIL::Cell*, RTLIL::IdString>> bufNormQueue;
pool<RTLIL::Cell *> buf_norm_cell_queue;
pool<pair<RTLIL::Cell *, RTLIL::IdString>> buf_norm_cell_port_queue;
pool<RTLIL::Wire *> buf_norm_wire_queue;
pool<RTLIL::Cell *> pending_deleted_cells;
dict<RTLIL::Wire *, pool<RTLIL::Cell *>> buf_norm_connect_index;
void bufNormalize();
template<typename T> void rewrite_sigspecs(T &functor);
@ -1872,6 +2075,8 @@ public:
int width, start_offset, port_id;
bool port_input, port_output, upto, is_signed;
bool known_driver() const { return driverCell_ != nullptr; }
RTLIL::Cell *driverCell() const { log_assert(driverCell_); return driverCell_; };
RTLIL::IdString driverPort() const { log_assert(driverCell_); return driverPort_; };
@ -1943,6 +2148,7 @@ public:
bool known() const;
bool input(const RTLIL::IdString &portname) const;
bool output(const RTLIL::IdString &portname) const;
PortDir port_dir(const RTLIL::IdString &portname) const;
// access cell parameters
bool hasParam(const RTLIL::IdString &paramname) const;
@ -1968,6 +2174,7 @@ public:
bool has_memid() const;
bool is_mem_cell() const;
bool is_builtin_ff() const;
};
struct RTLIL::CaseRule : public RTLIL::AttrObject

673
kernel/rtlil_bufnorm.cc Normal file
View file

@ -0,0 +1,673 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/modtools.h"
#include <string.h>
#include <algorithm>
#include <optional>
YOSYS_NAMESPACE_BEGIN
void RTLIL::Design::bufNormalize(bool enable)
{
if (!enable)
{
if (!flagBufferedNormalized)
return;
for (auto module : modules()) {
module->buf_norm_cell_queue.clear();
module->buf_norm_wire_queue.clear();
module->buf_norm_cell_port_queue.clear();
for (auto wire : module->wires()) {
wire->driverCell_ = nullptr;
wire->driverPort_ = IdString();
}
module->buf_norm_connect_index.clear();
}
flagBufferedNormalized = false;
return;
}
if (!flagBufferedNormalized)
{
for (auto module : modules())
{
// When entering buf normalized mode, we need the first module-level bufNormalize
// call to know about all drivers, about all module ports (whether represented by
// a cell or not) and about all used but undriven wires (whether represented by a
// cell or not). We ensure this by enqueing all cell output ports and all wires.
for (auto cell : module->cells())
for (auto &conn : cell->connections()) {
if (GetSize(conn.second) == 0 || (cell->port_dir(conn.first) != RTLIL::PD_OUTPUT && cell->port_dir(conn.first) != RTLIL::PD_INOUT))
continue;
module->buf_norm_cell_queue.insert(cell);
module->buf_norm_cell_port_queue.emplace(cell, conn.first);
}
for (auto wire : module->wires())
module->buf_norm_wire_queue.insert(wire);
}
flagBufferedNormalized = true;
}
for (auto module : modules())
module->bufNormalize();
}
struct bit_drive_data_t {
int drivers = 0;
int inout = 0;
int users = 0;
};
typedef ModWalker::PortBit PortBit;
void RTLIL::Module::bufNormalize()
{
// Since this is kernel code, we only log with yosys_xtrace set to not get
// in the way when using `debug` to debug specific passes.q
#define xlog(...) do { if (yosys_xtrace) log("#X [bufnorm] " __VA_ARGS__); } while (0)
if (!design->flagBufferedNormalized)
return;
if (!buf_norm_cell_queue.empty() || !buf_norm_wire_queue.empty() || !connections_.empty())
{
// Ensure that every enqueued input port is represented by a cell
for (auto wire : buf_norm_wire_queue) {
if (wire->port_input && !wire->port_output) {
if (wire->driverCell_ != nullptr && wire->driverCell_->type != ID($input_port)) {
wire->driverCell_ = nullptr;
wire->driverPort_.clear();
}
if (wire->driverCell_ == nullptr) {
Cell *input_port_cell = addCell(NEW_ID, ID($input_port));
input_port_cell->setParam(ID::WIDTH, GetSize(wire));
input_port_cell->setPort(ID::Y, wire); // this hits the fast path that doesn't mutate the queues
}
}
}
// Next we will temporarily undo buf normalization locally for
// everything enqueued. This means we will turn $buf and $connect back
// into connections. When doing this we also need to enqueue the other
// end of $buf and $connect cells, so we use a queue and do this until
// reaching a fixed point.
// While doing this, we will also discover all drivers fully connected
// to enqueued wires. We keep track of which wires are driven by a
// unique and full cell ports (in which case the wire can stay
// connected to the port) and which cell ports will need to be
// reconnected to a fresh intermediate wire to re-normalize the module.
idict<Wire *> wire_queue_entries; // Ordered queue of wires to process
int wire_queue_pos = 0; // Index up to which we processed the wires
// Wires with their unique driving cell port. We pick the first driver
// we encounter, with the exception that we ensure that a module input
// port can only get $input_port drivers and that $input_port drivers
// cannot drive any other modules. If we reject an $input_port driver
// because it's not driving an input port or because there already is
// another $input_port driver for the same port, we also delete that
// $input_port cell.
dict<Wire *, std::pair<Cell *, IdString>> direct_driven_wires;
// Set of cell ports that need a fresh intermediate wire. These are all
// cell ports that drive non-full-wire sigspecs, cell ports driving
// module input ports, and cell ports driving wires that are already
// driven.
pool<std::pair<Cell *, IdString>> pending_ports;
// This helper will be called for every output/inout cell port that is
// 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));
// An empty cell type means the cell got removed
if (cell->type.empty())
return;
SigSpec const &sig = cell->getPort(port);
// Make sure all wires of the cell port are enqueued, ensuring we
// detect other connected drivers (output and inout).
for (auto chunk : sig.chunks())
if (chunk.is_wire())
wire_queue_entries(chunk.wire);
if (cell->type == ID($buf) && cell->attributes.empty() && !cell->name.isPublic()) {
// For a plain `$buf` cell, we enqueue all wires on its input
// side, bypass it using module level connections (skipping 'z
// bits) and then remove the cell. Eventually the module level
// connections will turn back into `$buf` and `$connect` cells,
// but since we also need to handle externally added module
// level connections, turning everything into connections first
// simplifies the logic for doing so.
// TODO: We could defer removing the $buf cells here, and
// re-use them in case we would create a new identical cell
// later.
log_assert(port == ID::Y);
SigSpec sig_a = cell->getPort(ID::A);
SigSpec sig_y = sig;
for (auto const &s : {sig_a, sig})
for (auto const &chunk : s.chunks())
if (chunk.wire)
wire_queue_entries(chunk.wire);
if (sig_a.has_const(State::Sz)) {
SigSpec new_a;
SigSpec new_y;
for (int i = 0; i < GetSize(sig_a); ++i) {
SigBit b = sig_a[i];
if (b == State::Sz)
continue;
new_a.append(b);
new_y.append(sig_y[i]);
}
sig_a = std::move(new_a);
sig_y = std::move(new_y);
}
if (!sig_y.empty())
connect(sig_y, sig_a);
remove(cell);
log_assert(GetSize(buf_norm_wire_queue) <= 1);
buf_norm_wire_queue.clear();
return;
} else if (cell->type == ID($input_port)) {
log_assert(port == ID::Y);
if (sig.is_wire()) {
Wire *w = sig.as_wire();
if (w->port_input && !w->port_output) {
// An $input_port cell can only drive a full wire module input port
auto [found, inserted] = direct_driven_wires.emplace(w, {cell, port});
if (!inserted || (found->second.first == cell && found->second.second == port))
return;
}
}
// If an `$input_port` cell isn't driving a full
// input port wire, we remove it since the wires are still the
// canonical source of module ports
buf_norm_cell_queue.insert(cell);
remove(cell);
log_assert(GetSize(buf_norm_wire_queue) <= 1);
buf_norm_wire_queue.clear();
return;
}
if (sig.is_wire()) {
Wire *w = sig.as_wire();
if (!w->port_input || w->port_output) {
// If the full cell port is connected to a full non-input-port wire, pick it as driver
auto [found, inserted] = direct_driven_wires.emplace(w, {cell, port});
if (inserted || (found->second.first == cell && found->second.second == port))
return;
}
}
// Adds this port to the ports that need a fresh intermediate wire.
// For full wires uniquely driven by a full output port, this isn't
// reached due to the `return` above.
pending_ports.emplace(cell, port);
};
// We enqueue all enqueued wires for `$buf`/`$connect` processing (clearing the module level queue).
for (auto wire : buf_norm_wire_queue)
wire_queue_entries(wire);
buf_norm_wire_queue.clear();
// Only after clearing the `buf_norm_wire_queue` are we allowed to call
// enqueue_cell_port, since we're using assertions to check against
// unintended wires being enqueued into `buf_norm_wire_queue` that
// would prevent us from restoring the bufnorm invariants in a single
// pass.
// We process all explicitly enqueued cell ports (clearing the module level queue).
for (auto const &[cell, port_name] : buf_norm_cell_port_queue)
enqueue_cell_port(cell, port_name);
buf_norm_cell_port_queue.clear();
// We also enqueue all wires that saw newly added module level connections.
for (auto &[a, b] : connections_)
for (auto &sig : {a, b})
for (auto const &chunk : sig.chunks())
if (chunk.wire)
wire_queue_entries(chunk.wire);
// We then process all wires by processing known driving cell ports
// (previously buf normalized) and following all `$connect` cells (that
// have a dedicated module level index while the design is in buf
// 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));
if (wire->driverCell_) {
Cell *cell = wire->driverCell_;
IdString port = wire->driverPort_;
enqueue_cell_port(cell, port);
}
while (true) {
auto found = buf_norm_connect_index.find(wire);
if (found == buf_norm_connect_index.end())
break;
while (!found->second.empty()) {
Cell *connect_cell = *found->second.begin();
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));
for (auto &side : {sig_a, sig_b})
for (auto chunk : side.chunks())
if (chunk.wire)
wire_queue_entries(chunk.wire);
connect(sig_a, sig_b);
buf_norm_cell_queue.insert(connect_cell);
remove(connect_cell);
log_assert(GetSize(buf_norm_wire_queue) <= 2);
buf_norm_wire_queue.clear();
}
}
}
// At this point we know all cell ports and wires that need to be
// re-normalized and know their connectivity is represented by module
// level connections.
// As a first step for re-normalization we add all require intermediate
// wires for cell output and inout ports.
for (auto &[cell, port] : pending_ports) {
log_assert(cell->type != ID($input_port));
log_assert(!cell->type.empty());
log_assert(!pending_deleted_cells.count(cell));
SigSpec const &sig = cell->getPort(port);
Wire *w = addWire(NEW_ID, GetSize(sig));
// We update the module level connections, `direct_driven_wires`
// and `direct_driven_wires_conflicts` in such a way that they
// correspond to what you would get if the intermediate wires had
// been in place from the beginning.
connect(sig, w);
direct_driven_wires.emplace(w, {cell, port});
cell->setPort(port, w); // Hits the fast path that doesn't enqueue w
wire_queue_entries(w); // Needed so we pick up the sig <-> w connection
}
// At this point we're done with creating wires and know which ones are
// fully driven by full output ports of existing cells.
// First we clear the bufnorm data for all processed wires, all of
// these will be reassigned later, but we use `driverCell_ == nullptr`
// to keep track of the wires that we still have to update.
for (auto wire : wire_queue_entries) {
wire->driverCell_ = nullptr;
wire->driverPort_.clear();
}
// For the unique driving cell ports fully connected to a full wire, we
// can update the bufnorm data right away. For all other wires we will
// have to create new `$buf` cells.
for (auto const &[wire, cellport] : direct_driven_wires) {
wire->driverCell_ = cellport.first;
wire->driverPort_ = cellport.second;
}
// To create fresh `$buf` cells for all remaining wires, we need to
// process the module level connectivity to figure out what the input
// of those `$buf` cells should be and to figure out whether we need
// any `$connect` cells to represent bidirectional inout connections
// (or driver conflicts).
if (yosys_xtrace)
for (auto const &[lhs, rhs] : connections_)
xlog("connection %s <-> %s\n", log_signal(lhs), log_signal(rhs));
// We transfer the connectivity into a sigmap and then clear the module
// level connections. This forgets about the structure of module level
// connections, but bufnorm only guarantees that the connectivity as
// maintained by a `SigMap` is preserved.
SigMap sigmap(this);
new_connections({});
// We pick SigMap representatives by prioritizing input ports over
// driven wires over other/unknown wires.
for (bool input_ports : {false, true}) {
for (auto const &[wire, cellport] : direct_driven_wires) {
if ((wire->port_input && !wire->port_output) == input_ports) {
for (int i = 0; i != GetSize(wire); ++i) {
SigBit driver = SigBit(wire, i);
sigmap.database.promote(driver);
}
}
}
}
// All three pool<SigBit> below are in terms of sigmapped bits
// Bits that are known to have a unique driver that is an unconditional driver or one or more inout drivers
pool<SigBit> driven;
// Bits that have multiple unconditional drivers, this forces the use of `$connect`
pool<SigBit> conflicted;
// Bits that are driven by an inout driver
pool<SigBit> weakly_driven;
for (auto const &[wire, cellport] : direct_driven_wires) {
auto const &[cell, port] = cellport;
for (int i = 0; i != GetSize(wire); ++i) {
SigBit driver = sigmap(SigBit(wire, i));
if (cell->type == ID($tribuf) || cell->port_dir(port) == RTLIL::PD_INOUT) {
// We add inout drivers to `driven` in a separate loop below
weakly_driven.insert(driver);
} else {
// We remove driver conflicts from `driven` in a separate loop below
bool inserted = driven.insert(driver).second;
if (!inserted)
conflicted.insert(driver);
}
}
}
// If a wire has one or more inout drivers and an unconditional driver, that's still a conflict
for (auto driver : weakly_driven)
if (!driven.insert(driver).second)
conflicted.insert(driver);
// This only leaves the drivers matching `driven`'s definition above
for (auto driver : conflicted)
driven.erase(driver);
// Having picked representatives and checked whether they are unique
// drivers, we can turn the connecitivty of our sigmap back into $buf
// and $connect cells.
// Module level bitwise connections not representable by `$buf` cells
pool<pair<SigBit, SigBit>> undirected_connections;
// Starts out empty but is updated with the connectivity realized by freshly added `$buf` cells
SigMap buf_connected;
// For every enqueued wire, we compute a SigSpec of representative
// drivers. If there are any bits without a unique driver we represent
// that with `Sz`. If there are multiple drivers for a net, they become
// connected via `$connect` cells but every wire of the net has the
// corresponding bit still driven by a buffered `Sz`.
for (auto wire : wire_queue_entries) {
SigSpec wire_drivers;
for (int i = 0; i < GetSize(wire); ++i) {
SigBit bit(wire, i);
SigBit mapped = sigmap(bit);
xlog("bit %s -> mapped %s\n", log_signal(bit), log_signal(mapped));
buf_connected.apply(bit);
buf_connected.add(bit, mapped);
buf_connected.database.promote(mapped);
if (wire->driverCell_ == nullptr) {
if (!mapped.is_wire() || driven.count(mapped)) {
wire_drivers.append(mapped);
continue;
} else {
wire_drivers.append(State::Sz);
}
}
if (bit < mapped)
undirected_connections.emplace(bit, mapped);
else if (mapped < bit)
undirected_connections.emplace(mapped, bit);
}
if (wire->driverCell_ == nullptr) {
xlog("wire %s drivers %s\n", log_id(wire), log_signal(wire_drivers));
addBuf(NEW_ID, wire_drivers, wire);
}
}
// Finally we group the bitwise connections to emit word-level $connect cells
static auto sort_key = [](std::pair<SigBit, SigBit> const &p) {
int first_offset = p.first.is_wire() ? p.first.offset : 0;
int second_offset = p.second.is_wire() ? p.second.offset : 0;
return std::make_tuple(p.first.wire, p.second.wire, first_offset - second_offset, p);
};
undirected_connections.sort([](std::pair<SigBit, SigBit> const &p, std::pair<SigBit, SigBit> const &q) {
return sort_key(p) < sort_key(q);
});
SigSpec tmp_a, tmp_b;
for (auto &[bit_a, bit_b] : undirected_connections) {
tmp_a.append(bit_a);
tmp_b.append(bit_b);
}
xlog("LHS: %s\n", log_signal(tmp_a));
xlog("RHS: %s\n", log_signal(tmp_b));
SigSpec sig_a, sig_b;
SigBit next_a, next_b;
auto emit_connect_cell = [&]() {
if (sig_a.empty())
return;
xlog("connect %s <-> %s\n", log_signal(sig_a), log_signal(sig_b));
Cell *connect_cell = addCell(NEW_ID, ID($connect));
connect_cell->setParam(ID::WIDTH, GetSize(sig_a));
connect_cell->setPort(ID::A, sig_a);
connect_cell->setPort(ID::B, sig_b);
sig_a = SigSpec();
sig_b = SigSpec();
};
for (auto &[bit_a, bit_b] : undirected_connections) {
if (bit_a == bit_b)
continue;
if (bit_a != next_a || bit_b != next_b)
emit_connect_cell();
sig_a.append(bit_a);
sig_b.append(bit_b);
next_a = bit_a;
next_b = bit_b;
if (next_a.is_wire())
next_a.offset++;
if (next_b.is_wire())
next_b.offset++;
}
emit_connect_cell();
buf_norm_cell_queue.clear();
log_assert(buf_norm_cell_port_queue.empty());
log_assert(buf_norm_wire_queue.empty());
log_assert(connections_.empty());
}
for (auto cell : pending_deleted_cells) {
delete cell;
}
pending_deleted_cells.clear();
}
void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
{
RTLIL::SigSpec signal;
auto conn_it = connections_.find(portname);
if (conn_it != connections_.end())
{
for (auto mon : module->monitors)
mon->notify_connect(this, conn_it->first, conn_it->second, signal);
if (module->design)
for (auto mon : module->design->monitors)
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_backtrace("-X- ", yosys_xtrace-1);
}
if (module->design && module->design->flagBufferedNormalized) {
if (conn_it->second.is_wire()) {
Wire *w = conn_it->second.as_wire();
if (w->driverCell_ == this && w->driverPort_ == portname) {
w->driverCell_ = nullptr;
w->driverPort_ = IdString();
module->buf_norm_wire_queue.insert(w);
} else if (w->driverCell_) {
log_assert(w->driverCell_->getPort(w->driverPort_) == w);
}
}
if (type == ID($connect)) {
for (auto &[port, sig] : connections_) {
for (auto &chunk : sig.chunks()) {
if (!chunk.wire)
continue;
auto it = module->buf_norm_connect_index.find(chunk.wire);
if (it == module->buf_norm_connect_index.end())
continue;
it->second.erase(this);
if (it->second.empty())
module->buf_norm_connect_index.erase(it);
}
}
connections_.erase(conn_it);
for (auto &[port, sig] : connections_) {
for (auto &chunk : sig.chunks()) {
if (!chunk.wire)
continue;
module->buf_norm_connect_index[chunk.wire].insert(this);
}
}
return;
}
}
connections_.erase(conn_it);
}
}
void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal)
{
auto r = connections_.insert(portname);
auto conn_it = r.first;
if (!r.second && conn_it->second == signal)
return;
for (auto mon : module->monitors)
mon->notify_connect(this, conn_it->first, conn_it->second, signal);
if (module->design)
for (auto mon : module->design->monitors)
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_backtrace("-X- ", yosys_xtrace-1);
}
if (module->design && module->design->flagBufferedNormalized)
{
// We eagerly clear a driver that got disconnected by changing this port connection
if (conn_it->second.is_wire()) {
Wire *w = conn_it->second.as_wire();
if (w->driverCell_ == this && w->driverPort_ == portname) {
w->driverCell_ = nullptr;
w->driverPort_ = IdString();
module->buf_norm_wire_queue.insert(w);
}
}
auto dir = port_dir(portname);
// This is a fast path that handles connecting a full driverless wire to an output port,
// everything else is goes through the bufnorm queues and is handled during the next
// bufNormalize call
if ((dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) && signal.is_wire()) {
Wire *w = signal.as_wire();
if (w->driverCell_ == nullptr && (
(w->port_input && !w->port_output) == (type == ID($input_port)))) {
w->driverCell_ = this;
w->driverPort_ = portname;
conn_it->second = std::move(signal);
return;
}
}
if (dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) {
module->buf_norm_cell_queue.insert(this);
module->buf_norm_cell_port_queue.emplace(this, portname);
} else {
for (auto &chunk : signal.chunks())
if (chunk.wire != nullptr && chunk.wire->driverCell_ == nullptr)
module->buf_norm_wire_queue.insert(chunk.wire);
}
if (type == ID($connect)) {
for (auto &[port, sig] : connections_) {
for (auto &chunk : sig.chunks()) {
if (!chunk.wire)
continue;
auto it = module->buf_norm_connect_index.find(chunk.wire);
if (it == module->buf_norm_connect_index.end())
continue;
it->second.erase(this);
if (it->second.empty())
module->buf_norm_connect_index.erase(it);
}
}
conn_it->second = std::move(signal);
for (auto &[port, sig] : connections_) {
for (auto &chunk : sig.chunks()) {
if (!chunk.wire)
continue;
module->buf_norm_connect_index[chunk.wire].insert(this);
}
}
return;
}
}
conn_it->second = std::move(signal);
}
YOSYS_NAMESPACE_END

View file

@ -1202,7 +1202,7 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
return true;
}
if (timestep > 0 && (RTLIL::builtin_ff_cell_types().count(cell->type) || cell->type == ID($anyinit)))
if (timestep > 0 && (cell->is_builtin_ff() || cell->type == ID($anyinit)))
{
FfData ff(nullptr, cell);

View file

@ -103,7 +103,7 @@ struct SatGen
} else {
std::string wire_name = RTLIL::unescape_id(bit.wire->name);
std::string name = pf +
(bit.wire->width == 1 ? wire_name : stringf("%s [%d]", wire_name.c_str(), bit.offset));
(bit.wire->width == 1 ? wire_name : stringf("%s [%d]", wire_name, bit.offset));
vec.push_back(ez->frozen_literal(name));
imported_signals[pf][bit] = vec.back();
}

View file

@ -119,7 +119,7 @@ void SExprWriter::print(SExpr const &sexpr, bool close, bool indent_rest) {
_pending_nl = true;
}
}else
log_error("shouldn't happen: SExpr '%s' is neither an atom nor a list", sexpr.to_string().c_str());
log_error("shouldn't happen: SExpr '%s' is neither an atom nor a list", sexpr.to_string());
}
void SExprWriter::close(size_t n) {

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