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:
commit
99159e76e8
329 changed files with 7804 additions and 3722 deletions
2
.github/actions/setup-build-env/action.yml
vendored
2
.github/actions/setup-build-env/action.yml
vendored
|
|
@ -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'
|
||||
|
|
|
|||
16
.github/workflows/extra-builds.yml
vendored
16
.github/workflows/extra-builds.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
4
.github/workflows/prepare-docs.yml
vendored
4
.github/workflows/prepare-docs.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
54
.github/workflows/test-build.yml
vendored
54
.github/workflows/test-build.yml
vendored
|
|
@ -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]
|
||||
|
|
|
|||
20
.github/workflows/test-compile.yml
vendored
20
.github/workflows/test-compile.yml
vendored
|
|
@ -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
120
.github/workflows/test-sanitizers.yml
vendored
Normal 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
|
||||
23
.github/workflows/test-verific.yml
vendored
23
.github/workflows/test-verific.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
1
.github/workflows/update-flake-lock.yml
vendored
1
.github/workflows/update-flake-lock.yml
vendored
|
|
@ -6,6 +6,7 @@ on:
|
|||
|
||||
jobs:
|
||||
lockfile:
|
||||
if: github.repository == 'YosysHQ/Yosys'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
|
|
|||
8
.github/workflows/version.yml
vendored
8
.github/workflows/version.yml
vendored
|
|
@ -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 }}
|
||||
|
|
|
|||
1
.github/workflows/wheels.yml
vendored
1
.github/workflows/wheels.yml
vendored
|
|
@ -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
9
.gitignore
vendored
|
|
@ -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
|
||||
|
|
|
|||
1
Brewfile
1
Brewfile
|
|
@ -11,3 +11,4 @@ brew "bash"
|
|||
brew "boost-python3"
|
||||
brew "llvm@20"
|
||||
brew "lld"
|
||||
brew "googletest"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
21
Makefile
21
Makefile
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ struct JsonWriter
|
|||
bool first = true;
|
||||
for (auto ¶m : 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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>> ¶meters) {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ¶m : 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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ¯o_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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
31
kernel/ff.cc
31
kernel/ff.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
15
kernel/io.cc
15
kernel/io.cc
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
19
kernel/io.h
19
kernel/io.h
|
|
@ -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...);
|
||||
}
|
||||
|
|
|
|||
239
kernel/log.cc
239
kernel/log.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
133
kernel/log.h
133
kernel/log.h
|
|
@ -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
86
kernel/log_compat.cc
Normal 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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
515
kernel/rtlil.cc
515
kernel/rtlil.cc
|
|
@ -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;
|
||||
|
|
|
|||
329
kernel/rtlil.h
329
kernel/rtlil.h
|
|
@ -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 ¶mname) 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
673
kernel/rtlil_bufnorm.cc
Normal 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
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue